IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
LoadBalancer.hpp
Go to the documentation of this file.
1#ifndef IPPL_LOAD_BALANCER_H
2#define IPPL_LOAD_BALANCER_H
3
4#include <memory>
5
7
8template <typename T, unsigned Dim>
12
13private:
18 std::shared_ptr<ParticleContainer<T, Dim>> pc_m;
19 std::shared_ptr<FieldSolver_t> fs_m;
20 unsigned int loadbalancefreq_m;
22
23public:
24 LoadBalancer(double lbs, std::shared_ptr<FieldContainer<T, Dim>>& fc,
25 std::shared_ptr<ParticleContainer<T, Dim>>& pc, std::shared_ptr<FieldSolver_t>& fs)
27 , rho_m(&fc->getRho())
28 , E_m(&fc->getE())
29 , phi_m(&fc->getPhi())
30 , pc_m(pc)
31 , fs_m(fs) {}
32
34
36 void setLoadBalanceThreshold(double threshold) { loadbalancethreshold_m = threshold; }
37
38 Field_t<Dim>* getRho() const { return rho_m; }
39 void setRho(Field_t<Dim>* rho) { rho_m = rho; }
40
41 VField_t<T, Dim>* getE() const { return E_m; }
42 void setE(VField_t<T, Dim>* E) { E_m = E; }
43
44 Field<T, Dim>* getPhi() { return phi_m; }
45 void setPhi(Field<T, Dim>* phi) { phi_m = phi; }
46
47 std::shared_ptr<ParticleContainer<T, Dim>> getParticleContainer() const { return pc_m; }
48 void setParticleContainer(std::shared_ptr<ParticleContainer<T, Dim>> pc) { pc_m = pc; }
49
50 std::shared_ptr<FieldSolver_t> getFieldSolver() const { return fs_m; }
51 void setFieldSolver(std::shared_ptr<FieldSolver_t> fs) { fs_m = fs; }
52
54 bool& isFirstRepartition) {
55 // Update local fields
56
57 static IpplTimings::TimerRef tupdateLayout = IpplTimings::getTimer("updateLayout");
58 IpplTimings::startTimer(tupdateLayout);
59 (*E_m).updateLayout(*fl);
60 (*rho_m).updateLayout(*fl);
61
62 if (fs_m->getStype() == "CG" || fs_m->getStype() == "PCG") {
63 phi_m->updateLayout(*fl);
64 phi_m->setFieldBC(phi_m->getFieldBC());
65 }
66
67 // Update layout with new FieldLayout
68 PLayout_t<T, Dim>* layout = &pc_m->getLayout();
69 (*layout).updateLayout(*fl, *mesh);
70 IpplTimings::stopTimer(tupdateLayout);
71 static IpplTimings::TimerRef tupdatePLayout = IpplTimings::getTimer("updatePB");
72 IpplTimings::startTimer(tupdatePLayout);
73 if (!isFirstRepartition) {
74 pc_m->update();
75 }
76 IpplTimings::stopTimer(tupdatePLayout);
77 }
78
80 orb.initialize(*fl, *mesh, *rho_m);
81 }
82
84 bool& isFirstRepartition) {
85 // Repartition the domains
86
89 R = &pc_m->R;
90 bool res = orb.binaryRepartition(*R, *fl, isFirstRepartition);
91 if (res != true) {
92 std::cout << "Could not repartition!" << std::endl;
93 return;
94 }
95 // Update
96 this->updateLayout(fl, mesh, isFirstRepartition);
97 if constexpr (Dim == 2 || Dim == 3) {
98 if (fs_m->getStype() == "FFT") {
99 std::get<FFTSolver_t<T, Dim>>(fs_m->getSolver()).setRhs(*rho_m);
100 }
101 if constexpr (Dim == 3) {
102 if (fs_m->getStype() == "TG") {
104 } else if (fs_m->getStype() == "OPEN") {
105 std::get<OpenSolver_t<T, Dim>>(fs_m->getSolver()).setRhs(*rho_m);
106 }
107 }
108 }
109 }
110
111 bool balance(size_type totalP, const unsigned int nstep) {
112 if (ippl::Comm->size() < 2 && loadbalancethreshold_m != 1.0) {
113 return false;
114 }
115 if (std::strcmp(TestName, "UniformPlasmaTest") == 0) {
116 return (nstep % loadbalancefreq_m == 0);
117 } else {
118 int local = 0;
119 std::vector<int> res(ippl::Comm->size());
120 double equalPart = (double)totalP / ippl::Comm->size();
121 double dev = std::abs((double)pc_m->getLocalNum() - equalPart) / totalP;
122 if (dev > loadbalancethreshold_m) {
123 local = 1;
124 }
125 MPI_Allgather(&local, 1, MPI_INT, res.data(), 1, MPI_INT,
126 ippl::Comm->getCommunicator());
127
128 for (unsigned int i = 0; i < res.size(); i++) {
129 if (res[i] == 1) {
130 return true;
131 }
132 }
133 return false;
134 }
135 }
136};
137
138#endif
constexpr unsigned Dim
Field< Vector_t< T, Dim >, Dim, ViewArgs... > VField_t
Definition datatypes.h:44
ippl::detail::size_type size_type
Definition datatypes.h:23
const char * TestName
Field< double, Dim, ViewArgs... > Field_t
Definition datatypes.h:41
typename ippl::ParticleSpatialLayout< T, Dim, Mesh_t< Dim > > PLayout_t
Definition datatypes.h:15
ippl::OrthogonalRecursiveBisection< Field< double, Dim >, T > ORB
Definition datatypes.h:32
ippl::Field< T, Dim, Mesh_t< Dim >, Centering_t< Dim >, ViewArgs... > Field
Definition datatypes.h:29
KOKKOS_INLINE_FUNCTION auto & get(::ippl::Tuple< Ts... > &t)
Definition Tuple.h:362
std::unique_ptr< mpi::Communicator > Comm
Definition Ippl.h:22
typename ippl::ParticleSpatialLayout< T, Dim >::particle_position_type particle_position_type
Timing::TimerRef TimerRef
static TimerRef getTimer(const char *nm)
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)
std::shared_ptr< FieldSolver_t > getFieldSolver() const
double loadbalancethreshold_m
Field_t< Dim > * rho_m
void setParticleContainer(std::shared_ptr< ParticleContainer< T, Dim > > pc)
Field_t< Dim > * getRho() const
void setE(VField_t< T, Dim > *E)
void setLoadBalanceThreshold(double threshold)
Field< T, Dim > * getPhi()
LoadBalancer(double lbs, std::shared_ptr< FieldContainer< T, Dim > > &fc, std::shared_ptr< ParticleContainer< T, Dim > > &pc, std::shared_ptr< FieldSolver_t > &fs)
VField_t< T, Dim > * E_m
void setRho(Field_t< Dim > *rho)
bool balance(size_type totalP, const unsigned int nstep)
unsigned int loadbalancefreq_m
Field< T, Dim > * phi_m
double getLoadBalanceThreshold() const
VField_t< T, Dim > * getE() const
ippl::FieldSolverBase< T, Dim > FieldSolver_t
void repartition(ippl::FieldLayout< Dim > *fl, ippl::UniformCartesian< T, Dim > *mesh, bool &isFirstRepartition)
ippl::ParticleBase< ippl::ParticleSpatialLayout< T, Dim > > Base
std::shared_ptr< FieldSolver_t > fs_m
void updateLayout(ippl::FieldLayout< Dim > *fl, ippl::UniformCartesian< T, Dim > *mesh, bool &isFirstRepartition)
std::shared_ptr< ParticleContainer< T, Dim > > getParticleContainer() const
void setPhi(Field< T, Dim > *phi)
void setFieldSolver(std::shared_ptr< FieldSolver_t > fs)
void initializeORB(ippl::FieldLayout< Dim > *fl, ippl::UniformCartesian< T, Dim > *mesh)
std::shared_ptr< ParticleContainer< T, Dim > > pc_m
ORB< T, Dim > orb