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