/* ! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! ! ! Maintainers : support@fluidnumerics.com ! Official Repository : https://github.com/FluidNumerics/self/ ! ! Copyright © 2024 Fluid Numerics LLC ! ! Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: ! ! 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. ! ! 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in ! the documentation and/or other materials provided with the distribution. ! ! 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from ! this software without specific prior written permission. ! ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ! HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ! LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ! THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ! THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! ! //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! */ #include "SELF_GPU_Macros.h" // Element-set interface traces (see SELF_SetInterface_3D_t.f90). // // The outbox and ghost buffers are (Np,Np,nvarMax,nFaces) with Np = N+1, column-major, // so node (i,j), variable v of face f (all 0-based) sits at // i + Np*(j + Np*(v + nvarMax*f)). // The faces of one set are f0 .. f0+nFaces-1; elems[f] and sides[f] are 1-based // element and side indices in that set's sub-mesh, whose traces have nel elements. // outbox(i,j,v,f) = trace(i,j,s,e,v): each face's own trace, unflipped __global__ void GatherSetInterfaceOutbox_kernel(real *outbox, real *trace, int *elems, int *sides, int f0, int nFaces, int nvar, int nvarMax, int N, int nel){ uint32_t idof = threadIdx.x + blockIdx.x*blockDim.x; uint32_t np = N+1; uint32_t total = nFaces*nvar*np*np; if(idof < total){ uint32_t i = idof % np; uint32_t j = (idof/np) % np; uint32_t v = (idof/(np*np)) % nvar; uint32_t f = f0 + idof/(np*np*nvar); uint32_t e = elems[f]-1; uint32_t s = sides[f]-1; outbox[i + np*(j + np*(v + nvarMax*f))] = trace[SCB_3D_INDEX(i,j,s,e,v,N,nel)]; } } // extBoundary(i,j,s,e,v) = ghost(i,j,v,f): the partner trace, already flipped on the host __global__ void FillSetInterfaceBoundary_kernel(real *extBoundary, real *ghost, int *elems, int *sides, int f0, int nFaces, int nvar, int nvarMax, int N, int nel){ uint32_t idof = threadIdx.x + blockIdx.x*blockDim.x; uint32_t np = N+1; uint32_t total = nFaces*nvar*np*np; if(idof < total){ uint32_t i = idof % np; uint32_t j = (idof/np) % np; uint32_t v = (idof/(np*np)) % nvar; uint32_t f = f0 + idof/(np*np*nvar); uint32_t e = elems[f]-1; uint32_t s = sides[f]-1; extBoundary[SCB_3D_INDEX(i,j,s,e,v,N,nel)] = ghost[i + np*(j + np*(v + nvarMax*f))]; } } extern "C" { void GatherSetInterfaceOutbox_gpu(real *outbox, real *trace, int *elems, int *sides, int f0, int nFaces, int nvar, int nvarMax, int N, int nel) { int threads_per_block = 256; int total = nFaces*nvar*(N+1)*(N+1); int nblocks_x = total/threads_per_block + 1; GatherSetInterfaceOutbox_kernel<<<dim3(nblocks_x,1,1), dim3(threads_per_block,1,1), 0, 0>>>( outbox, trace, elems, sides, f0, nFaces, nvar, nvarMax, N, nel); } void FillSetInterfaceBoundary_gpu(real *extBoundary, real *ghost, int *elems, int *sides, int f0, int nFaces, int nvar, int nvarMax, int N, int nel) { int threads_per_block = 256; int total = nFaces*nvar*(N+1)*(N+1); int nblocks_x = total/threads_per_block + 1; FillSetInterfaceBoundary_kernel<<<dim3(nblocks_x,1,1), dim3(threads_per_block,1,1), 0, 0>>>( extBoundary, ghost, elems, sides, f0, nFaces, nvar, nvarMax, N, nel); } }