#include #include #include #include #include "cctk.h" #include "cctk_Parameters.h" #include "Slab.h" int BndPeriodicVI (CCTK_POINTER_TO_CONST _GH, int size, int const * restrict const stencil, int const do_periodic[3], int const vi) { cGH const * restrict const cctkGH = _GH; DECLARE_CCTK_PARAMETERS; cGroup group; cGroupDynamicData data; void * restrict varptr; struct xferinfo * restrict xferinfo; int global_bbox[6]; int global_lbnd[3], global_ubnd[3]; int fake_bbox[6]; int gi; int dir, face; int d; int ierr; /* Check arguments */ assert (cctkGH); assert (stencil); assert (vi>=0 && vi=0 && gi0); if(group.dim != size) { CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING, "The group \"%s\" has dimension %d, but the given stencil has " "size %d.", CCTK_GroupNameFromVarI(vi), group.dim, size); } ierr = CCTK_GroupDynamicData (cctkGH, gi, &data); assert (!ierr); varptr = CCTK_VarDataPtrI (cctkGH, 0, vi); assert (varptr); { int min_handle, max_handle; CCTK_REAL local[6], global[6]; min_handle = CCTK_ReductionArrayHandle ("minimum"); if (min_handle<0) CCTK_WARN (0, "Could not obtain reduction handle"); max_handle = CCTK_ReductionArrayHandle ("maximum"); if (max_handle<0) CCTK_WARN (0, "Could not obtain reduction handle"); for (d=0; d<6; ++d) local[d] = cctkGH->cctk_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]; } } if (poison_boundaries) { /* poison destination grid points */ for (dir=0; dir= 0); for (face=0; face<2; ++face) { if (cctkGH->cctk_bbox[2*dir+face]) { int imin[3], imax[3]; for (d=0; d= 0); if (data.gsh[dir] < 2*stencil[dir]+1) { return dir+1; } /* Loop over faces */ for (face=0; face<2; ++face) { if (global_bbox[2*dir+face]) { /* 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); if (check_boundaries) { /* check destination grid points for poison */ char poison[vartypesize]; memset (poison, poison_value, vartypesize); for (dir=0; dir= 0); for (face=0; face<2; ++face) { if (cctkGH->cctk_bbox[2*dir+face]) { int imin[3], imax[3]; for (d=0; d 0) { char *const fullname = CCTK_FullName(vi); CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING, "Found poison on symmetry boundary of variable \"%s\" direction %d face %d after applying periodicity boundary condition", fullname, dir, face); free (fullname); } } } } } } return 0; } int BndPeriodicVN (CCTK_POINTER_TO_CONST cctkGH, int size, int const * restrict const stencil, int const do_periodic[3], 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); if (verbose) { fullname = CCTK_FullName(vi); assert (fullname); CCTK_VInfo (CCTK_THORNSTRING, "Applying periodicity boundary conditions to \"%s\"", fullname); free (fullname); } ierr = BndPeriodicVI (cctkGH, dim, stencil, do_periodic, vi); if(ierr > 0 && ierr < 4) { int dir = ierr-1; int gi; cGroup group; cGroupDynamicData data; gi = CCTK_GroupIndexFromVarI (vi); ierr = CCTK_GroupData (gi, &group); assert (!ierr); ierr = CCTK_GroupDynamicData (cctkGH, gi, &data); assert (!ierr); 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); } assert (!ierr); free (stencil); } free (indices); free (faces); free (widths); free (tables); }