OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
LoadBalancer.hpp
Go to the documentation of this file.
1#ifndef OPAL_LOAD_BALANCER_H
2#define OPAL_LOAD_BALANCER_H
3
4#include <memory>
5
7
8template <typename T, unsigned Dim>
9using ORB = ippl::OrthogonalRecursiveBisection<Field<double, Dim>, T>;
10
11template <typename T, unsigned Dim>
13 using Base = ippl::ParticleBase<ippl::ParticleSpatialLayout<T, Dim>>;
14 using FieldSolver_t = ippl::FieldSolverBase<T, Dim>;
15
16private:
21 std::shared_ptr<ParticleContainer<T, Dim>> pc_m;
22 std::shared_ptr<FieldSolver_t> fs_m;
23 unsigned int loadbalancefreq_m;
25
26public:
28 double lbs, std::shared_ptr<FieldContainer<T, Dim>>& fc,
29 std::shared_ptr<ParticleContainer<T, Dim>>& pc, std::shared_ptr<FieldSolver_t>& fs)
31 rho_m(&fc->getRho()),
32 E_m(&fc->getE()),
33 phi_m(&fc->getPhi()),
34 pc_m(pc),
35 fs_m(fs) {
36 }
37
39 }
40
41 double getLoadBalanceThreshold() const {
43 }
44 void setLoadBalanceThreshold(double threshold) {
45 loadbalancethreshold_m = threshold;
46 }
47
49 return rho_m;
50 }
51 void setRho(Field_t<Dim>* rho) {
52 rho_m = rho;
53 }
54
56 return E_m;
57 }
59 E_m = E;
60 }
61
63 return phi_m;
64 }
65 void setPhi(Field<T, Dim>* phi) {
66 phi_m = phi;
67 }
68
69 std::shared_ptr<ParticleContainer<T, Dim>> getParticleContainer() const {
70 return pc_m;
71 }
73 pc_m = pc;
74 }
75
76 std::shared_ptr<FieldSolver_t> getFieldSolver() const {
77 return fs_m;
78 }
79 void setFieldSolver(std::shared_ptr<FieldSolver_t> fs) {
80 fs_m = fs;
81 }
82
84 ippl::FieldLayout<Dim>* fl, ippl::UniformCartesian<T, Dim>* mesh,
85 bool& isFirstRepartition) {
86 // Update local fields
87
88 static IpplTimings::TimerRef tupdateLayout = IpplTimings::getTimer("updateLayout");
89 IpplTimings::startTimer(tupdateLayout);
90 (*E_m).updateLayout(*fl);
91 (*rho_m).updateLayout(*fl);
92
93 if (fs_m->getStype() == "CG") {
94 phi_m->updateLayout(*fl);
95 phi_m->setFieldBC(phi_m->getFieldBC());
96 }
97
98 // Update layout with new FieldLayout
99 PLayout_t<T, Dim>* layout = &pc_m->getLayout();
100 (*layout).updateLayout(*fl, *mesh);
101 IpplTimings::stopTimer(tupdateLayout);
102 static IpplTimings::TimerRef tupdatePLayout = IpplTimings::getTimer("updatePB");
103 IpplTimings::startTimer(tupdatePLayout);
104 if (!isFirstRepartition) {
105 pc_m->update();
106 }
107 IpplTimings::stopTimer(tupdatePLayout);
108 }
109
110 void initializeORB(ippl::FieldLayout<Dim>* fl, ippl::UniformCartesian<T, Dim>* mesh) {
111 orb.initialize(*fl, *mesh, *rho_m);
112 }
113
115 ippl::FieldLayout<Dim>* fl, ippl::UniformCartesian<T, Dim>* mesh,
116 bool& isFirstRepartition) {
117 // Repartition the domains
118
119
120 using Base = ippl::ParticleBase<ippl::ParticleSpatialLayout<T, Dim>>;
121 typename Base::particle_position_type *R;
122 R = &pc_m->R;
123 bool res = orb.binaryRepartition(*R, *fl, isFirstRepartition);
124 if (res != true) {
125 std::cout << "Could not repartition!" << std::endl;
126 return;
127 }
128 // Update
129 this->updateLayout(fl, mesh, isFirstRepartition);
130 if constexpr (Dim == 2 || Dim == 3) {
131 if (fs_m->getStype() == "FFT") {
132 std::get<FFTSolver_t<T, Dim>>(fs_m->getSolver()).setRhs(*rho_m);
133 }
134 if constexpr (Dim == 3) {
135 if (fs_m->getStype() == "TG") {
136 std::get<FFTTruncatedGreenSolver_t<T, Dim>>(fs_m->getSolver()).setRhs(*rho_m);
137 } else if (fs_m->getStype() == "OPEN") {
138 std::get<OpenSolver_t<T, Dim>>(fs_m->getSolver()).setRhs(*rho_m);
139 }
140 }
141 }
142
143 }
144
145 bool balance(size_type totalP, const unsigned int nstep) {
146 if (ippl::Comm->size() < 2) {
147 return false;
148 } else {
149 int local = 0;
150 std::vector<int> res(ippl::Comm->size());
151 double equalPart = (double)totalP / ippl::Comm->size();
152 double dev = std::abs((double)pc_m->getLocalNum() - equalPart) / totalP;
153 if (dev > loadbalancethreshold_m) {
154 local = 1;
155 }
156 MPI_Allgather(
157 &local, 1, MPI_INT, res.data(), 1, MPI_INT, ippl::Comm->getCommunicator());
158
159 for (unsigned int i = 0; i < res.size(); i++) {
160 if (res[i] == 1) {
161 return true;
162 }
163 }
164 return false;
165 }
166 }
167};
168
169#endif
ippl::Field< double, Dim, ViewArgs... > Field_t
Definition PBunchDefs.h:30
ippl::Field< ippl::Vector< T, Dim >, Dim, ViewArgs... > VField_t
Definition PBunchDefs.h:33
typename ippl::ParticleSpatialLayout< T, Dim, Mesh_t< Dim > > PLayout_t
ippl::Field< T, Dim, Mesh_t< Dim >, Centering_t< Dim >, ViewArgs... > Field
ippl::detail::size_type size_type
double T
Definition datatypes.h:7
constexpr unsigned Dim
Definition datatypes.h:6
ippl::OrthogonalRecursiveBisection< Field< double, Dim >, T > ORB
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