/* $Header$ */ #include #include #include #include "cctk.h" #include "cctk_Parameters.h" #include "Slab.h" #include "periodic.h" static const char * restrict const rcsid = "$Header$"; CCTK_FILEVERSION(TAT_Periodic_periodic_c); int BndPeriodicVI (cGH const * restrict const cctkGH, int const * restrict const stencil, int const vi) { DECLARE_CCTK_PARAMETERS; cGroup group; cGroupDynamicData data; char * restrict fullname; void * restrict varptr; struct xferinfo * restrict xferinfo; int do_periodic[3]; int global_bbox[6]; int global_lbnd[3], global_ubnd[3]; int fake_bbox[6]; int gi; int dir; int d, f; int ierr; /* Check arguments */ assert (cctkGH); assert (stencil); assert (vi>=0 && vi=0 && gicctk_bbox[d]; ierr = CCTK_ReduceLocArrayToArray1D (cctkGH, -1, max_handle, local, global, 6, CCTK_VARIABLE_REAL); for (d=0; d<6; ++d) global_bbox[d] = (int)global[d]; for (d=0; d<3; ++d) local[d] = cctkGH->cctk_lbnd[d]; ierr = CCTK_ReduceLocArrayToArray1D (cctkGH, -1, min_handle, local, global, 3, CCTK_VARIABLE_REAL); for (d=0; d<3; ++d) global_lbnd[d] = (int)global[d]; for (d=0; d<3; ++d) local[d] = cctkGH->cctk_ubnd[d]; ierr = CCTK_ReduceLocArrayToArray1D (cctkGH, -1, max_handle, local, global, 3, CCTK_VARIABLE_REAL); for (d=0; d<3; ++d) global_ubnd[d] = (int)global[d]; for (d=0; d<3; ++d) { fake_bbox[2*d ] = data.lbnd[d] == global_lbnd[d]; fake_bbox[2*d+1] = data.ubnd[d] == global_ubnd[d]; } } /* Allocate slab transfer description */ xferinfo = malloc(group.dim * sizeof *xferinfo); assert (xferinfo); for (dir=0; dir= 0); if (data.gsh[dir] < 2*stencil[dir]+1) { CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING, "The group \"%s\" has in the %c-direction only %d grid points. " "This is not large enough for a periodic boundary that is %d grid points wide. " "The group needs to have at least %d grid points in that direction.", CCTK_GroupNameFromVarI(vi), "xyz"[dir], data.gsh[dir], stencil[dir], 2*stencil[dir]+1); } /* Loop over faces */ for (f=0; f<2; ++f) { if (global_bbox[2*dir+f]) { /* Fill in slab transfer description */ for (d=0; d 0); if (domain_size < step_size) { /* TODO: this could be made more efficient by taking larger steps */ step_size = 1; num_steps = stencil[dir]; } assert (num_steps*step_size == stencil[dir]); for (step=0; step data.gsh[dir] - stencil[dir]) { source -= domain_size; } assert (source >= stencil[dir]); xferinfo[dir].src.off = source; xferinfo[dir].src.len = step_size; xferinfo[dir].dst.off = data.gsh[dir] - stencil[dir] + step*step_size; xferinfo[dir].dst.len = step_size; } ierr = Slab_Transfer (cctkGH, group.dim, xferinfo, -1, group.vartype, varptr, group.vartype, varptr); assert (!ierr); } /* for step */ } } /* if bbox */ } /* for f */ } /* if dir */ } /* for dir */ free (xferinfo); return 0; } int BndPeriodicVN (cGH const * restrict const cctkGH, int const * restrict const stencil, char const * restrict const vn) { int const vi = CCTK_VarIndex (vn); assert (vi>=0 && vi=0 && gi=0); if (nv>0) { v1 = CCTK_FirstVarIndexI(gi); assert (v1>=0 && v1=0 && gi=0); indices = malloc (nvars * sizeof *indices); assert (indices); faces = malloc (nvars * sizeof *faces); assert (faces); widths = malloc (nvars * sizeof *widths); assert (widths); tables = malloc (nvars * sizeof *tables); assert (tables); ierr = Boundary_SelectedGVs (cctkGH, nvars, indices, faces, widths, tables, 0); assert (ierr == nvars); for (i=0; i=0 && vi= 0); dim = CCTK_GroupDimFromVarI (vi); assert (dim>=0); stencil = malloc (dim * sizeof *stencil); assert (stencil); ierr = CCTK_GroupnghostzonesVI (cctkGH, dim, stencil, vi); assert (!ierr); ierr = BndPeriodicVI (cctkGH, stencil, vi); assert (!ierr); free (stencil); } free (indices); free (faces); free (widths); free (tables); }