#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CCTK_MPI # include #else # include "nompi.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include namespace Carpet { using namespace std; // Helper routines for spliting regions automatically // The cost for a region, assuming a cost of 1 per interior point static rvect cost (region_t const & reg) { DECLARE_CCTK_PARAMETERS; static rvect costfactor; static bool initialised = false; if (not initialised) { costfactor = rvect(1.0); if (dim > 0) costfactor[0] = 1.0 / aspect_ratio_x; if (dim > 1) costfactor[1] = 1.0 / aspect_ratio_y; if (dim > 2) costfactor[2] = 1.0 / aspect_ratio_z; } if (reg.extent.empty()) return rvect(0); return rvect (reg.extent.shape() / reg.extent.stride()) * costfactor; } struct f_range { int lower, upper, stride; }; struct f_bbox { f_range dim[3]; f_bbox () {} f_bbox (ibbox const& box) { assert (::dim == 3); for (int d=0; d<3; ++d) { dim[d].lower = box.lower()[d]; dim[d].upper = box.upper()[d]; dim[d].stride = box.stride()[d]; } } /*explicit*/ operator ibbox () const { ivect lower, upper, stride; assert (::dim == 3); for (int d=0; d<3; ++d) { lower [d] = dim[d].lower; upper [d] = dim[d].upper; stride[d] = dim[d].stride; } return ibbox (lower, upper, stride); } }; struct f_boundary { int obound[2][3]; f_boundary () {} f_boundary (b2vect const& ob) { assert (::dim == 3); for (int d=0; d<3; ++d) { for (int f=0; f<2; ++f) { obound[f][d] = ob[f][d]; } } } /*explicit*/ operator b2vect () const { b2vect ob; assert (::dim == 3); for (int d=0; d<3; ++d) { for (int f=0; f<2; ++f) { ob[f][d] = obound[f][d]; } } return ob; } }; struct f_superregion2slim { f_bbox extent; f_boundary outer_boundaries; int map; int processor; /*explicit*/ operator region_t () const { region_t reg; reg.extent = ibbox(extent); reg.outer_boundaries = b2vect(outer_boundaries); reg.map = map; reg.processor = processor; reg.processors = NULL; return reg; } /*explicit*/ operator pseudoregion_t () const { pseudoregion_t preg; preg.extent = ibbox(extent); preg.component = processor; return preg; } }; extern "C" CCTK_FCALL void CCTK_FNAME(splitregions_recursively) (CCTK_POINTER const& cxx_superregs, int const& nsuperregs, CCTK_POINTER const& cxx_regs, int const& nprocs, int const& ghostsize, CCTK_REAL const& alpha, int const& limit_size, CCTK_INT const& granularity, CCTK_INT const& granularity_boundary, int const& procid); void SplitRegionsMaps_Recursively (cGH const * const cctkGH, vector > & superregss, vector > & regss) { DECLARE_CCTK_PARAMETERS; if (recompose_verbose) cout << "SRMR enter" << endl; int const nmaps = superregss.size(); assert (int(regss.size()) == nmaps); int map_offset = 1000000000; int max_map = 0; vector have_map(maps, false); for (int m=0; m superregs; { for (int m=0; m superreg_maps(nsuperregs); for (int r=0; r regs; // regs.reserve (...); CCTK_POINTER const cxx_regs = & regs; int const ghostsize = vdd.AT(0)->ghost_widths.AT(0)[0][0]; for (int m=0; mghost_widths.AT(rl)[f][d] == ghostsize); } } } } CCTK_REAL const alpha = ghost_zone_cost; int const limit_size = true; int const procid = CCTK_MyProc(cctkGH); CCTK_FNAME(splitregions_recursively) (cxx_superregs, nsuperregs, cxx_regs, nprocs, ghostsize, alpha, limit_size, granularity, granularity_boundary, procid); int nregs = regs.size(); if (same_number_of_components_on_each_process) { // Ensure all processes have the same number of components vector ncomps(nprocs, 0); for (int r=0; r=0); ++ncomps.AT(p); } int maxncomps = 0; int sumncomps = 0; for (int p=0; p 0) { // Invent a dummy component ibbox const& ext = superregss.AT(0).AT(0).extent; region_t dummy; dummy.extent = ibbox(ext.lower(), ext.lower()-ext.stride(), ext.stride()); assert (dummy.extent.empty()); dummy.outer_boundaries = b2vect(true); dummy.map = nmaps-1; // arbitrary choice // Insert dummy regions at the end regs.resize(nregs + missingcomps, dummy); for (int p=0; p bounds(missingcomps+1); for (int n=0; n subtrees(missingcomps); for (int n=0; n > old_superregss; swap (superregss, old_superregss); superregss.resize (old_superregss.size()); assert ((int)regss.size() == nmaps); for (int m=0; m=0 and m=0 and s=0 and m all_old_superregss(maps); for (size_t m=0; m all_superregss(maps); for (size_t m=0; m all_regss(maps); for (size_t m=0; m& superregs = *static_cast*>(cxx_superregs); region_t& superreg = superregs.AT(i); cxx_superreg = &superreg; } extern "C" CCTK_FCALL void CCTK_FNAME(carpet_get_bbox) (CCTK_POINTER& cxx_superreg, f_bbox& box, f_boundary& obound) { region_t& superreg = *static_cast(cxx_superreg); box = f_bbox(superreg.extent); obound = f_boundary(superreg.outer_boundaries); } extern "C" CCTK_FCALL void CCTK_FNAME(carpet_insert_region) (CCTK_POINTER& cxx_regs, f_superregion2slim const& reg) { vector& regs = *static_cast*>(cxx_regs); regs.push_back(region_t(reg)); } extern "C" CCTK_FCALL void CCTK_FNAME(carpet_create_tree_branch) (int const& nch, int const& dir, int const fbounds[], CCTK_POINTER cxx_subtrees[], CCTK_POINTER& cxx_tree) { vector bounds(nch+1); vector subtrees(nch); for (int i=0; i(cxx_subtrees[i]); assert (tree->invariant()); subtrees.AT(i) = tree; } cxx_tree = new ipfulltree (dir, bounds, subtrees); } extern "C" CCTK_FCALL void CCTK_FNAME(carpet_create_tree_leaf) (f_superregion2slim const& sreg, CCTK_POINTER& cxx_tree) { cxx_tree = new ipfulltree(pseudoregion_t(sreg)); } extern "C" CCTK_FCALL void CCTK_FNAME(carpet_set_tree) (CCTK_POINTER& cxx_superreg, CCTK_POINTER& cxx_tree) { region_t& superreg = *static_cast(cxx_superreg); ipfulltree* tree = static_cast(cxx_tree); assert (not superreg.processors); superreg.processors = tree; } } // namespace Carpet