From 129af4cef8b226a012edf80e98d2bb7c33cc2c3b Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Thu, 24 Jul 2008 18:08:29 -0500 Subject: CarpetInterp2: More debugging --- Carpet/CarpetInterp2/param.ccl | 4 + Carpet/CarpetInterp2/src/fasterp.cc | 442 ++++++++++++++++++++++++------------ Carpet/CarpetInterp2/src/fasterp.hh | 91 ++++++-- 3 files changed, 375 insertions(+), 162 deletions(-) (limited to 'Carpet/CarpetInterp2') diff --git a/Carpet/CarpetInterp2/param.ccl b/Carpet/CarpetInterp2/param.ccl index 9061931b7..00363ad92 100644 --- a/Carpet/CarpetInterp2/param.ccl +++ b/Carpet/CarpetInterp2/param.ccl @@ -1 +1,5 @@ # Parameter definitions for thorn CarpetInterp + +BOOLEAN veryverbose "Produce debugging output" STEERABLE=always +{ +} "no" diff --git a/Carpet/CarpetInterp2/src/fasterp.cc b/Carpet/CarpetInterp2/src/fasterp.cc index e70880b95..dee352b76 100644 --- a/Carpet/CarpetInterp2/src/fasterp.cc +++ b/Carpet/CarpetInterp2/src/fasterp.cc @@ -1,13 +1,16 @@ +#include #include #include #include #include +#include #include #include #include +#include #include "fasterp.hh" @@ -28,6 +31,29 @@ namespace CarpetInterp2 { + int const ipoison = -1234567890; + CCTK_REAL const poison = -1.0e+12; + + template T get_poison () { abort(); } + template<> int get_poison () { return ipoison; } + template<> CCTK_REAL get_poison () { return poison; } + + template + void fill (vector & v, T const & val) + { + fill (v.begin(), v.end(), val); + } + + template + void fill_with_poison (vector & v) + { +#ifndef NDEBUG + fill (v, get_poison()); +#endif + } + + + // Create an MPI datatype for location information MPI_Datatype fasterp_iloc_t::mpi_datatype () @@ -39,14 +65,11 @@ namespace CarpetInterp2 { #define ARRSIZE(m) (sizeof(s.m) / sizeof(s.m[0])) #define OFFSET(m) ((char*)&(s.m) - (char*)&(s)) // offsetof doesn't work (why?) #define SIZE (sizeof(s)) - CCTK_REAL rdummy; dist::mpi_struct_descr_t const descr[] = { - { 1, OFFSET(m ), MPI_INT }, - { 1, OFFSET(rl ), MPI_INT }, - { 1, OFFSET(c ), MPI_INT }, - { 1, OFFSET(ind3d ), MPI_INT }, - {ARRSIZE(offset), OFFSET(offset), dist::datatype(rdummy)}, - { 1, SIZE , MPI_UB } + { 3, OFFSET(mrc ), MPI_INT }, + { 1, OFFSET(ind3d ), MPI_INT }, + {ARRSIZE(offset), OFFSET(offset), dist::datatype()}, + { 1, SIZE , MPI_UB } }; #undef ARRSIZE #undef OFFSET @@ -58,6 +81,67 @@ namespace CarpetInterp2 { return newtype; } + void + fasterp_iloc_t:: + output (ostream& os) + const + { + os << "fasterp_iloc_t{" + << "mrc=" << mrc << "," + << "ind3d=" << ind3d << "," + << "offset=" << offset << "}"; + } + + + + ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + + + + int mrc_t::maps = -1; + int mrc_t::reflevels = -1; + int mrc_t::components = -1; + + void + mrc_t:: + determine_mrc_info () + { + maps = Carpet::maps; + reflevels = Carpet::reflevels; + components = 0; + for (int m=0; mcomponents (rl); + components = max (components, ncomps); + } + } + } + + mrc_t:: + mrc_t (int ind) + { + ASSERT (ind >= 0); + int const ind0 = ind; + c = ind % components; + ind /= components; + rl = ind % reflevels; + ind /= reflevels; + m = ind % maps; + ind /= maps; + ASSERT (ind == 0); + ASSERT (get_ind() == ind0); + } + + void + mrc_t:: + output (ostream& os) + const + { + os << "mrc{m=" << m << ",rl=" << rl << ",c=" << c << "}"; + } + ////////////////////////////////////////////////////////////////////////////// @@ -67,28 +151,57 @@ namespace CarpetInterp2 { // Calculate the coefficients for one interpolation stencil + // TODO: Could templatify this function on the order to improve + // efficiency void fasterp_src_loc_t:: calc_stencil (fasterp_iloc_t const & iloc, + ivect const & lsh, int const order) { ASSERT (order <= max_order); CCTK_REAL const rone = 1.0; CCTK_REAL const eps = 1.0e-12; - int const n0 = (order+1) / 2; + +#ifndef NDEBUG + // Poison all coefficients + for (int d=0; d= eps) { - // The interpolation point does not coincide with the anchor - // (this is the regular case): - ASSERT (fabs(remainder(xi, rone)) > eps/2); + CCTK_REAL const xi = offset[d]; + if (abs(remainder(xi, rone)) < eps) { for (int n=0; n<=order; ++n) { - CCTK_REAL const xn = n - n0; + CCTK_REAL const xn = n; CCTK_REAL c = 1.0; for (int m=0; m<=order; ++m) { if (m != n) { - CCTK_REAL const xm = m - n0; + CCTK_REAL const xm = m; c *= (xi - xm) / (xn - xm); } } @@ -102,12 +215,15 @@ namespace CarpetInterp2 { } ASSERT (fabs(s - rone) <= eps); } else { - // The interpolation point coincides with the anchor; no + // The interpolation point coincides with a grid point; no // interpolation is necessary (this is a special case) + iorigin[d] += int(round(xi)); exact[d] = true; } } - ind3d = iloc.ind3d; + + // Set 3D location of stencil anchor + ind3d = iloc.ind3d + index(lsh, iorigin); } @@ -128,6 +244,10 @@ namespace CarpetInterp2 { CCTK_REAL * restrict const vals) const { + ASSERT (O0 == 0 or not exact[0]); + ASSERT (O1 == 0 or not exact[1]); + ASSERT (O2 == 0 or not exact[2]); + size_t const di = 1; size_t const dj = di * lsh[0]; size_t const dk = dj * lsh[1]; @@ -137,11 +257,14 @@ namespace CarpetInterp2 { } for (size_t k=0; k<=O2; ++k) { - CCTK_REAL const coeff_k = coeffs[2][k]; + ASSERT (O2 == 0 or coeffs[2][k] != poison); + CCTK_REAL const coeff_k = (O2==0 ? 1.0 : coeffs[2][k]); for (size_t j=0; j<=O1; ++j) { - CCTK_REAL const coeff_jk = coeff_k * coeffs[1][j]; + ASSERT (O1 == 0 or coeffs[1][j] != poison); + CCTK_REAL const coeff_jk = coeff_k * (O1==0 ? 1.0 : coeffs[1][j]); for (size_t i=0; i<=O0; ++i) { - CCTK_REAL const coeff_ijk = coeff_jk * coeffs[0][i]; + ASSERT (O0 == 0 or coeffs[0][i] != poison); + CCTK_REAL const coeff_ijk = coeff_jk * (O0==0 ? 1.0 : coeffs[0][i]); for (size_t v=0; v (lsh, varptrs, vals); } else { - interpolate (lsh, varptrs, vals); + interpolate (lsh, varptrs, vals); } } else { if (exact[0]) { interpolate (lsh, varptrs, vals); } else { - interpolate (lsh, varptrs, vals); + interpolate (lsh, varptrs, vals); } } } else { if (exact[1]) { if (exact[0]) { - interpolate (lsh, varptrs, vals); + interpolate (lsh, varptrs, vals); } else { interpolate (lsh, varptrs, vals); } } else { if (exact[0]) { - interpolate (lsh, varptrs, vals); + interpolate (lsh, varptrs, vals); } else { interpolate (lsh, varptrs, vals); } @@ -310,11 +433,18 @@ namespace CarpetInterp2 { setup (cGH const * restrict const cctkGH, fasterp_llocs_t const & locations) { + DECLARE_CCTK_PARAMETERS; + // Some global properties int const npoints = locations.size(); int const nprocs = CCTK_nProcs (cctkGH); // int const myproc = CCTK_MyProc (cctkGH); + mrc_t::determine_mrc_info(); + int const maxmrc = mrc_t::get_max_ind(); + + MPI_Comm & comm_world = * (MPI_Comm *) GetMPICommWorld (cctkGH); + // Obtain the coordinate ranges for all patches @@ -335,6 +465,7 @@ namespace CarpetInterp2 { // indices vector ilocs (npoints); vector proc (npoints); + fill_with_poison (proc); vector nlocs (nprocs, 0); int n_nz_nlocs = 0; ASSERT (Carpet::is_level_mode()); @@ -357,34 +488,26 @@ namespace CarpetInterp2 { Carpet::mglevel, Carpet::reflevel, Carpet::reflevel+1, rl, c, ipos); + ASSERT (rl>=0 and c>=0); ibbox const & ext = Carpet::vdd.AT(m)->boxes.AT(Carpet::mglevel).AT(rl).AT(c).exterior; rvect dpos = rpos - rvect(ipos); + // Convert from Carpet indexing to grid point indexing ASSERT (all (ipos % ext.stride() == ivect(0))); ipos /= ext.stride(); dpos /= rvect(ext.stride()); ASSERT (all (abs(dpos) <= rvect(0.5))); - if (order % 2 != 0) { - // Potentially shift the stencil anchor for odd interpolation - // orders (i.e., for even numbers of stencil points) - ivect const ioff = either (dpos > rvect(0.0), ivect(1), ivect(0)); - ipos -= ioff; - dpos += rvect(ioff); - ASSERT (all (dpos >= rvect(0.0) and dpos < rvect(1.0))); - } - ivect const ind = ipos - ext.lower() / ext.stride(); ivect const lsh = ext.shape() / ext.stride(); - int const ind3d = ind[0] + lsh[0] * (ind[1] + lsh[1] * ind[2]); + int const ind3d = index (lsh, ind); + // TODO: ASSERT that there are enough ghost zones // Store result fasterp_iloc_t & iloc = ilocs.AT(n); - iloc.m = m; - iloc.rl = rl; - iloc.c = c; + iloc.mrc = mrc_t(m, rl, c); iloc.ind3d = ind3d; iloc.offset = dpos; @@ -393,6 +516,11 @@ namespace CarpetInterp2 { proc.AT(n) = p; if (nlocs.AT(p) == 0) ++n_nz_nlocs; ++ nlocs.AT(p); + + // Output + if (veryverbose) { + cout << "Point #" << n << " at " << pos << ": iloc " << iloc << endl; + } } @@ -426,6 +554,7 @@ namespace CarpetInterp2 { // from the other processors. { vector index (recv_descr.procs.size()); + fill_with_poison (index); for (int pp=0; pp received (npoints, false); + for (int n=0; n send_npoints (nprocs, 0), send_offsets (nprocs); + fill_with_poison (send_offsets); { int offset = 0; for (int pp=0; pp recv_npoints (nprocs), recv_offsets (nprocs); + fill_with_poison (recv_npoints); + fill_with_poison (recv_offsets); MPI_Alltoall (&send_npoints.front(), 1, MPI_INT, &recv_npoints.front(), 1, MPI_INT, - MPI_COMM_WORLD); + comm_world); int npoints_source = 0; for (int p=0; p gathered_ilocs(npoints_source); - MPI_Comm & comm_world = * (MPI_Comm *) GetMPICommWorld (cctkGH); MPI_Alltoallv (&scattered_ilocs.front(), &send_npoints.front(), &send_offsets.front(), fasterp_iloc_t::mpi_datatype(), @@ -499,90 +638,81 @@ namespace CarpetInterp2 { if (recv_npoints.AT(p) > 0) { send_proc_t & send_proc = send_descr.procs.AT(pp); send_proc.p = p; - send_proc.offset = recv_offsets.AT(p); - send_proc.npoints = recv_npoints.AT(p); + send_proc.offset = send_offsets.AT(p); + send_proc.npoints = send_npoints.AT(p); ++pp; } } ASSERT (pp == n_nz_recv_npoints); } + + + // Calculate stencil coefficients + for (size_t pp=0; ppcomponents (rl); - send_proc.maps.AT(m).rls.AT(rl).compinds.resize (ncomps, -1); - } - } + vector mrc2comp (maxmrc, -1); + vector comp2mrc (maxmrc); + fill_with_poison (comp2mrc); + int comps = 0; - vector > > npoints_comp (Carpet::maps); - for (int m=0; mcomponents (rl); - npoints_comp.AT(m).AT(rl).resize(ncomps, 0); - } - } - - vector > n_nz_npoints_comp (Carpet::maps); - for (int m=0; m npoints_comp (maxmrc, 0); for (int n=0; ncomponents (rl); - for (int c=0; c 0) { - send_comp_t & comp = send_proc.maps.AT(m).rls.AT(rl).comps.AT(cc); - comp.locs.clear(); - comp.locs.reserve (npoints_comp.AT(m).AT(rl).AT(c)); - comp.c = c; - send_proc.maps.AT(m).rls.AT(rl).compinds.AT(c) = cc; - ++cc; - } - } - } + int offset = 0; + for (int comp=0; compboxes.AT(Carpet::mglevel).AT(rl).AT(c).exterior; + send_comp.lsh = ext.shape() / ext.stride(); + + send_comp.offset = offset; + send_comp.npoints = npoints_comp.AT(mrc); + offset += send_comp.npoints; } + ASSERT (offset == send_proc.npoints); - } // for pp - - - - // Calculate stencil coefficients - for (size_t pp=0; pp recv_points (recv_descr.npoints * nvars); + fill_with_poison (recv_points); vector recv_reqs (recv_descr.procs.size()); for (size_t pp=0; pp(), recv_proc.p, mpi_tag, comm_world, & recv_reqs.AT(pp)); } // Interpolate data and post Isends vector send_points (send_descr.npoints * nvars); - vector::iterator destit = send_points.begin(); + fill_with_poison (send_points); vector send_reqs (send_descr.procs.size()); for (size_t pp=0; pp varptrs (nvars); - for (size_t v=0; v= 0); - int const vi = varinds.AT(v) - CCTK_FirstVarIndexI (gi); - ASSERT (vi >= 0); - int const tl = 0; - varptrs.AT(v) = - (CCTK_REAL const *) - (* Carpet::arrdata.AT(gi).AT(m).data.AT(vi)) - (tl, rl, c, Carpet::mglevel)->storage(); - ASSERT (varptrs.AT(v)); - } - - for (size_t n=0; n::iterator + destit = send_points.begin() + send_proc.offset * nvars; + vector::iterator const + endit = destit + send_proc.npoints * nvars; + + for (size_t comp=0; comp varptrs (nvars); + for (size_t v=0; v= 0); + int const vi = varinds.AT(v) - CCTK_FirstVarIndexI (gi); + ASSERT (vi >= 0); + varptrs.AT(v) = + (CCTK_REAL const *) + (* Carpet::arrdata.AT(gi).AT(m).data.AT(vi)) + (tl, rl, c, Carpet::mglevel)->storage(); + ASSERT (varptrs.AT(v)); + } + + for (size_t n=0; n gathered_send_points (send_proc.npoints * nvars); + fill_with_poison (gathered_send_points); + for (int n=0; n(), send_proc.p, mpi_tag, comm_world, & send_reqs.AT(pp)); } // for pp - ASSERT (destit == send_points.end()); // Wait for Irecvs to complete MPI_Waitall (recv_reqs.size(), & recv_reqs.front(), MPI_STATUSES_IGNORE); @@ -711,6 +854,9 @@ namespace CarpetInterp2 { size_t const nn = recv_descr.index.AT(n); for (size_t v=0; v #include +#include #include #include @@ -27,6 +29,52 @@ namespace CarpetInterp2 { + // Keep a map, refinement level, and component index together + struct mrc_t { + static int maps; + static int reflevels; + static int components; + + static void determine_mrc_info (); + static int get_max_ind () + { + return maps * reflevels * components; + } + + int m; + int rl; + int c; + + mrc_t () + { + } + + mrc_t (int const m_, int const rl_, int const c_) + : m(m_), rl(rl_), c(c_) + { + assert (m>=0 and m=0 and rl=0 and c coords[dim]; @@ -56,15 +104,21 @@ namespace CarpetInterp2 { // An integer location, given by map, refinement level, and // component struct fasterp_iloc_t { - int m, rl, c; + mrc_t mrc; // map, refinement level, component // ivect idx; int ind3d; rvect offset; // in terms of grid points static MPI_Datatype mpi_datatype (); + + void output (ostream& os) const; }; + inline + ostream& operator<< (ostream& os, fasterp_iloc_t const & iloc) + { iloc.output(os); return os; } + struct fasterp_dest_loc_t { @@ -82,6 +136,7 @@ namespace CarpetInterp2 { public: void calc_stencil (fasterp_iloc_t const & iloc, + ivect const & lsh, int order); void interpolate (ivect const & lsh, @@ -103,8 +158,15 @@ namespace CarpetInterp2 { vector const & varptrs, CCTK_REAL * restrict vals) const; + + public: + void output (ostream& os) const; }; + inline + ostream& operator<< (ostream& os, fasterp_src_loc_t const & sloc) + { sloc.output(os); return os; } + // A receive descriptor, describing what is received from other @@ -120,36 +182,37 @@ namespace CarpetInterp2 { vector procinds; int npoints; // total number of received points - vector index; // gather index list + vector index; // gather index list: index[user-location] = + // mpi-location }; // A send descriptor; describing what to send to other processors struct send_comp_t { // This structure does not exist for all components -- components // which are not accessed are not described, making this a sparse - // data structure. The field c contains the component number. + // data structure. The fields m, rl, and c identify the + // component. vector locs; - int c; // source component - }; - - struct send_rl_t { - vector comps; - vector compinds; + + mrc_t mrc; // source map, refinement level, component + ivect lsh; + int offset; + int npoints; }; - struct send_map_t { - vector rls; - }; - struct send_proc_t { // This structure does not exist for all processors -- processors // with which there is no communication are not described, making // this a sparse data structure. The field p contains the // processor number. - vector maps; + vector comps; + int p; // receiving processor int offset; int npoints; // total number of sent points + + vector index; // gather index list: index[mpi-location] = + // calculation-location }; struct send_descr_t { -- cgit v1.2.3