IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
FieldSolver.hpp
Go to the documentation of this file.
1#ifndef IPPL_FIELD_SOLVER_H
2#define IPPL_FIELD_SOLVER_H
3
4#include <memory>
5
8
9// Define the FieldSolver class
10template <typename T, unsigned Dim>
11class FieldSolver : public ippl::FieldSolverBase<T, Dim> {
12private:
16 std::vector<std::string> preconditioner_params_m;
17
18public:
19 FieldSolver(std::string solver, Field_t<Dim>* rho, VField_t<T, Dim>* E, Field<T, Dim>* phi,
20 std::vector<std::string> preconditioner_params = {})
21 : ippl::FieldSolverBase<T, Dim>(solver)
22 , rho_m(rho)
23 , E_m(E)
24 , phi_m(phi)
25 , preconditioner_params_m(preconditioner_params) {
27 }
28
30
31 Field_t<Dim>* getRho() const { return rho_m; }
32 void setRho(Field_t<Dim>* rho) { rho_m = rho; }
33
34 VField_t<T, Dim>* getE() const { return E_m; }
35 void setE(VField_t<T, Dim>* E) { E_m = E; }
36
37 Field<T, Dim>* getPhi() const { return phi_m; }
38 void setPhi(Field<T, Dim>* phi) { phi_m = phi; }
39
40 void initSolver() override {
41 Inform m("solver ");
42 if (this->getStype() == "FFT") {
44 } else if (this->getStype() == "CG") {
46 } else if (this->getStype() == "TG") {
48 } else if (this->getStype() == "PCG") {
50 } else if (this->getStype() == "OPEN") {
52 } else {
53 m << "No solver matches the argument" << endl;
54 }
55 }
56
58 // CG requires explicit periodic boundary conditions while the periodic Poisson solver
59 // simply assumes them
60 typedef ippl::BConds<Field<T, Dim>, Dim> bc_type;
61 if (this->getStype() == "CG" || this->getStype() == "PCG") {
62 bc_type allPeriodic;
63 for (unsigned int i = 0; i < 2 * Dim; ++i) {
64 allPeriodic[i] = std::make_shared<ippl::PeriodicFace<Field<T, Dim>>>(i);
65 }
66 phi_m->setFieldBC(allPeriodic);
67 }
68 }
69
70 void runSolver() override {
71 if ((this->getStype() == "CG") || (this->getStype() == "PCG")) {
73 solver.solve();
74
75 if (ippl::Comm->rank() == 0) {
76 std::stringstream fname;
77 if (this->getStype() == "CG") {
78 fname << "data_CG/CG_";
79 } else {
80 fname << "data_";
81 fname << preconditioner_params_m[0];
82 fname << "/";
83 fname << preconditioner_params_m[0];
84 fname << "_";
85 }
86 fname << ippl::Comm->size();
87 fname << ".csv";
88
89 Inform log(NULL, fname.str().c_str(), Inform::APPEND);
90 int iterations = solver.getIterationCount();
91 // Assume the dummy solve is the first call
92 if (iterations == 0) {
93 log << "residue,iterations" << endl;
94 }
95 // Don't print the dummy solve
96 if (iterations > 0) {
97 log << solver.getResidue() << "," << iterations << endl;
98 }
99 }
100 ippl::Comm->barrier();
101 } else if (this->getStype() == "FFT") {
102 if constexpr (Dim == 2 || Dim == 3) {
103 std::get<FFTSolver_t<T, Dim>>(this->getSolver()).solve();
104 }
105 } else if (this->getStype() == "TG") {
106 if constexpr (Dim == 3) {
108 }
109 } else if (this->getStype() == "OPEN") {
110 if constexpr (Dim == 3) {
112 }
113 } else {
114 throw std::runtime_error("Unknown solver type");
115 }
116 }
117
118 template <typename Solver>
120 this->getSolver().template emplace<Solver>();
121 Solver& solver = std::get<Solver>(this->getSolver());
122
123 solver.mergeParameters(sp);
124
125 solver.setRhs(*rho_m);
126
127 if constexpr (std::is_same_v<Solver, CGSolver_t<T, Dim>>) {
128 // The CG solver computes the potential directly and
129 // uses this to get the electric field
130 solver.setLhs(*phi_m);
131 solver.setGradient(*E_m);
132 } else {
133 // The periodic Poisson solver, Open boundaries solver,
134 // and the TG solver compute the electric field directly
135 solver.setLhs(*E_m);
136 }
137 }
138
140 if constexpr (Dim == 2 || Dim == 3) {
142 sp.add("output_type", FFTSolver_t<T, Dim>::GRAD);
143 sp.add("use_heffte_defaults", false);
144 sp.add("use_pencils", true);
145 sp.add("use_reorder", false);
146 sp.add("use_gpu_aware", true);
147 sp.add("comm", ippl::p2p_pl);
148 sp.add("r2c_direction", 0);
149
151 } else {
152 throw std::runtime_error("Unsupported dimensionality for FFT solver");
153 }
154 }
155
158 sp.add("output_type", CGSolver_t<T, Dim>::GRAD);
159 // Increase tolerance in the 1D case
160 sp.add("tolerance", 1e-10);
161
163 }
164
167 sp.add("solver", "preconditioned");
168 sp.add("output_type", CGSolver_t<T, Dim>::GRAD);
169 // Increase tolerance in the 1D case
170 sp.add("tolerance", 1e-10);
171
172 int arg = 0;
173
174 int gauss_seidel_inner_iterations;
175 int gauss_seidel_outer_iterations;
176 int newton_level;
177 int chebyshev_degree;
178 int richardson_iterations;
179 int communication = 0;
180 double ssor_omega;
181 std::string preconditioner_type = "";
182
183 preconditioner_type = preconditioner_params_m[arg++];
184 if (preconditioner_type == "newton") {
185 newton_level = std::stoi(preconditioner_params_m[arg++]);
186 } else if (preconditioner_type == "chebyshev") {
187 chebyshev_degree = std::stoi(preconditioner_params_m[arg++]);
188 } else if (preconditioner_type == "richardson") {
189 richardson_iterations = std::stoi(preconditioner_params_m[arg++]);
190 communication = std::stoi(preconditioner_params_m[arg++]);
191 } else if (preconditioner_type == "gauss-seidel") {
192 gauss_seidel_inner_iterations = std::stoi(preconditioner_params_m[arg++]);
193 gauss_seidel_outer_iterations = std::stoi(preconditioner_params_m[arg++]);
194 communication = std::stoi(preconditioner_params_m[arg++]);
195 } else if (preconditioner_type == "ssor") {
196 gauss_seidel_inner_iterations = std::stoi(preconditioner_params_m[arg++]);
197 gauss_seidel_outer_iterations = std::stoi(preconditioner_params_m[arg++]);
198 ssor_omega = std::stod(preconditioner_params_m[arg++]);
199 }
200
201 sp.add("preconditioner_type", preconditioner_type);
202 sp.add("gauss_seidel_inner_iterations", gauss_seidel_inner_iterations);
203 sp.add("gauss_seidel_outer_iterations", gauss_seidel_outer_iterations);
204 sp.add("newton_level", newton_level);
205 sp.add("chebyshev_degree", chebyshev_degree);
206 sp.add("richardson_iterations", richardson_iterations);
207 sp.add("communication", communication);
208 sp.add("ssor_omega", ssor_omega);
209
211 }
212
214 if constexpr (Dim == 3) {
217 sp.add("use_heffte_defaults", false);
218 sp.add("use_pencils", true);
219 sp.add("use_reorder", false);
220 sp.add("use_gpu_aware", true);
221 sp.add("comm", ippl::p2p_pl);
222 sp.add("r2c_direction", 0);
223
225 } else {
226 throw std::runtime_error("Unsupported dimensionality for TG solver");
227 }
228 }
229
231 if constexpr (Dim == 3) {
233 sp.add("output_type", OpenSolver_t<T, Dim>::GRAD);
234 sp.add("use_heffte_defaults", false);
235 sp.add("use_pencils", true);
236 sp.add("use_reorder", false);
237 sp.add("use_gpu_aware", true);
238 sp.add("comm", ippl::p2p_pl);
239 sp.add("r2c_direction", 0);
240 sp.add("algorithm", OpenSolver_t<T, Dim>::HOCKNEY);
241
243 } else {
244 throw std::runtime_error("Unsupported dimensionality for OPEN solver");
245 }
246 }
247};
248#endif
constexpr unsigned Dim
Field< Vector_t< T, Dim >, Dim, ViewArgs... > VField_t
Definition datatypes.h:44
Field< double, Dim, ViewArgs... > Field_t
Definition datatypes.h:41
ConditionalType< Dim==3, ippl::FFTOpenPoissonSolver< VField_t< T, Dim >, Field_t< Dim > > > OpenSolver_t
Definition datatypes.h:64
ippl::Field< T, Dim, Mesh_t< Dim >, Centering_t< Dim >, ViewArgs... > Field
Definition datatypes.h:29
ConditionalType< Dim==2||Dim==3, ippl::FFTPeriodicPoissonSolver< VField_t< T, Dim >, Field_t< Dim > > > FFTSolver_t
Definition datatypes.h:55
ippl::PoissonCG< Field< T, Dim >, Field_t< Dim > > CGSolver_t
Definition datatypes.h:47
ConditionalType< Dim==3, ippl::FFTTruncatedGreenPeriodicPoissonSolver< VField_t< T, Dim >, Field_t< Dim > > > FFTTruncatedGreenSolver_t
Definition datatypes.h:59
Inform & endl(Inform &inf)
Definition Inform.cpp:42
KOKKOS_INLINE_FUNCTION auto & get(::ippl::Tuple< Ts... > &t)
Definition Tuple.h:362
Definition Archive.h:20
@ p2p_pl
Definition FFT.h:59
std::unique_ptr< mpi::Communicator > Comm
Definition Ippl.h:22
Solver_t< T, Dim > & getSolver()
std::string & getStype()
FieldSolverBase(std::string solver)
int getIterationCount()
Definition PoissonCG.h:139
void solve() override
Definition PoissonCG.h:123
Tlhs getResidue() const
Definition PoissonCG.h:145
@ APPEND
Definition Inform.h:45
void add(const std::string &key, const T &value)
void initTGSolver()
VField_t< T, Dim > * getE() const
void initPCGSolver()
FieldSolver(std::string solver, Field_t< Dim > *rho, VField_t< T, Dim > *E, Field< T, Dim > *phi, std::vector< std::string > preconditioner_params={})
Field< T, Dim > * phi_m
void setRho(Field_t< Dim > *rho)
void setPhi(Field< T, Dim > *phi)
void initSolver() override
void initFFTSolver()
void initCGSolver()
void runSolver() override
void initSolverWithParams(const ippl::ParameterList &sp)
Field< T, Dim > * getPhi() const
void initOpenSolver()
void setE(VField_t< T, Dim > *E)
VField_t< T, Dim > * E_m
std::vector< std::string > preconditioner_params_m
Field_t< Dim > * rho_m
void setPotentialBCs()
Field_t< Dim > * getRho() const