// $Header: /home/eschnett/C/carpet/Carpet/Carpet/CarpetInterp/src/interp.cc,v 1.12 2003/08/15 11:42:25 schnetter Exp $ #include #include #include #include #include #include "cctk.h" #include "bbox.hh" #include "data.hh" #include "vect.hh" #include "carpet.hh" #include "interp.hh" extern "C" { static char const * const rcsid = "$Header: /home/eschnett/C/carpet/Carpet/Carpet/CarpetInterp/src/interp.cc,v 1.12 2003/08/15 11:42:25 schnetter Exp $"; CCTK_FILEVERSION(Carpet_CarpetInterp_interp_cc); } namespace CarpetInterp { using namespace Carpet; typedef vect ivect; typedef vect rvect; typedef bbox ibbox; #define ind_rc(rl,c) ind_rc_(rl,minrl,maxrl,c,maxncomps,hh) static inline int ind_rc_(int const rl, int const minrl, int const maxrl, int const c, int const maxncomps, gh const * const hh) { assert (rl>=minrl && rl=0 && maxrl<=hh->reflevels()); assert (c>=0 && c=0 && maxncomps<=hh->components(rl)); int const ind = rl * maxncomps + c; assert (ind>=0 && ind < (maxrl-minrl) * maxncomps); return ind; } #define ind_prc(p,rl,c) ind_prc_(p,nprocs,rl,minrl,maxrl,c,maxncomps,cgh,hh) static inline int ind_prc_(int const p, int const nprocs, int const rl, int const minrl, int const maxrl, int const c, int const maxncomps, cGH const * const cgh, gh const * const hh) { assert (p>=0 && p=minrl && rl=0 && maxrl<=hh->reflevels()); assert (c>=0 && c=0 && maxncomps<=hh->components(rl)); int const ind = (p * (maxrl-minrl) + rl) * maxncomps + c; assert (ind>=0 && ind < nprocs * (maxrl-minrl) * maxncomps); return ind; } void CarpetInterpStartup () { CCTK_OverloadInterpGridArrays (InterpGridArrays); } int InterpGridArrays (cGH const * const cgh, int const N_dims, int const local_interp_handle, int const param_table_handle, int const coord_system_handle, int const N_interp_points, int const interp_coords_type_code, void const * const interp_coords [], int const N_input_arrays, CCTK_INT const input_array_variable_indices [], int const N_output_arrays, CCTK_INT const output_array_type_codes [], void * const output_arrays []) { int ierr; assert (cgh); assert (N_dims == dim); // Find out about the coordinates const char * coord_system_name = CCTK_CoordSystemName (coord_system_handle); assert (coord_system_name); rvect lower, upper, delta; for (int d=0; dbaseextent.shape()[d] - hh->baseextent.stride()[d]); } assert (interp_coords); for (int d=0; d=0 && myprocreflevels() : reflevel+1; int const ml = 0; int maxncomps = 0; for (int rl=minrl; rlcomponents(rl)); } // Assert that all refinement levels have the same time // TODO: interpolate in time { bool can_interp = true; for (int rl=minrl; rltime (tl, rl, ml); CCTK_REAL const time2 = cgh->cctk_time / cgh->cctk_delta_time; // assert (fabs((time1 - time2) / (fabs(time1) + fabs(time2) + fabs(cgh->cctk_delta_time))) < 1e-12); can_interp = can_interp && (fabs((time1 - time2) / (fabs(time1) + fabs(time2) + fabs(cgh->cctk_delta_time))) < 1e-12); } if (! can_interp) { if (reflevel == -1) { CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING, "Cannot interpolate in global mode at iteration %d (time %g), because not all refinement levels exist at this time. Interpolation in time is not yet implemented.", cgh->cctk_iteration, (double)cgh->cctk_time); } else { CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING, "Cannot interpolate in level mode at iteration %d (time %g), because refinement level %d does not exist at this time. Interpolation in time is not yet implemented.", cgh->cctk_iteration, (double)cgh->cctk_time, reflevel); } assert (0); } } // Assign interpolation points to components vector rlev (N_interp_points); // refinement level of point n vector home (N_interp_points); // component of point n vector homecnts ((maxrl-minrl) * maxncomps); // number of points in component c for (int n=0; n(interp_coords[d])[n]; } // Find the component that this grid point belongs to rlev[n] = -1; home[n] = -1; for (int rl=maxrl-1; rl>=minrl; --rl) { CCTK_REAL (* const rfloor) (CCTK_REAL const) = floor; ivect const ipos = ivect(map(rfloor, (pos - lower) / delta + 0.5)); // TODO: use something faster than a linear search for (int c=0; ccomponents(rl); ++c) { if (hh->extents[rl][c][ml].contains(ipos)) { rlev[n] = rl; home[n] = c; goto found; } } } CCTK_VWarn (0, __LINE__, __FILE__, CCTK_THORNSTRING, "Interpolation point #%d at [%g,%g,%g] is not on any grid patch", n, pos[0], pos[1], pos[2]); found: assert (rlev[n]>=minrl && rlev[n]=0 && home[n]components(rlev[n])); ++ homecnts [ind_rc(rlev[n], home[n])]; } // for n // Communicate counts vector allhomecnts(nprocs * (maxrl-minrl) * maxncomps); MPI_Allgather (&homecnts [0], (maxrl-minrl) * maxncomps, MPI_INT, &allhomecnts[0], (maxrl-minrl) * maxncomps, MPI_INT, comm); // Create coordinate patches vector > allcoords (nprocs * (maxrl-minrl) * maxncomps); for (int p=0; pcomponents(rl); ++c) { ivect lo (0); ivect up (1); up[0] = allhomecnts[ind_prc(p,rl,c)]; up[1] = dim; ivect str (1); ibbox extent (lo, up-str, str); allcoords [ind_prc(p,rl,c)].allocate (extent, p); } } } // Fill in local coordinate patches { vector tmpcnts ((maxrl-minrl) * maxncomps); for (int n=0; n=minrl && rl=0 && ccomponents(rl)); assert (tmpcnts[ind_rc(rl,c)] >= 0); assert (tmpcnts[ind_rc(rl,c)] < homecnts[ind_rc(rl,c)]); assert (dim==3); for (int d=0; d(interp_coords[d])[n]; } ++ tmpcnts[c + (rl-minrl)*maxncomps]; } for (int rl=minrl; rlcomponents(rl); ++c) { assert (tmpcnts[ind_rc(rl,c)] == homecnts[ind_rc(rl,c)]); } } } // Transfer coordinate patches for (int p=0; pcomponents(rl); ++c) { allcoords[ind_prc(p,rl,c)].change_processor (hh->processors[rl][c]); } } } // Create output patches vector > alloutputs (nprocs * (maxrl-minrl) * maxncomps); for (int p=0; pcomponents(rl); ++c) { ivect lo (0); ivect up (1); up[0] = allhomecnts[ind_prc(p,rl,c)]; up[1] = N_output_arrays; ivect str (1); ibbox extent (lo, up-str, str); alloutputs[ind_prc(p,rl,c)].allocate (extent, hh->processors[rl][c]); } } } // // Do the local interpolation // int const saved_reflevel = reflevel; int const saved_mglevel = mglevel; int const saved_component = component; if (component!=-1) { set_component ((cGH*)cgh, -1); } if (mglevel!=-1) { set_mglevel ((cGH*)cgh, -1); } if (reflevel!=-1) { set_reflevel ((cGH*)cgh, -1); } BEGIN_REFLEVEL_LOOP(cgh) { if (reflevel>=minrl && reflevelcctk_lsh[d]; coord_delta[d] = cgh->cctk_delta_space[d] / cgh->cctk_levfac[d]; coord_origin[d] = cgh->cctk_origin_space[d] + (1.0 * cgh->cctk_levoff[d] / cgh->cctk_levoffdenom[d] + cgh->cctk_lbnd[d]) * coord_delta[d]; } // Find out about the grid functions vector input_array_type_codes(N_input_arrays); vector input_arrays(N_input_arrays); for (int n=0; n=0 && vi=0 && gi tmp_interp_coords (dim); for (int d=0; d tmp_output_arrays (N_output_arrays); for (int m=0; mcomponents(rl); ++c) { alloutputs[ind_prc(p,rl,c)].change_processor (p); } } } // Read out local output patches { vector tmpcnts ((maxrl-minrl) * maxncomps); for (int n=0; n(output_arrays[m])[n] = alloutputs[ind_prc(myproc,rl,c)][ivect(tmpcnts[ind_rc(rl,c)],m,0)]; } ++ tmpcnts[ind_rc(rl,c)]; } for (int rl=minrl; rlcomponents(rl); ++c) { assert (tmpcnts[ind_rc(rl,c)] == homecnts[ind_rc(rl,c)]); } } } // Done. return 0; } } // namespace CarpetInterp