OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
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<
14 ippl::ParticleSpatialLayout<T, Dim>, Kokkos::DefaultExecutionSpace::memory_space>;
15 using FieldSolver_t = ippl::FieldSolverBase<T, Dim>;
16
17private:
22 std::shared_ptr<ParticleContainer<T, Dim>> pc_m;
23 std::shared_ptr<FieldSolver_t> fs_m;
24 unsigned int loadbalancefreq_m;
26
27public:
29 double lbs, std::shared_ptr<FieldContainer<T, Dim>>& fc,
30 std::shared_ptr<ParticleContainer<T, Dim>>& pc, std::shared_ptr<FieldSolver_t>& fs)
32 rho_m(&fc->getRho()),
33 E_m(&fc->getE()),
34 phi_m(&fc->getPhi()),
35 pc_m(pc),
36 fs_m(fs) {}
37
39
41 void setLoadBalanceThreshold(double threshold) { loadbalancethreshold_m = threshold; }
42
43 Field_t<Dim>* getRho() const { return rho_m; }
44 void setRho(Field_t<Dim>* rho) { rho_m = rho; }
45
46 VField_t<T, Dim>* getE() const { return E_m; }
47 void setE(VField_t<T, Dim>* E) { E_m = E; }
48
49 Field<T, Dim>* getPhi() { return phi_m; }
50 void setPhi(Field<T, Dim>* phi) { phi_m = phi; }
51
52 std::shared_ptr<ParticleContainer<T, Dim>> getParticleContainer() const { return pc_m; }
53 void setParticleContainer(std::shared_ptr<ParticleContainer<T, Dim>> pc) { pc_m = pc; }
54
55 std::shared_ptr<FieldSolver_t> getFieldSolver() const { return fs_m; }
56 void setFieldSolver(std::shared_ptr<FieldSolver_t> fs) { fs_m = fs; }
57
59 ippl::FieldLayout<Dim>* fl, ippl::UniformCartesian<T, Dim>* mesh,
60 bool& isFirstRepartition) {
61 // Update local fields
62
63 static IpplTimings::TimerRef tupdateLayout = IpplTimings::getTimer("updateLayout");
64 IpplTimings::startTimer(tupdateLayout);
65 (*E_m).updateLayout(*fl);
66 (*rho_m).updateLayout(*fl);
67
68 if (fs_m->getStype() == "CG") {
69 phi_m->updateLayout(*fl);
70 phi_m->setFieldBC(phi_m->getFieldBC());
71 }
72
73 // Update layout with new FieldLayout
74 PLayout_t<T, Dim>* layout = &pc_m->getLayout();
75 (*layout).updateLayout(*fl, *mesh);
76 IpplTimings::stopTimer(tupdateLayout);
77 static IpplTimings::TimerRef tupdatePLayout = IpplTimings::getTimer("updatePB");
78 IpplTimings::startTimer(tupdatePLayout);
79 if (!isFirstRepartition) {
80 pc_m->update();
81 }
82 IpplTimings::stopTimer(tupdatePLayout);
83 }
84
85 void initializeORB(ippl::FieldLayout<Dim>* fl, ippl::UniformCartesian<T, Dim>* mesh) {
86 orb.initialize(*fl, *mesh, *rho_m);
87 }
88
90 ippl::FieldLayout<Dim>* fl, ippl::UniformCartesian<T, Dim>* mesh,
91 bool& isFirstRepartition) {
92 // Repartition the domains
93
94 using Base = ippl::ParticleBase<
95 ippl::ParticleSpatialLayout<T, Dim>, Kokkos::DefaultExecutionSpace::memory_space>;
96 typename Base::particle_position_type* R;
97 R = &pc_m->R;
98 bool res = orb.binaryRepartition(*R, *fl, isFirstRepartition);
99 if (res != true) {
100 std::cout << "Could not repartition!" << std::endl;
101 return;
102 }
103 // Update
104 this->updateLayout(fl, mesh, isFirstRepartition);
105 if constexpr (Dim == 2 || Dim == 3) {
106 if (fs_m->getStype() == "FFT") {
107 std::get<FFTSolver_t<T, Dim>>(fs_m->getSolver()).setRhs(*rho_m);
108 }
109 if constexpr (Dim == 3) {
110 if (fs_m->getStype() == "TG") {
111 std::get<FFTTruncatedGreenSolver_t<T, Dim>>(fs_m->getSolver()).setRhs(*rho_m);
112 } else if (fs_m->getStype() == "OPEN") {
113 std::get<OpenSolver_t<T, Dim>>(fs_m->getSolver()).setRhs(*rho_m);
114 }
115 }
116 }
117 }
118
119 bool balance(size_type totalP) {
120 if (ippl::Comm->size() < 2) {
121 return false;
122 } else {
123 int local = 0;
124 std::vector<int> res(ippl::Comm->size());
125 double equalPart = (double)totalP / ippl::Comm->size();
126 double dev = std::abs((double)pc_m->getLocalNum() - equalPart) / totalP;
127 if (dev > loadbalancethreshold_m) {
128 local = 1;
129 }
130 MPI_Allgather(
131 &local, 1, MPI_INT, res.data(), 1, MPI_INT, ippl::Comm->getCommunicator());
132
133 for (unsigned int i = 0; i < res.size(); i++) {
134 if (res[i] == 1) {
135 return true;
136 }
137 }
138 return false;
139 }
140 }
141};
142
143#endif
typename ippl::ParticleSpatialLayout< T, Dim, Mesh_t< Dim > > PLayout_t
ippl::Field< T, Dim, Mesh_t< Dim >, Centering_t< Dim >, ViewArgs... > Field
ippl::OrthogonalRecursiveBisection< Field< double, Dim >, T > ORB
double T
Definition OPALTypes.h:8
constexpr unsigned Dim
Definition OPALTypes.h:7
ippl::Field< double, Dim, ViewArgs... > Field_t
Definition PBunchDefs.h:28
ippl::Field< ippl::Vector< T, Dim >, Dim, ViewArgs... > VField_t
Definition PBunchDefs.h:31
ippl::detail::size_type size_type
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
ippl::ParticleBase< ippl::ParticleSpatialLayout< T, Dim >, Kokkos::DefaultExecutionSpace::memory_space > Base
void setRho(Field_t< Dim > *rho)
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)
std::shared_ptr< FieldSolver_t > fs_m
void updateLayout(ippl::FieldLayout< Dim > *fl, ippl::UniformCartesian< T, Dim > *mesh, bool &isFirstRepartition)
bool balance(size_type totalP)
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
Container for all per-particle (and per-simulation) fields tracked during OPALX tracking.