chombo-discharge
CD_FieldStepperImplem.H
Go to the documentation of this file.
1 /* chombo-discharge
2  * Copyright © 2021 SINTEF Energy Research.
3  * Please refer to Copyright.txt and LICENSE in the chombo-discharge root directory.
4  */
5 
12 #ifndef CD_FieldStepperImplem_H
13 #define CD_FieldStepperImplem_H
14 
15 // Std includes
16 #include <math.h>
17 
18 // Chombo includes
19 #include <CH_Timer.H>
20 #include <ParmParse.H>
21 
22 // Our includes
23 #include <CD_FieldStepper.H>
24 #include <CD_DataOps.H>
25 #include <CD_NamespaceHeader.H>
26 
27 namespace Physics {
28  namespace Electrostatics {
29 
30  template <class T>
32  {
33  CH_TIME("FieldStepper::FieldStepper");
34 
35  m_verbosity = -1;
36 
37  ParmParse pp("FieldStepper");
38 
39  Real rho0 = 0.0;
40  Real sigma0 = 0.0;
41  Real blobRadius = 1.0;
42  RealVect blobCenter = RealVect::Zero;
43 
44  std::string str;
45  Vector<Real> vec(SpaceDim);
46 
47  // Read in parameters
48  pp.get("init_rho", rho0);
49  pp.get("init_sigma", sigma0);
50  pp.get("rho_radius", blobRadius);
51  pp.get("load_balance", m_loadBalance);
52  pp.get("box_sorting", str);
53  pp.get("realm", m_realm);
54  pp.get("verbosity", m_verbosity);
55  pp.getarr("rho_center", vec, 0, SpaceDim);
56 
57  blobCenter = RealVect(D_DECL(vec[0], vec[1], vec[2]));
58 
59  m_rhoGas = [a = rho0, c = blobCenter, r = blobRadius](const RealVect x) -> Real {
60  const Real d = (x - c).dotProduct(x - c);
61  return a * exp(-d / (2 * r * r));
62  };
63 
64  m_rhoDielectric = m_rhoGas;
65  m_surfaceChargeDensity = [s = sigma0](const RealVect& x) -> Real {
66  return s;
67  };
68 
69  if (str == "none") {
70  m_boxSort = BoxSorting::None;
71  }
72  if (str == "std") {
73  m_boxSort = BoxSorting::Std;
74  }
75  else if (str == "shuffle") {
76  m_boxSort = BoxSorting::Shuffle;
77  }
78  else if (str == "morton") {
79  m_boxSort = BoxSorting::Morton;
80  }
81  else {
82  MayDay::Error("FieldStepper::FieldStepper - unknown box sorting method requested for argument 'BoxSorting'");
83  }
84  }
85 
86  template <class T>
88  {
89  CH_TIME("FieldStepper::~FieldStepper");
90  }
91 
92  template <class T>
93  void
95  {
96  CH_TIME("FieldStepper::setupSolvers");
97  if (m_verbosity > 5) {
98  pout() << "FieldStepper<T>::setupSolvers" << endl;
99  }
100 
101  // Define a voltage function to be used in the simulation.
102  auto voltage = [](const Real a_time) -> Real {
103  return 1.0;
104  };
105 
106  // Instantiate the FieldSolver and set it up.
107  m_fieldSolver = RefCountedPtr<FieldSolver>(new T());
108  m_fieldSolver->parseOptions();
109  m_fieldSolver->setAmr(m_amr);
110  m_fieldSolver->setComputationalGeometry(m_computationalGeometry);
111  m_fieldSolver->setVoltage(voltage);
112  m_fieldSolver->setRealm(m_realm);
113  m_fieldSolver->setTime(0, 0.0, 0.0);
114  m_fieldSolver->setVerbosity(m_verbosity);
115 
116  // Instantiate the surface charge solver and set it up.
117  m_sigma = RefCountedPtr<SurfaceODESolver<1>>(new SurfaceODESolver<1>(m_amr));
118  m_sigma->setPhase(phase::gas);
119  m_sigma->setRealm(m_realm);
120  m_sigma->setName("Surface charge");
121  m_sigma->parseOptions();
122  m_sigma->setTime(0, 0.0, 0.0);
123  m_sigma->setVerbosity(m_verbosity);
124  }
125 
126  template <class T>
127  void
129  {
130  CH_TIME("FieldStepper::registerOperators");
131  if (m_verbosity > 5) {
132  pout() << "FieldStepper<T>::registerOperators" << endl;
133  }
134 
135  m_fieldSolver->registerOperators();
136  m_sigma->registerOperators();
137  }
138 
139  template <class T>
140  void
142  {
143  CH_TIME("FieldStepper::registerRealms");
144  if (m_verbosity > 5) {
145  pout() << "FieldStepper<T>::registerRealms" << endl;
146  }
147 
148  m_amr->registerRealm(m_realm);
149  }
150 
151  template <class T>
152  void
154  {
155  CH_TIME("FieldStepper::allocate");
156  if (m_verbosity > 5) {
157  pout() << "FieldStepper<T>::allocate" << endl;
158  }
159 
160  m_fieldSolver->allocate();
161  m_sigma->allocate();
162  }
163 
164  template <class T>
167  {
168  CH_TIME("FieldStepper::getPotential");
169  if (m_verbosity > 5) {
170  pout() << "FieldStepper<T>::getPotential" << endl;
171  }
172 
173  return m_fieldSolver->getPotential();
174  }
175 
176  template <class T>
177  void
179  {
180  CH_TIME("FieldStepper::initialData");
181  if (m_verbosity > 5) {
182  pout() << "FieldStepper<T>::initialData" << endl;
183  }
184  }
185 
186  template <class T>
187  void
189  {
190  CH_TIME("FieldStepper::solvePoisson");
191  if (m_verbosity > 5) {
192  pout() << "FieldStepper<T>::solvePoisson" << endl;
193  }
194 
195  // Solve using rho from fieldsolver and sigma from SurfaceODESolver.
196  MFAMRCellData& phi = m_fieldSolver->getPotential();
197  MFAMRCellData& rho = m_fieldSolver->getRho();
198  EBAMRIVData& sigma = m_sigma->getPhi();
199 
200  // Solve and issue error message if we did not converge.
201  const bool converged = m_fieldSolver->solve(phi, rho, sigma);
202 
203  if (!converged) {
204  MayDay::Warning("FieldStepper<T>::solvePoisson - did not converge");
205  }
206 
207  // Compute the electric field.
208  m_fieldSolver->computeElectricField();
209  }
210 
211  template <class T>
212  void
214  {
215  CH_TIME("FieldStepper::postInitialize");
216  if (m_verbosity > 5) {
217  pout() << "FieldStepper<T>::postInitialize" << endl;
218  }
219 
220  // Fetch the potential and surface/space charges and initialize them. The potential is set to zero
221  // and the space/surface charge set from m_rhoGas, m_rhoDielectric, and m_surfaceChargeDensity
222  MFAMRCellData& state = m_fieldSolver->getPotential();
223  EBAMRIVData& sigma = m_sigma->getPhi();
224 
225  DataOps::setValue(state, 0.0);
226  DataOps::setValue(sigma, m_surfaceChargeDensity, m_amr->getProbLo(), m_amr->getDx(), 0);
227  m_sigma->resetElectrodes(sigma, 0.0);
228  m_fieldSolver->setRho(m_rhoGas);
229 
230  // Solve Poisson equation.
231  this->solvePoisson();
232  }
233 
234  template <class T>
235  Real
236  FieldStepper<T>::advance(const Real a_dt)
237  {
238  CH_TIME("FieldStepper::advance");
239  if (m_verbosity > 5) {
240  pout() << "FieldStepper<T>::advance" << endl;
241  }
242 
243  MayDay::Error("FieldStepper<T>::advance - callling this is an error. Please set Driver.max_steps = 0");
244 
246  }
247 
248 #ifdef CH_USE_HDF5
249  template <class T>
250  void
251  FieldStepper<T>::writeCheckpointData(HDF5Handle& a_handle, const int a_lvl) const
252  {
253  CH_TIME("FieldStepper::writeCheckpointData");
254  if (m_verbosity > 5) {
255  pout() << "FieldStepper<T>::writeCheckpointData" << endl;
256  }
257  }
258 #endif
259 
260 #ifdef CH_USE_HDF5
261  template <class T>
262  void
263  FieldStepper<T>::readCheckpointData(HDF5Handle& a_handle, const int a_lvl)
264  {
265  CH_TIME("FieldStepper::readCheckpointData");
266  if (m_verbosity > 5) {
267  pout() << "FieldStepper<T>::readCheckpointData" << endl;
268  }
269 
270  MayDay::Error("FieldStepper<T>::readCheckpointData - checkpointing not supported for this module");
271  }
272 #endif
273 
274  template <class T>
275  int
277  {
278  CH_TIME("FieldStepper::getNumberOfPlotVariables");
279  if (m_verbosity > 5) {
280  pout() << "FieldStepper<T>::getNumberOfPlotVariables" << endl;
281  }
282 
283  int ncomp = 0;
284 
285  ncomp += m_fieldSolver->getNumberOfPlotVariables();
286  ncomp += m_sigma->getNumberOfPlotVariables();
287 
288  return ncomp;
289  }
290 
291  template <class T>
292  Vector<std::string>
294  {
295  CH_TIME("FieldStepper::getPlotVariableNames");
296  if (m_verbosity > 5) {
297  pout() << "FieldStepper<T>::getPlotVariableNames" << endl;
298  }
299 
300  Vector<std::string> plotVars;
301 
302  plotVars.append(m_fieldSolver->getPlotVariableNames());
303  plotVars.append(m_sigma->getPlotVariableNames());
304 
305  return plotVars;
306  }
307 
308  template <class T>
309  void
310  FieldStepper<T>::writePlotData(LevelData<EBCellFAB>& a_output,
311  int& a_icomp,
312  const std::string a_outputRealm,
313  const int a_level) const
314  {
315  CH_TIME("FieldStepper::writePlotData");
316  if (m_verbosity > 5) {
317  pout() << "FieldStepper<T>::writePlotData" << endl;
318  }
319 
320  CH_assert(a_level >= 0);
321  CH_assert(a_level <= m_amr->getFinestLevel());
322 
323  // Write into plot data holder memory.
324  m_fieldSolver->writePlotData(a_output, a_icomp, a_outputRealm, a_level);
325  m_sigma->writePlotData(a_output, a_icomp, a_outputRealm, a_level);
326  }
327 
328  template <class T>
329  void
330  FieldStepper<T>::synchronizeSolverTimes(const int a_step, const Real a_time, const Real a_dt)
331  {
332  CH_TIME("FieldStepper::synchronizeSolverTimes");
333  if (m_verbosity > 5) {
334  pout() << "FieldStepper<T>::synchronizeSolverTimes" << endl;
335  }
336 
337  m_timeStep = a_step;
338  m_time = a_time;
339  m_dt = a_dt;
340 
341  m_fieldSolver->setTime(a_step, a_time, a_dt);
342  }
343 
344  template <class T>
345  void
346  FieldStepper<T>::preRegrid(const int a_lbase, const int a_oldFinestLevel)
347  {
348  CH_TIME("FieldStepper::preRegrid");
349  if (m_verbosity > 5) {
350  pout() << "FieldStepper<T>::preRegrid" << endl;
351  }
352 
353  m_fieldSolver->preRegrid(a_lbase, a_oldFinestLevel);
354  m_sigma->preRegrid(a_lbase, a_oldFinestLevel);
355  }
356 
357  template <class T>
358  void
359  FieldStepper<T>::regrid(const int a_lmin, const int a_oldFinestLevel, const int a_newFinestLevel)
360  {
361  CH_TIME("FieldStepper::regrid");
362  if (m_verbosity > 5) {
363  pout() << "FieldStepper<T>::regrid" << endl;
364  }
365 
366  // TLDR: The FieldSolver regrid methods just regrids the data -- it does not re-solve the Poisson equation. Here,
367  // that is done in postRegrid.
368 
369  m_fieldSolver->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
370  m_sigma->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
371  }
372 
373  template <class T>
374  void
376  {
377  CH_TIME("FieldStepper::postRegrid");
378  if (m_verbosity > 5) {
379  pout() << "FieldStepper<T>::postRegrid" << endl;
380  }
381 
382  this->solvePoisson();
383  }
384 
385  template <class T>
386  bool
387  FieldStepper<T>::loadBalanceThisRealm(const std::string a_realm) const
388  {
389  CH_TIME("FieldStepper::loadBalanceThisRealm");
390  if (m_verbosity > 5) {
391  pout() << "FieldStepper<T>::loadBalanceThisRealm" << endl;
392  }
393 
394  return (a_realm == m_realm) && m_loadBalance;
395  }
396 
397  template <class T>
398  void
399  FieldStepper<T>::loadBalanceBoxes(Vector<Vector<int>>& a_procs,
400  Vector<Vector<Box>>& a_boxes,
401  const std::string a_realm,
402  const Vector<DisjointBoxLayout>& a_grids,
403  const int a_lmin,
404  const int a_finestLevel)
405  {
406  CH_TIME("FieldStepper::loadBalanceBoxes");
407  if (m_verbosity > 5) {
408  pout() << "FieldStepper<T>::loadBalanceBoxes" << endl;
409  }
410 
411  CH_assert(m_loadBalance && a_realm == m_realm);
412 
413  // TLDR: This code tries to compute a load for each grid patch by applying a relaxation operator to each box. This means that the load
414  // should be a decent estimate that takes into account boundary conditions, coarse-fine interface arithmetic, and enlargened stencils
415  // near the embedded boundary.
416 
417  a_procs.resize(1 + a_finestLevel);
418  a_boxes.resize(1 + a_finestLevel);
419 
420  // We need to make AmrMesh restore some operators that we need in order to create a multigrid object. Fortunately, FieldSolver has routines
421  // for doing that but it will not know if AmrMesh has updated it's operators or not. So, we need to regrid them.
422  m_amr->regridOperators(a_lmin);
423 
424  Loads rankLoads;
425  rankLoads.resetLoads();
426 
427  // Field solver implementation gets the responsibility of computing loads on each level.
428  for (int lvl = 0; lvl <= a_finestLevel; lvl++) {
429  Vector<long long> boxLoads = m_fieldSolver->computeLoads(a_grids[lvl], lvl);
430 
431  // Do the desired sorting and load balancing
432  a_boxes[lvl] = a_grids[lvl].boxArray();
433 
434  LoadBalancing::sort(a_boxes[lvl], boxLoads, m_boxSort);
435  LoadBalancing::makeBalance(a_procs[lvl], rankLoads, boxLoads, a_boxes[lvl]);
436  }
437  }
438 
439  template <class T>
440  void
441  FieldStepper<T>::setRho(const std::function<Real(const RealVect& a_pos)>& a_rho,
442  const phase::which_phase a_phase) noexcept
443  {
444  CH_TIME("FieldStepper::setRho");
445  if (m_verbosity > 5) {
446  pout() << "FieldStepper<T>::setRho" << endl;
447  }
448 
449  if (a_phase == phase::gas) {
450  m_rhoGas = a_rho;
451  }
452  else if (a_phase == phase::solid) {
453  m_rhoDielectric = a_rho;
454  }
455  }
456 
457  template <class T>
458  void
459  FieldStepper<T>::setSigma(const std::function<Real(const RealVect& a_pos)>& a_sigma) noexcept
460  {
461  CH_TIME("FieldStepper::setSigma");
462  if (m_verbosity > 5) {
463  pout() << "FieldStepper<T>::setSigma" << endl;
464  }
465 
466  m_surfaceChargeDensity = a_sigma;
467  }
468  } // namespace Electrostatics
469 } // namespace Physics
470 
471 #include <CD_NamespaceFooter.H>
472 
473 #endif
Agglomeration of useful data operations.
TimeStepper class for only solving the Poisson equation (with surface charge)
static void setValue(LevelData< MFInterfaceFAB< T >> &a_lhs, const T &a_value)
Set value in an MFInterfaceFAB data holder.
Definition: CD_DataOpsImplem.H:23
static void makeBalance(Vector< int > &a_ranks, const Vector< T > &a_loads, const Vector< Box > &a_boxes)
Load balancing, assigning ranks to boxes.
Definition: CD_LoadBalancingImplem.H:31
static void sort(Vector< Vector< Box >> &a_boxes, Vector< Vector< T >> &a_loads, const BoxSorting a_whichSorting)
Sorts boxes and loads over a hierarchy according to some sorting criterion.
Definition: CD_LoadBalancingImplem.H:221
Class for holding computational loads.
Definition: CD_Loads.H:30
virtual void resetLoads() noexcept
Reset loads. Sets all loads to 0.
Definition: CD_Loads.cpp:54
Implementation of TimeStepper for solving electrostatic problems. The template parameter is the Field...
Definition: CD_FieldStepper.H:36
void loadBalanceBoxes(Vector< Vector< int >> &a_procs, Vector< Vector< Box >> &a_boxes, const std::string a_realm, const Vector< DisjointBoxLayout > &a_grids, const int a_lmin, const int a_finestLevel) override
Load balance grid boxes for a specified realm.
Definition: CD_FieldStepperImplem.H:399
void setRho(const std::function< Real(const RealVect &a_pos)> &a_rho, const phase::which_phase a_phase) noexcept
Set space charge.
Definition: CD_FieldStepperImplem.H:441
void writePlotData(LevelData< EBCellFAB > &a_output, int &a_icomp, const std::string a_outputRealm, const int a_level) const override
Write plot data to file.
Definition: CD_FieldStepperImplem.H:310
void preRegrid(const int a_lbase, const int a_finestLevel) override
Perform pre-regrid operations.
Definition: CD_FieldStepperImplem.H:346
Vector< std::string > getPlotVariableNames() const override
Get plot variable names.
Definition: CD_FieldStepperImplem.H:293
void initialData() override
Set initial data – this sets the space and surface charges.
Definition: CD_FieldStepperImplem.H:178
void regrid(const int a_lmin, const int a_oldFinestLevel, const int a_newFinestLevel) override
Regrid method – regrids the potential distribution in FieldSolver (but does not solve the Poisson equ...
Definition: CD_FieldStepperImplem.H:359
void setSigma(const std::function< Real(const RealVect &a_pos)> &a_sigma) noexcept
Set surface charge.
Definition: CD_FieldStepperImplem.H:459
void solvePoisson()
Internal routine for solving the Poisson equation.
Definition: CD_FieldStepperImplem.H:188
void postInitialize() override
Post-initialization routine. This solves the Poisson equation.
Definition: CD_FieldStepperImplem.H:213
int getNumberOfPlotVariables() const override
Get number of plot variables.
Definition: CD_FieldStepperImplem.H:276
void registerRealms() override
Register simulation realms to be used for this simulation module.
Definition: CD_FieldStepperImplem.H:141
void allocate() override
Allocation method – allocates memory and internal data for solvers.
Definition: CD_FieldStepperImplem.H:153
void registerOperators() override
Register operators for this simulation module.
Definition: CD_FieldStepperImplem.H:128
void synchronizeSolverTimes(const int a_step, const Real a_time, const Real a_dt) override
Synchronzie solver times and time steps.
Definition: CD_FieldStepperImplem.H:330
virtual ~FieldStepper()
Destructor (does nothing)
Definition: CD_FieldStepperImplem.H:87
void postRegrid() override
Perform post-regrid operations – this will resolve the Poisson equation.
Definition: CD_FieldStepperImplem.H:375
MFAMRCellData & getPotential()
Get the potential.
Definition: CD_FieldStepperImplem.H:166
FieldStepper()
Constructor – parses some input options.
Definition: CD_FieldStepperImplem.H:31
bool loadBalanceThisRealm(const std::string a_realm) const override
Load balancing query for a specified realm. If this returns true for a_realm, load balancing routines...
Definition: CD_FieldStepperImplem.H:387
Real advance(const Real a_dt) override
Perform a single time step with step a_dt.
Definition: CD_FieldStepperImplem.H:236
void setupSolvers() override
Solver setup routine. This instantiates the FieldSolver and parses input options.
Definition: CD_FieldStepperImplem.H:94
Surface ODE solver.
Definition: CD_SurfaceODESolver.H:28
Real max(const Real &a_input) noexcept
Get the maximum of the input, reduced over MPI ranks (in the Chombo communicator)
Definition: CD_ParallelOpsImplem.H:176
Name containing various physics models for running chombo-discharge code.
Definition: CD_AdvectionDiffusion.H:15
constexpr Real c
Speed of light.
Definition: CD_Units.H:39