Skip to content

Commit

Permalink
add of a load balancer for the hybrid model based on NPPC
Browse files Browse the repository at this point in the history
  • Loading branch information
rochSmets authored and PhilipDeegan committed Apr 25, 2024
1 parent 88893fa commit 73a722d
Show file tree
Hide file tree
Showing 14 changed files with 793 additions and 9 deletions.
2 changes: 2 additions & 0 deletions pyphare/pyphare/pharein/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ def add_vector_int(path, val):

add_int("simulation/AMR/tag_buffer", simulation.tag_buffer)

add_string("simulation/AMR/loadbalancing", simulation.loadbalancing)

refinement_boxes = simulation.refinement_boxes

def as_paths(rb):
Expand Down
13 changes: 13 additions & 0 deletions pyphare/pyphare/pharein/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,16 @@ def check_clustering(**kwargs):
return clustering


def check_loadbalancing(**kwargs):
valid_keys = ["nppc", "homogeneous"]
loadbalancing = kwargs.get("loadbalancing", "nppc")
if loadbalancing not in valid_keys:
raise ValueError(
f"Error: loadbalancing type is not supported, supported types are {valid_keys}"
)
return loadbalancing


# ------------------------------------------------------------------------------


Expand Down Expand Up @@ -605,6 +615,7 @@ def wrapper(simulation_object, **kwargs):
"restart_options",
"tag_buffer",
"description",
"loadbalancing",
]

accepted_keywords += check_optional_keywords(**kwargs)
Expand All @@ -625,6 +636,8 @@ def wrapper(simulation_object, **kwargs):

kwargs["clustering"] = check_clustering(**kwargs)

kwargs["loadbalancing"] = check_loadbalancing(**kwargs)

time_step_nbr, time_step, final_time = check_time(**kwargs)
kwargs["time_step_nbr"] = time_step_nbr
kwargs["time_step"] = time_step
Expand Down
7 changes: 7 additions & 0 deletions src/amr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ set( SOURCES_INC
level_initializer/hybrid_level_initializer.hpp
level_initializer/level_initializer_factory.hpp
data/field/field_variable_fill_pattern.hpp
load_balancing/load_balancer_manager.hpp
load_balancing/load_balancer_estimator.hpp
load_balancing/load_balancer_estimator_hybrid.hpp
load_balancing/load_balancer_hybrid_strategy_factory.hpp
load_balancing/load_balancer_hybrid_strategy.hpp
load_balancing/concrete_load_balancer_hybrid_strategy_homogeneous.hpp
load_balancing/concrete_load_balancer_hybrid_strategy_nppc.hpp
)
set( SOURCES_CPP
data/field/refine/linear_weighter.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@


#ifndef PHARE_CONCRERTE_LOAD_BALANCER_HYBRID_STRATEGY_HOMOGENEOUS_HPP
#define PHARE_CONCRERTE_LOAD_BALANCER_HYBRID_STRATEGY_HOMOGENEOUS_HPP

#include <SAMRAI/hier/PatchLevel.h>
#include <SAMRAI/pdat/CellData.h>
#include <string>

#include "amr/load_balancing/load_balancer_hybrid_strategy.hpp"
#include "amr/physical_models/physical_model.hpp"
#include "amr/types/amr_types.hpp"
#include "amr/resources_manager/amr_utils.hpp"
#include "core/data/ndarray/ndarray_vector.hpp"




namespace PHARE::amr
{
template<typename PHARE_T>
class ConcreteLoadBalancerHybridStrategyHomogeneous : public LoadBalancerHybridStrategy<PHARE_T>
{
public:
using HybridModel = typename PHARE_T::HybridModel_t;
using gridlayout_type = typename HybridModel::gridlayout_type;

ConcreteLoadBalancerHybridStrategyHomogeneous(int const id)
: id_{id}
{
}

void compute(SAMRAI::hier::PatchLevel& level,
PHARE::solver::IPhysicalModel<SAMRAI_Types>& model) override;


private:
int const id_;
};



template<typename PHARE_T>
void ConcreteLoadBalancerHybridStrategyHomogeneous<PHARE_T>::compute(
SAMRAI::hier::PatchLevel& level, PHARE::solver::IPhysicalModel<SAMRAI_Types>& model)
{
static auto constexpr dimension = HybridModel::dimension;
auto& hybridModel = dynamic_cast<HybridModel&>(model);
auto& resourcesManager = hybridModel.resourcesManager;
auto& ions = hybridModel.state.ions;

bool constexpr c_ordering = false;

for (auto& patch : level)
{
auto const& layout = layoutFromPatch<gridlayout_type>(*patch);

auto patch_data_lb
= dynamic_cast<SAMRAI::pdat::CellData<double>*>(patch->getPatchData(this->id_).get());
auto load_balancer_val = patch_data_lb->getPointer();

const auto& box = patch->getBox();

auto lb_view = core::NdArrayView<dimension, double, double*, c_ordering>(load_balancer_val,
layout.nbrCells());

auto _ = resourcesManager->setOnPatch(*patch, ions);

// The view on "load_balancer_val" do not have any ghost cells, meaning that this patch
// data lies on a box defind by the nbr of cells in the physical domain
// As the nbr of ghost cells in the box associated to the load balancer patch data is
// null, we hence loop on an AMR index (then needing to firstly get the AMR box)
// to get the AMRLocatStart and AMRLocalEnd.
// Then, we build "by hand" the local index for the "lb_view" considering that the nbr
// of ghost cell for this patch data is null.
auto amr_box = layout.AMRBox();

// The lb_view is a CellData, meaning that it is dual as the index of an amr box
auto amr_start = amr_box.lower;
auto amr_end = amr_box.upper;

// nbr of cells in the physical domain
auto nbrCells = layout.nbrCells();




if constexpr (dimension == 1)
{
for (auto i_loc = 0, i_amr = amr_start[0]; i_loc < nbrCells[0]; ++i_loc, ++i_amr)
{
auto amr_point{core::Point{i_amr}};
auto amr_index = amr_point.template toArray<int>();

lb_view(i_loc) = 1;
}
}



if constexpr (dimension == 2)
{
for (auto i_loc = 0, i_amr = amr_start[0]; i_loc < nbrCells[0]; ++i_loc, ++i_amr)
{
for (auto j_loc = 0, j_amr = amr_start[1]; j_loc < nbrCells[1]; ++j_loc, ++j_amr)
{
auto amr_point{core::Point{i_amr, j_amr}};
auto amr_index = amr_point.template toArray<int>();

lb_view(i_loc, j_loc) = 1;
std::cout << lb_view(i_loc, j_loc) << std::endl;
}
}
}


if constexpr (dimension == 3)
{
for (auto i_loc = 0, i_amr = amr_start[0]; i_loc < nbrCells[0]; ++i_loc, ++i_amr)
{
for (auto j_loc = 0, j_amr = amr_start[1]; j_loc < nbrCells[1]; ++j_loc, ++j_amr)
{
for (auto k_loc = 0, k_amr = amr_start[2]; k_loc < nbrCells[2];
++k_loc, ++k_amr)
{
auto amr_point{core::Point{i_amr, j_amr, k_amr}};
auto amr_index = amr_point.template toArray<int>();

lb_view(i_loc, j_loc, k_loc) = 1;
}
}
}
}
}
}

} // namespace PHARE::amr

#endif
173 changes: 173 additions & 0 deletions src/amr/load_balancing/concrete_load_balancer_hybrid_strategy_nppc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@


#ifndef PHARE_CONCRERTE_LOAD_BALANCER_HYBRID_STRATEGY_NPPC_HPP
#define PHARE_CONCRERTE_LOAD_BALANCER_HYBRID_STRATEGY_NPPC_HPP

#include <SAMRAI/hier/PatchLevel.h>
#include <SAMRAI/pdat/CellData.h>

#include <string>

#include "amr/load_balancing/load_balancer_hybrid_strategy.hpp"
#include "amr/physical_models/physical_model.hpp"
#include "amr/types/amr_types.hpp"
#include "amr/resources_manager/amr_utils.hpp"
#include "core/data/ndarray/ndarray_vector.hpp"




namespace PHARE::amr
{
template<typename PHARE_T>
class ConcreteLoadBalancerHybridStrategyNPPC : public LoadBalancerHybridStrategy<PHARE_T>
{
public:
using HybridModel = typename PHARE_T::HybridModel_t;
using gridlayout_type = typename HybridModel::gridlayout_type;

ConcreteLoadBalancerHybridStrategyNPPC(int const id)
: id_{id}
{
}

void compute(SAMRAI::hier::PatchLevel& level,
PHARE::solver::IPhysicalModel<SAMRAI_Types>& model) override;


private:
int const id_;
};



template<typename PHARE_T>
void ConcreteLoadBalancerHybridStrategyNPPC<PHARE_T>::compute(
SAMRAI::hier::PatchLevel& level, PHARE::solver::IPhysicalModel<SAMRAI_Types>& model)
{
static auto constexpr dimension = HybridModel::dimension;
auto& hybridModel = dynamic_cast<HybridModel&>(model);
auto& resourcesManager = hybridModel.resourcesManager;
auto& ions = hybridModel.state.ions;

bool constexpr c_ordering = false;

for (auto& patch : level)
{
auto const& layout = layoutFromPatch<gridlayout_type>(*patch);

auto patch_data_lb
= dynamic_cast<SAMRAI::pdat::CellData<double>*>(patch->getPatchData(this->id_).get());
auto load_balancer_val = patch_data_lb->getPointer();

const auto& box = patch->getBox();

auto lb_view = core::NdArrayView<dimension, double, double*, c_ordering>(load_balancer_val,
layout.nbrCells());

auto _ = resourcesManager->setOnPatch(*patch, ions);

// The view on "load_balancer_val" do not have any ghost cells, meaning that this patch
// data lies on a box defind by the nbr of cells in the physical domain
// As the nbr of ghost cells in the box associated to the load balancer patch data is
// null, we hence loop on an AMR index (then needing to firstly get the AMR box)
// to get the AMRLocatStart and AMRLocalEnd.
// Then, we build "by hand" the local index for the "lb_view" considering that the nbr
// of ghost cell for this patch data is null.
auto amr_box = layout.AMRBox();

// The lb_view is a CellData, meaning that it is dual as the index of an amr box
auto amr_start = amr_box.lower;
auto amr_end = amr_box.upper;

// nbr of cells in the physical domain
auto nbrCells = layout.nbrCells();




if constexpr (dimension == 1)
{
for (std::uint32_t i_loc = 0, i_amr = amr_start[0]; i_loc < nbrCells[0]; ++i_loc, ++i_amr)
{
auto amr_point{core::Point{i_amr}};
auto amr_index = amr_point.template toArray<int>();

std::size_t nbr = 0;

for (auto& pop : ions)
{
const auto& domainParticles = pop.domainParticles();

nbr += domainParticles.nbr_particles_in(amr_index);
}

lb_view(i_loc) = nbr;
}
}



if constexpr (dimension == 2)
{
for (std::uint32_t i_loc = 0, i_amr = amr_start[0]; i_loc < nbrCells[0]; ++i_loc, ++i_amr)
{
for (std::uint32_t j_loc = 0, j_amr = amr_start[1]; j_loc < nbrCells[1]; ++j_loc, ++j_amr)
{
auto amr_point{core::Point{i_amr, j_amr}};
auto amr_index = amr_point.template toArray<int>();

std::size_t nbr = 0;

for (auto& pop : ions)
{
const auto& domainParticles = pop.domainParticles();

nbr += domainParticles.nbr_particles_in(amr_index);
}

lb_view(i_loc, j_loc) = nbr;
}
}
}


if constexpr (dimension == 3)
{
for (std::uint32_t i_loc = 0, i_amr = amr_start[0]; i_loc < nbrCells[0]; ++i_loc, ++i_amr)
{
for (std::uint32_t j_loc = 0, j_amr = amr_start[1]; j_loc < nbrCells[1]; ++j_loc, ++j_amr)
{
for (std::uint32_t k_loc = 0, k_amr = amr_start[2]; k_loc < nbrCells[2];
++k_loc, ++k_amr)
{
auto amr_point{core::Point{i_amr, j_amr, k_amr}};
auto amr_index = amr_point.template toArray<int>();

std::size_t nbr = 0;

for (auto& pop : ions)
{
const auto& domainParticles = pop.domainParticles();

nbr += domainParticles.nbr_particles_in(amr_index);
}

lb_view(i_loc, j_loc, k_loc) = nbr;
}
}
}
}
}

// TODO here, we have the lb_view value correctly set on all patches. we also know the id_
// so this is where we should call setWorkloadPatchDataIndex... which is a method of the CascadePartitioner
// lb_view is a local container containing the datz
// the loadbalancezrmanager knows the id, as well as the loadbalancerestimator
// and the loadbalancerestimator is a cascadpartotioner

}

} // namespace PHARE::amr

#endif
Loading

0 comments on commit 73a722d

Please sign in to comment.