OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
FieldSolver.cpp
Go to the documentation of this file.
1//
2// Class FieldSolver
3// The class for the OPAL FIELDSOLVER command.
4// A FieldSolver definition is used by most physics commands to define the
5// particle charge and the reference momentum, together with some other data.
6//
7// Copyright (c) 200x - 2022, Paul Scherrer Institut, Villigen PSI, Switzerland
8//
9// All rights reserved
10//
11// This file is part of OPAL.
12//
13// OPAL is free software: you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation, either version 3 of the License, or
16// (at your option) any later version.
17//
18// You should have received a copy of the GNU General Public License
19// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
20//
22
30#include "Physics/Physics.h"
33#ifdef HAVE_SAAMG_SOLVER
35#endif
39
40#ifdef ENABLE_AMR
41 #include "Amr/AmrBoxLib.h"
42#ifdef AMREX_ENABLE_FBASELIB
44#endif
46 #include "Amr/AmrDefs.h"
48#endif
49
50#ifdef HAVE_AMR_MG_SOLVER
52#endif
53
54#include <map>
55
56using namespace Expressions;
57
58//TODO: o add a FIELD for DISCRETIZATION, MAXITERS, TOL...
59
60// The attributes of class FieldSolver.
61namespace {
62 namespace deprecated {
63 enum {
64 BCFFTT,
65 SIZE
66 };
67 }
68 enum {
69 FSTYPE = deprecated::SIZE, // The field solver name
70 // FOR FFT BASED SOLVER
71 MX, // mesh sixe in x
72 MY, // mesh sixe in y
73 MT, // mesh sixe in z
74 PARFFTX, // parallelized grid in x
75 PARFFTY, // parallelized grid in y
76 PARFFTT, // parallelized grid in z
77 BCFFTX, // boundary condition in x [FFT + AMR_MG only]
78 BCFFTY, // boundary condition in y [FFT + AMR_MG only]
79 BCFFTZ, // boundary condition in z [FFT + AMR_MG only]
80 GREENSF, // holds greensfunction to be used [FFT + P3M only]
81 BBOXINCR, // how much the boundingbox is increased
82 GEOMETRY, // geometry of boundary [SAAMG only]
83 ITSOLVER, // iterative solver [SAAMG + AMR_MG]
84 INTERPL, // interpolation used for boundary points [SAAMG only]
85 TOL, // tolerance of the SAAMG preconditioned solver [SAAMG only]
86 MAXITERS, // max number of iterations [SAAMG only]
87 PRECMODE, // preconditioner mode [SAAMG only]
88 RC, // cutoff radius for PP interactions
89 ALPHA, // Green’s function splitting parameter
90#ifdef ENABLE_AMR
91 AMR_MAXLEVEL, // AMR, maximum refinement level
92 AMR_REFX, // AMR, refinement ratio in x
93 AMR_REFY, // AMR, refinement ratio in y
94 AMR_REFZ, // AMR, refinement ration in z
95 AMR_MAXGRIDX, // AMR, maximum grid size in x (default: 16)
96 AMR_MAXGRIDY, // AMR, maximum grid size in y (default: 16)
97 AMR_MAXGRIDZ, // AMR, maximum grid size in z (default: 16)
98 AMR_BFX, // AMR, blocking factor in x (maxgrid needs to be a multiple, default: 8)
99 AMR_BFY, // AMR, blocking factor in y (maxgrid needs to be a multiple, default: 8)
100 AMR_BFZ, // AMR, blocking factor in z (maxgrid needs to be a multiple, default: 8)
101 AMR_TAGGING,
102 AMR_DENSITY,
103 AMR_MAX_NUM_PART,
104 AMR_MIN_NUM_PART,
105 AMR_SCALING,
106 AMR_DOMAIN_RATIO,
107#endif
108#ifdef HAVE_AMR_MG_SOLVER
109 // AMR_MG = Adaptive-Mesh-Refinement Multi-Grid
110 AMR_MG_SMOOTHER, // AMR, smoother for level solution
111 AMR_MG_NSWEEPS, // AMR, number of smoothing sweeps
112 AMR_MG_PREC, // AMR, preconditioner for bottom solver
113 AMR_MG_INTERP, // AMR, interpolater for solution from level l to l+1
114 AMR_MG_NORM, // AMR, norm convergence criteria
115 AMR_MG_VERBOSE, // AMR, enable solver info writing (SDDS file)
116 AMR_MG_REBALANCE, // AMR, rebalance smoothed aggregation (SA) preconditioner
117 AMR_MG_REUSE, // AMR, reuse type of SA (NONE, RP, RAP, SYMBOLIC or FULL)
118 AMR_MG_TOL, // AMR, tolerance of solver
119#endif
120 // FOR XXX BASED SOLVER
121 SIZE
122 };
123}
124
125
127 Definition(SIZE, "FIELDSOLVER",
128 "The \"FIELDSOLVER\" statement defines data for a the field solver") {
129
130 itsAttr[FSTYPE] = Attributes::makePredefinedString("FSTYPE", "Name of the attached field solver.",
131 {"FFT", "FFTPERIODIC", "SAAMG", "FMG", "ML", "AMR_MG", "NONE","P3M"});
132
133 itsAttr[MX] = Attributes::makeReal("MX", "Meshsize in x");
134 itsAttr[MY] = Attributes::makeReal("MY", "Meshsize in y");
135 itsAttr[MT] = Attributes::makeReal("MT", "Meshsize in z(t)");
136
137 itsAttr[PARFFTX] = Attributes::makeBool("PARFFTX",
138 "True, dimension 0 i.e x is parallelized",
139 false);
140
141 itsAttr[PARFFTY] = Attributes::makeBool("PARFFTY",
142 "True, dimension 1 i.e y is parallelized",
143 false);
144
145 itsAttr[PARFFTT] = Attributes::makeBool("PARFFTT",
146 "True, dimension 2 i.e z(t) is parallelized",
147 true);
148
149 //FFT ONLY:
150 itsAttr[BCFFTX] = Attributes::makePredefinedString("BCFFTX",
151 "Boundary conditions in x.",
152 {"OPEN", "DIRICHLET", "PERIODIC"},
153 "OPEN");
154
155 itsAttr[BCFFTY] = Attributes::makePredefinedString("BCFFTY",
156 "Boundary conditions in y.",
157 {"OPEN", "DIRICHLET", "PERIODIC"},
158 "OPEN");
159
160 itsAttr[BCFFTZ] = Attributes::makePredefinedString("BCFFTZ",
161 "Boundary conditions in z(t).",
162 {"OPEN", "DIRICHLET", "PERIODIC"},
163 "OPEN");
164
165 itsAttr[deprecated::BCFFTT] = Attributes::makePredefinedString("BCFFTT",
166 "Boundary conditions in z(t).",
167 {"OPEN", "DIRICHLET", "PERIODIC"},
168 "OPEN");
169
170 //GREENSF is also used in P3M
171 itsAttr[GREENSF] = Attributes::makePredefinedString("GREENSF",
172 "Which Greensfunction to be used.",
173 {"STANDARD", "INTEGRATED"},
174 "INTEGRATED");
175
176 itsAttr[BBOXINCR] = Attributes::makeReal("BBOXINCR",
177 "Increase of bounding box in % ",
178 2.0);
179
180 // P3M only:
181 itsAttr[RC] = Attributes::makeReal("RC",
182 "cutoff radius for PP interactions",
183 0.0);
184
186 "Standard Ewald Green’s function splitting parameter",
187 1e8);
188 //SAAMG and in case of FFT with dirichlet BC in x and y
189 itsAttr[GEOMETRY] = Attributes::makeUpperCaseString("GEOMETRY",
190 "GEOMETRY to be used as domain boundary",
191 "");
192
193 itsAttr[ITSOLVER] = Attributes::makePredefinedString("ITSOLVER",
194 "Type of iterative solver.",
195 {"CG",
196 "BICGSTAB",
197 "GMRES",
198 "MINRES",
199 "PCPG",
200 "STOCHASTIC_CG",
201 "RECYCLING_CG",
202 "RECYCLING_GMRES",
203 "KLU2",
204 "SUPERLU",
205 "UMFPACK",
206 "PARDISO_MKL",
207 "MUMPS",
208 "LAPACK",
209 "SA"},
210 "CG");
211
212 itsAttr[INTERPL] = Attributes::makePredefinedString("INTERPL",
213 "interpolation used for boundary points.",
214 {"CONSTANT", "LINEAR", "QUADRATIC"},
215 "LINEAR");
216
217 itsAttr[TOL] = Attributes::makeReal("TOL",
218 "Tolerance for iterative solver",
219 1e-8);
220
221 itsAttr[MAXITERS] = Attributes::makeReal("MAXITERS",
222 "Maximum number of iterations of iterative solver",
223 100);
224
225 itsAttr[PRECMODE] = Attributes::makePredefinedString("PRECMODE",
226 "Preconditioner Mode.",
227 {"STD", "HIERARCHY", "REUSE"},
228 "HIERARCHY");
229
230 // AMR
231#ifdef ENABLE_AMR
232 itsAttr[AMR_MAXLEVEL] = Attributes::makeReal("AMR_MAXLEVEL",
233 "Maximum number of levels in AMR",
234 0);
235
236 itsAttr[AMR_REFX] = Attributes::makeReal("AMR_REFX",
237 "Refinement ration in x-direction in AMR",
238 2);
239
240 itsAttr[AMR_REFY] = Attributes::makeReal("AMR_REFY",
241 "Refinement ration in y-direction in AMR",
242 2);
243
244 itsAttr[AMR_REFZ] = Attributes::makeReal("AMR_REFZ",
245 "Refinement ration in z-direction in AMR",
246 2);
247
248 itsAttr[AMR_MAXGRIDX] = Attributes::makeReal("AMR_MAXGRIDX",
249 "Maximum grid size in x for AMR",
250 16);
251
252 itsAttr[AMR_MAXGRIDY] = Attributes::makeReal("AMR_MAXGRIDY",
253 "Maximum grid size in y for AMR",
254 16);
255
256 itsAttr[AMR_MAXGRIDZ] = Attributes::makeReal("AMR_MAXGRIDZ",
257 "Maximum grid size in z for AMR",
258 16);
259
260 itsAttr[AMR_BFX] = Attributes::makeReal("AMR_BFX",
261 "Blocking factor in x for AMR (AMR_MAXGRIDX needs to be a multiple)",
262 8);
263
264 itsAttr[AMR_BFY] = Attributes::makeReal("AMR_BFY",
265 "Blocking factor in y for AMR (AMR_MAXGRIDY needs to be a multiple)",
266 8);
267
268 itsAttr[AMR_BFZ] = Attributes::makeReal("AMR_BFZ",
269 "Blocking factor in y for AMR (AMR_MAXGRIDZ needs to be a multiple)",
270 8);
271
272 itsAttr[AMR_TAGGING] = Attributes::makeUpperCaseString("AMR_TAGGING",
273 "Refinement criteria [CHARGE_DENSITY | POTENTIAL | EFIELD | MIN_NUM_PARTICLES | MAX_NUM_PARTICLES]",
274 "CHARGE_DENSITY");
275
276 itsAttr[AMR_DENSITY] = Attributes::makeReal("AMR_DENSITY",
277 "Tagging value for charge density refinement [C / cell volume]",
278 1.0e-14);
279
280 itsAttr[AMR_MAX_NUM_PART] = Attributes::makeReal("AMR_MAX_NUM_PART",
281 "Tagging value for max. #particles",
282 1);
283
284 itsAttr[AMR_MIN_NUM_PART] = Attributes::makeReal("AMR_MIN_NUM_PART",
285 "Tagging value for min. #particles",
286 1);
287
288 itsAttr[AMR_SCALING] = Attributes::makeReal("AMR_SCALING",
289 "Scaling value for maximum value tagging "
290 "(only POTENTIAL / CHARGE_DENSITY / "
291 "MOMENTA)", 0.75);
292
293 itsAttr[AMR_DOMAIN_RATIO] = Attributes::makeRealArray("AMR_DOMAIN_RATIO",
294 "Box ratio of AMR computation domain. Default: [-1, 1]^3");
295
296 // default
297 Attributes::setRealArray(itsAttr[AMR_DOMAIN_RATIO], {1.0, 1.0, 1.0});
298#endif
299
300#ifdef HAVE_AMR_MG_SOLVER
301 itsAttr[AMR_MG_SMOOTHER] = Attributes::makePredefinedString("AMR_MG_SMOOTHER",
302 "Smoothing of level solution.",
303 {"GS", "SGS", "JACOBI"}, "GS");
304
305 itsAttr[AMR_MG_NSWEEPS] = Attributes::makeReal("AMR_MG_NSWEEPS",
306 "Number of relaxation steps",
307 8);
308
309 itsAttr[AMR_MG_PREC] = Attributes::makePredefinedString("AMR_MG_PREC",
310 "Preconditioner of bottom solver.",
311 {"NONE", "ILUT", "CHEBYSHEV", "RILUK", "JACOBI", "BLOCK_JACOBI", "GS", "BLOCK_GS", "SA"},
312 "NONE");
313
314 itsAttr[AMR_MG_INTERP] = Attributes::makePredefinedString("AMR_MG_INTERP",
315 "Interpolater between levels.",
316 {"TRILINEAR", "LAGRANGE", "PC"},
317 "PC");
318
319 itsAttr[AMR_MG_NORM] = Attributes::makePredefinedString("AMR_MG_NORM",
320 "Norm for convergence criteria.",
321 {"L1_NORM", "L2_NORM", "LINF_NORM"},
322 "LINF_NORM");
323
324 itsAttr[AMR_MG_VERBOSE] = Attributes::makeBool("AMR_MG_VERBOSE",
325 "Write solver info in SDDS format (*.solver)",
326 false);
327
328 itsAttr[AMR_MG_REBALANCE] = Attributes::makeBool("AMR_MG_REBALANCE",
329 "Rebalancing of Smoothed Aggregation "
330 "Preconditioner",
331 false);
332
333 itsAttr[AMR_MG_REUSE] = Attributes::makePredefinedString("AMR_MG_REUSE",
334 "Reuse type of Smoothed Aggregation.",
335 {"NONE", "RP", "RAP", "SYMBOLIC", "FULL"},
336 "RAP");
337
338 itsAttr[AMR_MG_TOL] = Attributes::makeReal("AMR_MG_TOL",
339 "AMR MG solver tolerance (default: 1.0e-10)",
340 1.0e-10);
341#endif
342
343 mesh_m = 0;
344 FL_m = 0;
345 PL_m.reset(nullptr);
346 solver_m = 0;
347
349}
350
351
352FieldSolver::FieldSolver(const std::string& name, FieldSolver* parent):
353 Definition(name, parent)
354{
355 mesh_m = 0;
356 FL_m = 0;
357 PL_m.reset(nullptr);
358 solver_m = 0;
359}
360
361
363 if (mesh_m) {
364 delete mesh_m;
365 mesh_m = 0;
366 }
367 if (FL_m) {
368 delete FL_m;
369 FL_m = 0;
370 }
371 if (solver_m) {
372 delete solver_m;
373 solver_m = 0;
374 }
375}
376
377FieldSolver* FieldSolver::clone(const std::string& name) {
378 return new FieldSolver(name, this);
379}
380
385
386FieldSolver* FieldSolver::find(const std::string& name) {
387 FieldSolver* fs = dynamic_cast<FieldSolver*>(OpalData::getInstance()->find(name));
388
389 if (fs == 0) {
390 throw OpalException("FieldSolver::find()", "FieldSolver \"" + name + "\" not found.");
391 }
392 return fs;
393}
394
395std::string FieldSolver::getType() {
396 return Attributes::getString(itsAttr[FSTYPE]);
397}
398
399double FieldSolver::getMX() const {
400 return Attributes::getReal(itsAttr[MX]);
401}
402
403double FieldSolver::getMY() const {
404 return Attributes::getReal(itsAttr[MY]);
405}
406
407double FieldSolver::getMT() const {
408 return Attributes::getReal(itsAttr[MT]);
409}
410
411void FieldSolver::setMX(double value) {
412 Attributes::setReal(itsAttr[MX], value);
413}
414
415void FieldSolver::setMY(double value) {
416 Attributes::setReal(itsAttr[MY], value);
417}
418
419void FieldSolver::setMT(double value) {
420 Attributes::setReal(itsAttr[MT], value);
421}
422
424
425}
426
428
429 e_dim_tag decomp[3] = {SERIAL, SERIAL, SERIAL};
430
431 NDIndex<3> domain;
432 domain[0] = Index((int)getMX() + 1);
433 domain[1] = Index((int)getMY() + 1);
434 domain[2] = Index((int)getMT() + 1);
435
436 if (Attributes::getBool(itsAttr[PARFFTX]))
437 decomp[0] = PARALLEL;
438 if (Attributes::getBool(itsAttr[PARFFTY]))
439 decomp[1] = PARALLEL;
440 if (Attributes::getBool(itsAttr[PARFFTT]))
441 decomp[2] = PARALLEL;
442
443 if (Attributes::getString(itsAttr[FSTYPE]) == "FFTPERIODIC") {
444 decomp[0] = decomp[1] = SERIAL;
445 decomp[2] = PARALLEL;
446 }
447 // create prototype mesh and layout objects for this problem domain
448
449 if ( !isAmrSolverType() ) {
450 mesh_m = new Mesh_t(domain);
451 FL_m = new FieldLayout_t(*mesh_m, decomp);
452 PL_m.reset(new Layout_t(*FL_m, *mesh_m));
453 // OpalData::getInstance()->setMesh(mesh_m);
454 // OpalData::getInstance()->setFieldLayout(FL_m);
455 // OpalData::getInstance()->setLayout(PL_m);
456 }
457}
458
460 if (itsAttr[BCFFTZ].defaultUsed() &&
461 !itsAttr[deprecated::BCFFTT].defaultUsed()) {
462 return itsAttr[deprecated::BCFFTT];
463 }
464
465 return itsAttr[BCFFTZ];
466}
467
469 std::string bcz = Attributes::getString(getBCZAttribute());
470
471 return (bcz == "PERIODIC");
472}
473
478 throw OpalException("FieldSolver::isAmrSolverType",
479 "The attribute \"FSTYPE\" has not correct type for AMR solver");
480 } else {
481 return Options::amr;
482 }
483}
484
486 static const std::map<std::string, FieldSolverType> stringFSType_s = {
487 {"NONE", FieldSolverType::NONE},
488 {"FFT", FieldSolverType::FFT},
489 {"FFTBOX", FieldSolverType::FFTBOX},
490 {"SAAMG", FieldSolverType::SAAMG},
491 {"P3M", FieldSolverType::P3M},
492 {"FMG", FieldSolverType::FMG},
493 {"ML", FieldSolverType::ML},
494 {"AMR_MG", FieldSolverType::AMRMG},
495 {"HYPRE", FieldSolverType::HYPRE},
496 {"HPGMG", FieldSolverType::HPGMG}
497 };
498 fsName_m = getType();
499 if (fsName_m.empty()) {
500 throw OpalException("FieldSolver::setFieldSolverType",
501 "The attribute \"FSTYPE\" isn't set for \"FIELDSOLVER\"!");
502 } else {
503 fsType_m = stringFSType_s.at(fsName_m);
504 }
505}
506
508 itsBunch_m = b;
509
510 std::string greens = Attributes::getString(itsAttr[GREENSF]);
511 std::string bcx = Attributes::getString(itsAttr[BCFFTX]);
512 std::string bcy = Attributes::getString(itsAttr[BCFFTY]);
513 std::string bcz = Attributes::getString(getBCZAttribute());
514
515 if ( isAmrSolverType() ) {
516 Inform m("FieldSolver::initAmrSolver");
517
518#ifdef ENABLE_AMR
520
522#endif
523 } else if (fsType_m == FieldSolverType::FFT) {
524 bool sinTrafo = ((bcx == "DIRICHLET") && (bcy == "DIRICHLET") && (bcz == "DIRICHLET"));
525 if (sinTrafo) {
526 std::cout << "FFTBOX ACTIVE" << std::endl;
527 //we go over all geometries and add the Geometry Elements to the geometry list
528 std::string geoms = Attributes::getString(itsAttr[GEOMETRY]);
529 std::string tmp;
530 //split and add all to list
531 std::vector<BoundaryGeometry*> geometries;
532 for (unsigned int i = 0; i <= geoms.length(); i++) {
533 if (i == geoms.length() || geoms[i] == ',') {
535 if (geom != 0)
536 geometries.push_back(geom);
537 tmp.clear();
538 } else {
539 tmp += geoms[i];
540 }
541 }
542 BoundaryGeometry* ttmp = geometries[0];
543 solver_m = new FFTBoxPoissonSolver(mesh_m, FL_m, greens, ttmp->getA());
545 fsName_m = "FFTBOX";
547 } else {
548 solver_m = new FFTPoissonSolver(mesh_m, FL_m, greens, bcz);
550 }
551 } else if (fsType_m == FieldSolverType::P3M) {
553 FL_m,
556 greens);
557
559
560 } else if (fsType_m == FieldSolverType::SAAMG) {
561#ifdef HAVE_SAAMG_SOLVER
562 //we go over all geometries and add the Geometry Elements to the geometry list
563 std::string geoms = Attributes::getString(itsAttr[GEOMETRY]);
564 std::string tmp;
565 //split and add all to list
566 std::vector<BoundaryGeometry*> geometries;
567 for (unsigned int i = 0; i <= geoms.length(); i++) {
568 if (i == geoms.length() || geoms[i] == ',') {
570 if (geom != 0) {
571 geometries.push_back(geom);
572 }
573 tmp.clear();
574 } else
575 tmp += geoms[i];
576 }
577 solver_m = new MGPoissonSolver(dynamic_cast<PartBunch*>(itsBunch_m), mesh_m, FL_m,
578 geometries,
582 Attributes::getReal(itsAttr[MAXITERS]),
583 Attributes::getString(itsAttr[PRECMODE]));
585#else
586 throw OpalException("FieldSolver::initSolver",
587 "SAAMG Solver not enabled! Please build OPAL with -DENABLE_SAAMG_SOLVER=1");
588#endif
589 } else {
590 solver_m = 0;
591 INFOMSG("No solver attached" << endl);
592 }
593}
594
596 return (solver_m != 0);
597}
598
600 os << "* ************* F I E L D S O L V E R ********************************************** " << endl;
601 os << "* FIELDSOLVER " << getOpalName() << '\n'
602 << "* TYPE " << fsName_m << '\n'
603 << "* N-PROCESSORS " << Ippl::getNodes() << '\n'
604 << "* MX " << Attributes::getReal(itsAttr[MX]) << '\n'
605 << "* MY " << Attributes::getReal(itsAttr[MY]) << '\n'
606 << "* MT " << Attributes::getReal(itsAttr[MT]) << '\n'
607 << "* BBOXINCR " << Attributes::getReal(itsAttr[BBOXINCR]) << endl;
609 os << "* RC " << Attributes::getReal(itsAttr[RC]) << '\n'
610 << "* ALPHA " << Attributes::getReal(itsAttr[ALPHA]) << '\n'
611 << "* GREENSF " << Attributes::getString(itsAttr[GREENSF]) << endl;
612 } else if (fsType_m == FieldSolverType::FFT) {
613 os << "* GREENSF " << Attributes::getString(itsAttr[GREENSF]) << '\n'
614 << "* BCFFTX " << Attributes::getString(itsAttr[BCFFTX]) << '\n'
615 << "* BCFFTY " << Attributes::getString(itsAttr[BCFFTY]) << '\n'
616 << "* BCFFTZ " << Attributes::getString(getBCZAttribute()) << endl;
617 } else if (fsType_m == FieldSolverType::SAAMG) {
618 os << "* GEOMETRY " << Attributes::getString(itsAttr[GEOMETRY]) << '\n'
619 << "* ITSOLVER " << Attributes::getString(itsAttr[ITSOLVER]) << '\n'
620 << "* INTERPL " << Attributes::getString(itsAttr[INTERPL]) << '\n'
621 << "* TOL " << Attributes::getReal(itsAttr[TOL]) << '\n'
622 << "* MAXITERS " << Attributes::getReal(itsAttr[MAXITERS]) << '\n'
623 << "* PRECMODE " << Attributes::getString(itsAttr[PRECMODE]) << endl;
624 } else if (Options::amr) {
625#ifdef ENABLE_AMR
626 os << "* AMR_MAXLEVEL " << Attributes::getReal(itsAttr[AMR_MAXLEVEL]) << '\n'
627 << "* AMR_REFX " << Attributes::getReal(itsAttr[AMR_REFX]) << '\n'
628 << "* AMR_REFY " << Attributes::getReal(itsAttr[AMR_REFY]) << '\n'
629 << "* AMR_REFZ " << Attributes::getReal(itsAttr[AMR_REFZ]) << '\n'
630 << "* AMR_MAXGRIDX " << Attributes::getReal(itsAttr[AMR_MAXGRIDX]) << '\n'
631 << "* AMR_MAXGRIDY " << Attributes::getReal(itsAttr[AMR_MAXGRIDY]) << '\n'
632 << "* AMR_MAXGRIDZ " << Attributes::getReal(itsAttr[AMR_MAXGRIDZ]) << '\n'
633 << "* AMR_BFX " << Attributes::getReal(itsAttr[AMR_BFX]) << '\n'
634 << "* AMR_BFY " << Attributes::getReal(itsAttr[AMR_BFY]) << '\n'
635 << "* AMR_BFZ " << Attributes::getReal(itsAttr[AMR_BFZ]) << '\n'
636 << "* AMR_TAGGING " << this->getTagging_m() <<'\n'
637 << "* AMR_DENSITY " << Attributes::getReal(itsAttr[AMR_DENSITY]) << '\n'
638 << "* AMR_MAX_NUM_PART " << Attributes::getReal(itsAttr[AMR_MAX_NUM_PART]) << '\n'
639 << "* AMR_MIN_NUM_PART " << Attributes::getReal(itsAttr[AMR_MIN_NUM_PART]) << '\n'
640 << "* AMR_DENSITY " << Attributes::getReal(itsAttr[AMR_DENSITY]) << '\n'
641 << "* AMR_SCALING " << Attributes::getReal(itsAttr[AMR_SCALING]) << endl;
642 auto length = Attributes::getRealArray(itsAttr[AMR_DOMAIN_RATIO]);
643 os << "* AMR_DOMAIN_RATIO ( ";
644 for (auto& l : length) {
645 os << l << " ";
646 }
647 os << ")" << endl;
648#endif
649 }
650
651#ifdef HAVE_AMR_MG_SOLVER
653 os << "* ITSOLVER (AMR_MG) "
654 << Attributes::getString(itsAttr[ITSOLVER]) << '\n'
655 << "* AMR_MG_PREC "
656 << Attributes::getString(itsAttr[AMR_MG_PREC]) << '\n'
657 << "* AMR_MG_REBALANCE "
658 << Attributes::getBool(itsAttr[AMR_MG_REBALANCE]) << '\n'
659 << "* AMR_MG_REUSE "
660 << Attributes::getString(itsAttr[AMR_MG_REUSE]) << '\n'
661 << "* AMR_MG_SMOOTHER "
662 << Attributes::getString(itsAttr[AMR_MG_SMOOTHER]) << '\n'
663 << "* AMR_MG_NSWEEPS "
664 << Attributes::getReal(itsAttr[AMR_MG_NSWEEPS]) << '\n'
665 << "* AMR_MG_INTERP "
666 << Attributes::getString(itsAttr[AMR_MG_INTERP]) << '\n'
667 << "* AMR_MG_NORM "
668 << Attributes::getString(itsAttr[AMR_MG_NORM]) << '\n'
669 << "* AMR_MG_TOL "
670 << Attributes::getReal(itsAttr[AMR_MG_TOL]) << '\n'
671 << "* AMR_MG_VERBOSE "
672 << Attributes::getBool(itsAttr[AMR_MG_VERBOSE]) << '\n'
673 << "* BCFFTX "
674 << Attributes::getString(itsAttr[BCFFTX]) << '\n'
675 << "* BCFFTY "
676 << Attributes::getString(itsAttr[BCFFTY]) << '\n'
677 << "* BCFFTZ "
679 }
680#endif
681
682 if (Attributes::getBool(itsAttr[PARFFTX])) {
683 os << "* XDIM parallel " << endl;
684 } else {
685 os << "* XDIM serial " << endl;
686 }
687
688 if (Attributes::getBool(itsAttr[PARFFTY])) {
689 os << "* YDIM parallel " << endl;
690 } else {
691 os << "* YDIM serial " << endl;
692 }
693
694 if (Attributes::getBool(itsAttr[PARFFTT])) {
695 os << "* Z(T)DIM parallel " << endl;
696 }else {
697 os << "* Z(T)DIM serial " << endl;
698 }
699
700 if ( !isAmrSolverType() ) {
701 INFOMSG(level3 << *mesh_m << endl);
702 INFOMSG(level3 << *PL_m << endl);
703 }
704
705 if (solver_m)
706 os << *solver_m << endl;
707 os << "* ********************************************************************************** " << endl;
708 return os;
709}
710
711#ifdef ENABLE_AMR
712std::string FieldSolver::getTagging_m() const {
713 std::string tagging = Attributes::getString(itsAttr[AMR_TAGGING]);
714
715 // This conversion was introduced to allow numbers for tagging (useful for the sampler).
716 if ( Util::isAllDigits(tagging) ) {
717 tagging = AmrObject::getTaggingString(std::stoi(tagging));
718 }
719 return tagging;
720}
721
722
724
725 auto domain = Attributes::getRealArray(itsAttr[AMR_DOMAIN_RATIO]);
726 dynamic_cast<AmrPartBunch*>(itsBunch_m)->setAmrDomainRatio(
727 Attributes::getRealArray(itsAttr[AMR_DOMAIN_RATIO])
728 );
730
731 // setup initial info for creating the object
733 info.grid[0] = (int)this->getMX();
734 info.grid[1] = (int)this->getMY();
735 info.grid[2] = (int)this->getMT();
736 info.maxgrid[0] = Attributes::getReal(itsAttr[AMR_MAXGRIDX]);
737 info.maxgrid[1] = Attributes::getReal(itsAttr[AMR_MAXGRIDY]);
738 info.maxgrid[2] = Attributes::getReal(itsAttr[AMR_MAXGRIDZ]);
739 info.bf[0] = Attributes::getReal(itsAttr[AMR_BFX]);
740 info.bf[1] = Attributes::getReal(itsAttr[AMR_BFY]);
741 info.bf[2] = Attributes::getReal(itsAttr[AMR_BFZ]);
742 info.maxlevel = Attributes::getReal(itsAttr[AMR_MAXLEVEL]);
743 info.refratio[0] = Attributes::getReal(itsAttr[AMR_REFX]);
744 info.refratio[1] = Attributes::getReal(itsAttr[AMR_REFY]);
745 info.refratio[2] = Attributes::getReal(itsAttr[AMR_REFZ]);
746
748
749 itsAmrObject_mp->setTagging( this->getTagging_m() );
750
751 itsAmrObject_mp->setScalingFactor( Attributes::getReal(itsAttr[AMR_SCALING]) );
752
753 itsAmrObject_mp->setChargeDensity( Attributes::getReal(itsAttr[AMR_DENSITY]) );
754
755 itsAmrObject_mp->setMaxNumParticles(
756 Attributes::getReal(itsAttr[AMR_MAX_NUM_PART])
757 );
758
759 itsAmrObject_mp->setMinNumParticles(
760 Attributes::getReal(itsAttr[AMR_MIN_NUM_PART])
761 );
762}
763
764
766
768 if ( dynamic_cast<AmrBoxLib*>( itsAmrObject_mp.get() ) == 0 )
769 throw OpalException("FieldSolver::initAmrSolver_m()",
770 "ML solver requires AMReX.");
771 solver_m = new MLPoissonSolver(static_cast<AmrBoxLib*>(itsAmrObject_mp.get()));
772#ifdef AMREX_ENABLE_FBASELIB
773 } else if (fsType_m == FieldSolverType::FMG) {
774
775 if ( dynamic_cast<AmrBoxLib*>( itsAmrObject_mp.get() ) == 0 )
776 throw OpalException("FieldSolver::initAmrSolver_m()",
777 "FMultiGrid solver requires AMReX.");
778
779 solver_m = new FMGPoissonSolver(static_cast<AmrBoxLib*>(itsAmrObject_mp.get()));
780#endif
781 } else if (fsType_m == FieldSolverType::HYPRE) {
782 throw OpalException("FieldSolver::initAmrSolver_m()",
783 "HYPRE solver not yet implemented.");
784 } else if (fsType_m == FieldSolverType::HPGMG) {
785 throw OpalException("FieldSolver::initAmrSolver_m()",
786 "HPGMG solver not yet implemented.");
787 } else if (fsType_m == FieldSolverType::AMRMG) {
788#ifdef HAVE_AMR_MG_SOLVER
789 if ( dynamic_cast<AmrBoxLib*>( itsAmrObject_mp.get() ) == 0 )
790 throw OpalException("FieldSolver::initAmrSolver_m()",
791 "FMultiGrid solver requires AMReX.");
792
793 std::string bcz = Attributes::getString(getBCZAttribute());
794
795 solver_m = new AmrMultiGrid(static_cast<AmrBoxLib*>(itsAmrObject_mp.get()),
797 Attributes::getString(itsAttr[AMR_MG_PREC]),
798 Attributes::getBool(itsAttr[AMR_MG_REBALANCE]),
799 Attributes::getString(itsAttr[AMR_MG_REUSE]),
802 bcz,
803 Attributes::getString(itsAttr[AMR_MG_SMOOTHER]),
804 Attributes::getReal(itsAttr[AMR_MG_NSWEEPS]),
805 Attributes::getString(itsAttr[AMR_MG_INTERP]),
806 Attributes::getString(itsAttr[AMR_MG_NORM]));
807
808 dynamic_cast<AmrMultiGrid*>(solver_m)->setVerbose(
809 Attributes::getBool(itsAttr[AMR_MG_VERBOSE]));
810
811 dynamic_cast<AmrMultiGrid*>(solver_m)->setTolerance(
812 Attributes::getReal(itsAttr[AMR_MG_TOL]));
813#else
814 throw OpalException("FieldSolver::initAmrSolver_m()",
815 "Multigrid solver not enabled! "
816 "Please build OPAL with -DENABLE_AMR_MG_SOLVER=1");
817#endif
818 } else
819 throw OpalException("FieldSolver::initAmrSolver_m()",
820 "Unknown solver " + getType() + ".");
821}
822#endif
UniformCartesian< 3, double > Mesh_t
Definition PBunchDefs.h:22
ParticleSpatialLayout< double, 3, Mesh_t > Layout_t
Definition PBunchDefs.h:24
CenteredFieldLayout< 3, Mesh_t, Center_t > FieldLayout_t
Definition PBunchDefs.h:28
@ SIZE
Definition IndexMap.cpp:178
#define INFOMSG(msg)
Definition IpplInfo.h:348
Inform & endl(Inform &inf)
Definition Inform.cpp:42
Inform & level3(Inform &inf)
Definition Inform.cpp:47
e_dim_tag
Definition FieldLayout.h:55
@ PARALLEL
Definition FieldLayout.h:55
@ SERIAL
Definition FieldLayout.h:55
const std::string name
Representation objects and parsers for attribute expressions.
Definition Expressions.h:64
Attribute makeBool(const std::string &name, const std::string &help)
Make logical attribute.
double getReal(const Attribute &attr)
Return real value.
void setRealArray(Attribute &attr, const std::vector< double > &value)
Set array value.
Attribute makeUpperCaseString(const std::string &name, const std::string &help)
Make uppercase string attribute.
Attribute makePredefinedString(const std::string &name, const std::string &help, const std::initializer_list< std::string > &predefinedStrings)
Make predefined string attribute.
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
bool getBool(const Attribute &attr)
Return logical value.
void setReal(Attribute &attr, double val)
Set real value.
Attribute makeRealArray(const std::string &name, const std::string &help)
Create real array attribute.
std::vector< double > getRealArray(const Attribute &attr)
Get array value.
std::string getString(const Attribute &attr)
Get string value.
bool amr
Enable AMR if true.
Definition Options.cpp:97
bool isAllDigits(const std::string &str)
Definition Util.cpp:225
A representation of an Object attribute.
Definition Attribute.h:52
The base class for all OPAL definitions.
Definition Definition.h:30
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition Object.cpp:191
const std::string & getOpalName() const
Return object name.
Definition Object.cpp:310
void clear()
Clear the occurrence counter.
Definition Object.cpp:341
std::vector< Attribute > itsAttr
The object attributes.
Definition Object.h:216
virtual void set_meshEnlargement(double dh)
Object * find(const std::string &name)
Find entry.
Definition OpalData.cpp:571
static OpalData * getInstance()
Definition OpalData.cpp:196
BoundaryGeometry * getGlobalGeometry()
Definition OpalData.cpp:461
static std::unique_ptr< AmrBoxLib > create(const AmrInfo &info, AmrPartBunch *bunch_p)
Definition AmrBoxLib.cpp:74
static std::string getTaggingString(int number)
int grid[3]
Number of grid points in x-, y- and z-direction.
Definition AmrObject.h:54
int maxgrid[3]
Maximum grid size in x-, y- and z-direction.
Definition AmrObject.h:55
static BoundaryGeometry * find(const std::string &name)
virtual void update()
Update the field solver data.
std::unique_ptr< Layout_t > PL_m
The particle layout.
FieldSolverType fsType_m
void setMT(double)
Store emittance for mode 3.
void initCartesianFields()
double getMY() const
Return meshsize.
std::string getTagging_m() const
Mesh_t * mesh_m
The cartesian mesh.
std::string fsName_m
PartBunchBase< double, 3 > * itsBunch_m
all the particles are here ...
std::string getType()
PoissonSolver * solver_m
the actual solver, should be a base object
Inform & printInfo(Inform &os) const
bool isAmrSolverType() const
static FieldSolver * find(const std::string &name)
Find named FieldSolver.
FieldSolver()
Exemplar constructor.
void setFieldSolverType()
virtual void execute()
Execute (init) the field solver data.
double getMX() const
Return meshsize.
FieldLayout_t * FL_m
The field layout f.
bool hasPeriodicZ()
void initAmrObject_m()
std::unique_ptr< AmrObject > itsAmrObject_mp
const Attribute & getBCZAttribute() const
void setMY(double)
Store emittance for mode 2.
double getMT() const
Return meshsize.
virtual ~FieldSolver()
bool hasValidSolver()
void setMX(double)
Store emittance for mode 1.
virtual FieldSolver * clone(const std::string &name)
Make clone.
void initSolver(PartBunchBase< double, 3 > *b)
void initAmrSolver_m()
The base class for all OPAL exceptions.
Definition Index.h:237
static int getNodes()
Definition IpplInfo.cpp:670