#include #include using namespace amrex; void WarpX::LoadBalance () { BL_PROFILE_REGION("LoadBalance"); BL_PROFILE("WarpX::LoadBalance()"); AMREX_ALWAYS_ASSERT(costs[0] != nullptr); for (int lev = 0; lev <= finestLevel(); ++lev) { const Real nboxes = costs[lev]->size(); const Real nprocs = ParallelDescriptor::NProcs(); const int nmax = static_cast(std::ceil(nboxes/nprocs*load_balance_knapsack_factor)); const DistributionMapping newdm = (load_balance_with_sfc) ? DistributionMapping::makeSFC(*costs[lev], false) : DistributionMapping::makeKnapSack(*costs[lev], nmax); RemakeLevel(lev, t_new[lev], boxArray(lev), newdm); } mypc->Redistribute(); } void WarpX::RemakeLevel (int lev, Real time, const BoxArray& ba, const DistributionMapping& dm) { if (ba == boxArray(lev)) { if (ParallelDescriptor::NProcs() == 1) return; #ifdef WARPX_DO_ELECTROSTATIC AMREX_ALWAYS_ASSERT(masks[lev] == nullptr); AMREX_ALWAYS_ASSERT(gather_masks[lev] == nullptr); #endif // WARPX_DO_ELECTROSTATIC // Fine patch const auto& period = Geom(lev).periodicity(); for (int idim=0; idim < 3; ++idim) { { const IntVect& ng = Bfield_fp[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(Bfield_fp[lev][idim]->boxArray(), dm, 1, ng)); pmf->Redistribute(*Bfield_fp[lev][idim], 0, 0, 1, ng); Bfield_fp[lev][idim] = std::move(pmf); } { const IntVect& ng = Efield_fp[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(Efield_fp[lev][idim]->boxArray(), dm, 1, ng)); pmf->Redistribute(*Efield_fp[lev][idim], 0, 0, 1, ng); Efield_fp[lev][idim] = std::move(pmf); } { const IntVect& ng = current_fp[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(current_fp[lev][idim]->boxArray(), dm, 1, ng)); current_fp[lev][idim] = std::move(pmf); current_fp_owner_masks[lev][idim] = std::move(current_fp[lev][idim]->OwnerMask(period)); } if (current_store[lev][idim]) { const IntVect& ng = current_store[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(current_store[lev][idim]->boxArray(), dm, 1, ng)); // no need to redistribute current_store[lev][idim] = std::move(pmf); } } if (F_fp[lev] != nullptr) { const IntVect& ng = F_fp[lev]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(F_fp[lev]->boxArray(), dm, 1, ng)); pmf->Redistribute(*F_fp[lev], 0, 0, 1, ng); F_fp[lev] = std::move(pmf); } if (rho_fp[lev] != nullptr) { const int nc = rho_fp[lev]->nComp(); const IntVect& ng = rho_fp[lev]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(rho_fp[lev]->boxArray(), dm, nc, ng)); rho_fp[lev] = std::move(pmf); rho_fp_owner_masks[lev] = std::move(rho_fp[lev]->OwnerMask(period)); } // Aux patch if (lev == 0) { for (int idim = 0; idim < 3; ++idim) { Bfield_aux[lev][idim].reset(new MultiFab(*Bfield_fp[lev][idim], amrex::make_alias, 0, 1)); Efield_aux[lev][idim].reset(new MultiFab(*Efield_fp[lev][idim], amrex::make_alias, 0, 1)); } } else { for (int idim=0; idim < 3; ++idim) { { const IntVect& ng = Bfield_aux[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(Bfield_aux[lev][idim]->boxArray(), dm, 1, ng)); // pmf->Redistribute(*Bfield_aux[lev][idim], 0, 0, 1, ng); Bfield_aux[lev][idim] = std::move(pmf); } { const IntVect& ng = Efield_aux[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(Efield_aux[lev][idim]->boxArray(), dm, 1, ng)); // pmf->Redistribute(*Efield_aux[lev][idim], 0, 0, 1, ng); Efield_aux[lev][idim] = std::move(pmf); } } } // Coarse patch if (lev > 0) { const auto& cperiod = Geom(lev-1).periodicity(); for (int idim=0; idim < 3; ++idim) { { const IntVect& ng = Bfield_cp[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(Bfield_cp[lev][idim]->boxArray(), dm, 1, ng)); pmf->Redistribute(*Bfield_cp[lev][idim], 0, 0, 1, ng); Bfield_cp[lev][idim] = std::move(pmf); } { const IntVect& ng = Efield_cp[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(Efield_cp[lev][idim]->boxArray(), dm, 1, ng)); pmf->Redistribute(*Efield_cp[lev][idim], 0, 0, 1, ng); Efield_cp[lev][idim] = std::move(pmf); } { const IntVect& ng = current_cp[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr( new MultiFab(current_cp[lev][idim]->boxArray(), dm, 1, ng)); current_cp[lev][idim] = std::move(pmf); current_cp_owner_masks[lev][idim] = std::move( current_cp[lev][idim]->OwnerMask(cperiod)); } } if (F_cp[lev] != nullptr) { const IntVect& ng = F_cp[lev]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(F_cp[lev]->boxArray(), dm, 1, ng)); pmf->Redistribute(*F_cp[lev], 0, 0, 1, ng); F_cp[lev] = std::move(pmf); } if (rho_cp[lev] != nullptr) { const int nc = rho_cp[lev]->nComp(); const IntVect& ng = rho_cp[lev]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(rho_cp[lev]->boxArray(), dm, nc, ng)); rho_cp[lev] = std::move(pmf); rho_cp_owner_masks[lev] = std::move(rho_cp[lev]->OwnerMask(cperiod)); } } if (lev > 0 && (n_field_gather_buffer > 0 || n_current_deposition_buffer > 0)) { for (int idim=0; idim < 3; ++idim) { if (Bfield_cax[lev][idim]) { const IntVect& ng = Bfield_cax[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(Bfield_cax[lev][idim]->boxArray(), dm, 1, ng)); // pmf->ParallelCopy(*Bfield_cax[lev][idim], 0, 0, 1, ng, ng); Bfield_cax[lev][idim] = std::move(pmf); } if (Efield_cax[lev][idim]) { const IntVect& ng = Efield_cax[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(Efield_cax[lev][idim]->boxArray(), dm, 1, ng)); // pmf->ParallelCopy(*Efield_cax[lev][idim], 0, 0, 1, ng, ng); Efield_cax[lev][idim] = std::move(pmf); } if (current_buf[lev][idim]) { const IntVect& ng = current_buf[lev][idim]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(current_buf[lev][idim]->boxArray(), dm, 1, ng)); // pmf->ParallelCopy(*current_buf[lev][idim], 0, 0, 1, ng, ng); current_buf[lev][idim] = std::move(pmf); } } if (charge_buf[lev]) { const IntVect& ng = charge_buf[lev]->nGrowVect(); auto pmf = std::unique_ptr(new MultiFab(charge_buf[lev]->boxArray(), dm, 1, ng)); // pmf->ParallelCopy(*charge_buf[lev][idim], 0, 0, 1, ng, ng); charge_buf[lev] = std::move(pmf); } if (current_buffer_masks[lev]) { const IntVect& ng = current_buffer_masks[lev]->nGrowVect(); auto pmf = std::unique_ptr(new iMultiFab(current_buffer_masks[lev]->boxArray(), dm, 1, ng)); // pmf->ParallelCopy(*current_buffer_masks[lev], 0, 0, 1, ng, ng); current_buffer_masks[lev] = std::move(pmf); } if (gather_buffer_masks[lev]) { const IntVect& ng = gather_buffer_masks[lev]->nGrowVect(); auto pmf = std::unique_ptr(new iMultiFab(gather_buffer_masks[lev]->boxArray(), dm, 1, ng)); // pmf->ParallelCopy(*gather_buffer_masks[lev], 0, 0, 1, ng, ng); gather_buffer_masks[lev] = std::move(pmf); } } if (costs[lev] != nullptr) { costs[lev].reset(new MultiFab(costs[lev]->boxArray(), dm, 1, 0)); costs[lev]->setVal(0.0); } SetDistributionMap(lev, dm); } else { amrex::Abort("RemakeLevel: to be implemented"); } }