chombo-discharge
CD_ItoSolverImplem.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 
13 #ifndef CD_ItoSolverImplem_H
14 #define CD_ItoSolverImplem_H
15 
16 // Std includes
17 #include <chrono>
18 
19 // Chombo includes
20 #include <EBAlias.H>
21 #include <PolyGeom.H>
22 
23 // Our includes
24 #include <CD_ItoSolver.H>
25 #include <CD_DataOps.H>
26 #include <CD_Random.H>
27 #include <CD_NamespaceHeader.H>
28 
29 inline RealVect
31 {
32  // TLDR: We draw a random number from a Gaussian distribution for each coordinate, and truncate the distribution at m_normalDistributionTruncation.
33 
34  auto sign = [](const Real& a) -> Real {
35  return (a > 0) - (a < 0);
36  };
37 
38  RealVect r = RealVect::Zero;
39  for (int i = 0; i < SpaceDim; i++) {
40  r[i] = Random::getNormal01();
41 
42  r[i] = sign(r[i]) * std::min(std::abs(r[i]), m_normalDistributionTruncation);
43  }
44 
45  return r;
46 }
47 
48 template <ItoSolver::WhichContainer C>
49 void
50 ItoSolver::addParticles(ListBox<ItoParticle>& a_inputParticles,
51  const int a_lvl,
52  const DataIndex a_dit,
53  const bool a_destructive)
54 {
55  CH_TIME("ItoSolver::addParticles");
56  if (m_verbosity > 5) {
57  pout() << m_name + "::addParticles" << endl;
58  }
59 
61 
62  ListBox<ItoParticle>& my_particles = particles[a_lvl][a_dit];
63  if (a_destructive) {
64  my_particles.addItemsDestructive(a_inputParticles.listItems());
65  }
66  else {
67  my_particles.addItems(a_inputParticles.listItems());
68  }
69 }
70 
71 template <class P, const Real& (P::*particleScalarField)() const>
72 void
74 {
75  CH_TIME("ItoSolver::depositParticles");
76  if (m_verbosity > 5) {
77  pout() << m_name + "::depositParticles" << endl;
78  }
79 
80  this->depositParticles<P, particleScalarField>(a_phi, a_particles, m_deposition, m_coarseFineDeposition);
81 }
82 
83 template <class P, const Real& (P ::*particleScalarField)() const>
84 void
85 ItoSolver::depositParticlesNGP(LevelData<EBCellFAB>& a_output,
86  const ParticleContainer<P>& a_particles,
87  const int a_level) const noexcept
88 {
89  CH_TIME("ItoSolver::depositParticles(NGP)");
90  if (m_verbosity > 5) {
91  pout() << m_name + "::depositParticles(NGP)" << endl;
92  }
93 
94  CH_assert(a_level >= 0);
95  CH_assert(a_level <= m_amr->getFinestLevel());
96 
97  const ProblemDomain& domain = m_amr->getDomains()[a_level];
98  const DisjointBoxLayout& dbl = m_amr->getGrids(a_particles.getRealm())[a_level];
99  const DataIterator& dit = dbl.dataIterator();
100  const EBISLayout& ebisl = m_amr->getEBISLayout(a_particles.getRealm(), m_phase)[a_level];
101  const Real dx = m_amr->getDx()[a_level];
102  const RealVect probLo = m_amr->getProbLo();
103 
104  CH_assert(a_output.disjointBoxLayout() == dbl);
105 
106  const int nbox = dit.size();
107 
108 #pragma omp parallel for schedule(runtime)
109  for (int mybox = 0; mybox < nbox; mybox++) {
110  const DataIndex& din = dit[mybox];
111 
112  const Box cellBox = dbl[din];
113  const EBISBox& ebisbox = ebisl[din];
114 
115  EBParticleMesh particleMesh(domain, cellBox, ebisbox, dx * RealVect::Unit, probLo);
116 
117  EBCellFAB& output = a_output[din];
118  const List<P>& particles = a_particles[a_level][din].listItems();
119 
120  particleMesh.deposit<P, particleScalarField>(particles, output, DepositionType::NGP, true);
121  }
122 }
123 
124 template <class P, Real (P ::*particleScalarField)() const>
125 void
126 ItoSolver::depositParticlesNGP(LevelData<EBCellFAB>& a_output,
127  const ParticleContainer<P>& a_particles,
128  const int a_level) const noexcept
129 {
130  CH_TIME("ItoSolver::depositParticles(NGP)");
131  if (m_verbosity > 5) {
132  pout() << m_name + "::depositParticles(NGP)" << endl;
133  }
134 
135  CH_assert(a_level >= 0);
136  CH_assert(a_level <= m_amr->getFinestLevel());
137 
138  const ProblemDomain& domain = m_amr->getDomains()[a_level];
139  const DisjointBoxLayout& dbl = m_amr->getGrids(a_particles.getRealm())[a_level];
140  const DataIterator& dit = dbl.dataIterator();
141  const EBISLayout& ebisl = m_amr->getEBISLayout(a_particles.getRealm(), m_phase)[a_level];
142  const Real dx = m_amr->getDx()[a_level];
143  const RealVect probLo = m_amr->getProbLo();
144 
145  CH_assert(a_output.disjointBoxLayout() == dbl);
146 
147  const int nbox = dit.size();
148 
149 #pragma omp parallel for schedule(runtime)
150  for (int mybox = 0; mybox < nbox; mybox++) {
151  const DataIndex& din = dit[mybox];
152 
153  const Box cellBox = dbl[din];
154  const EBISBox& ebisbox = ebisl[din];
155 
156  EBParticleMesh particleMesh(domain, cellBox, ebisbox, dx * RealVect::Unit, probLo);
157 
158  EBCellFAB& output = a_output[din];
159  const List<P>& particles = a_particles[a_level][din].listItems();
160 
161  particleMesh.deposit<P, particleScalarField>(particles, output, DepositionType::NGP, true);
162  }
163 }
164 
165 template <class P, const Real& (P::*particleScalarField)() const>
166 void
168  ParticleContainer<P>& a_particles,
169  const DepositionType a_deposition,
170  const CoarseFineDeposition a_coarseFineDeposition) const
171 {
172  CH_TIME("ItoSolver::depositParticles");
173  if (m_verbosity > 5) {
174  pout() << m_name + "::depositParticles" << endl;
175  }
176 
177  CH_assert(a_phi[0]->nComp() == 1);
178  CH_assert(!a_particles.isOrganizedByCell());
179 
180  // TLDR: First, deposit onto the mesh as usual (as if the EB wasn't there). If the user asks for it, he can redistribute mass in order to
181  // conserve total mass (if that is important). But the corresponding scheme will be O(1) accurate.
182  this->depositKappaConservative<P, particleScalarField>(a_phi, a_particles, a_deposition, a_coarseFineDeposition);
183 
184  // Redistribution magic.
185  this->redistributeAMR(a_phi);
186 
187  // Average down and interpolate
188  m_amr->conservativeAverage(a_phi, m_realm, m_phase);
189  m_amr->interpGhost(a_phi, m_realm, m_phase);
190 }
191 
192 template <class P, Real (P::*particleScalarField)() const>
193 void
195  ParticleContainer<P>& a_particles,
196  const DepositionType a_deposition,
197  const CoarseFineDeposition a_coarseFineDeposition) const
198 {
199  CH_TIME("ItoSolver::depositParticles");
200  if (m_verbosity > 5) {
201  pout() << m_name + "::depositParticles" << endl;
202  }
203 
204  CH_assert(a_phi[0]->nComp() == 1);
205  CH_assert(!a_particles.isOrganizedByCell());
206 
207  // TLDR: First, deposit onto the mesh as usual (as if the EB wasn't there). If the user asks for it, he can redistribute mass in order to
208  // conserve total mass (if that is important). But the corresponding scheme will be O(1) accurate.
209  this->depositKappaConservative<P, particleScalarField>(a_phi, a_particles, a_deposition, a_coarseFineDeposition);
210 
211  // Redistribution magic.
212  this->redistributeAMR(a_phi);
213 
214  // Average down and interpolate
215  m_amr->conservativeAverage(a_phi, m_realm, m_phase);
216  m_amr->interpGhost(a_phi, m_realm, m_phase);
217 }
218 
219 template <class P, const Real& (P::*particleScalarField)() const>
220 void
222  ParticleContainer<P>& a_particles,
223  const DepositionType a_deposition,
224  const CoarseFineDeposition a_coarseFineDeposition) const
225 {
226  CH_TIME("ItoSolver::depositKappaConservative");
227  if (m_verbosity > 5) {
228  pout() << m_name + "::depositKappaConservative" << endl;
229  }
230 
231  CH_assert(a_phi[0]->nComp() == 1);
232 
233  // Now do the deposition. Recall that when we deposit with "halos", we need to fetch the subset of coarse-level particles that surround the
234  // refinement boundary.
235  switch (a_coarseFineDeposition) {
236  case CoarseFineDeposition::Interp: {
237  m_amr->depositParticles<P, particleScalarField>(a_phi,
238  m_realm,
239  m_phase,
240  a_particles,
241  a_deposition,
242  CoarseFineDeposition::Interp,
244  break;
245  }
246  case CoarseFineDeposition::Halo: {
247 
248  // Copy the mask particles.
249  const AMRMask& mask = m_amr->getMask(s_particle_halo, m_haloBuffer, m_realm);
250  a_particles.copyMaskParticles(mask);
251 
252  m_amr->depositParticles<P, particleScalarField>(a_phi,
253  m_realm,
254  m_phase,
255  a_particles,
256  a_deposition,
257  CoarseFineDeposition::Halo,
259 
260  a_particles.clearMaskParticles();
261 
262  break;
263  }
264  case CoarseFineDeposition::HaloNGP: {
265 
266  // Transfer mask particles
267  const AMRMask& mask = m_amr->getMask(s_particle_halo, m_haloBuffer, m_realm);
268  a_particles.transferMaskParticles(mask);
269 
270  m_amr->depositParticles<P, particleScalarField>(a_phi,
271  m_realm,
272  m_phase,
273  a_particles,
274  a_deposition,
275  CoarseFineDeposition::HaloNGP,
277 
278  a_particles.transferParticles(a_particles.getMaskParticles());
279 
280  break;
281  }
282  default: {
283  MayDay::Error("ItoSolverImplem.H in function ItoSolver::depositKappaConservative -- logic bust!");
284 
285  break;
286  }
287  }
288 }
289 template <class P, Real (P::*particleScalarField)() const>
290 void
292  ParticleContainer<P>& a_particles,
293  const DepositionType a_deposition,
294  const CoarseFineDeposition a_coarseFineDeposition) const
295 {
296  CH_TIME("ItoSolver::depositKappaConservative");
297  if (m_verbosity > 5) {
298  pout() << m_name + "::depositKappaConservative" << endl;
299  }
300 
301  CH_assert(a_phi[0]->nComp() == 1);
302 
303  // Now do the deposition. Recall that when we deposit with "halos", we need to fetch the subset of coarse-level particles that surround the
304  // refinement boundary.
305  switch (a_coarseFineDeposition) {
306  case CoarseFineDeposition::Interp: {
307  m_amr->depositParticles<P, particleScalarField>(a_phi,
308  m_realm,
309  m_phase,
310  a_particles,
311  a_deposition,
312  CoarseFineDeposition::Interp,
314  break;
315  }
316  case CoarseFineDeposition::Halo: {
317 
318  // Copy the mask particles.
319  const AMRMask& mask = m_amr->getMask(s_particle_halo, m_haloBuffer, m_realm);
320  a_particles.copyMaskParticles(mask);
321 
322  m_amr->depositParticles<P, particleScalarField>(a_phi,
323  m_realm,
324  m_phase,
325  a_particles,
326  a_deposition,
327  CoarseFineDeposition::Halo,
329 
330  a_particles.clearMaskParticles();
331 
332  break;
333  }
334  case CoarseFineDeposition::HaloNGP: {
335 
336  // Transfer mask particles
337  const AMRMask& mask = m_amr->getMask(s_particle_halo, m_haloBuffer, m_realm);
338  a_particles.transferMaskParticles(mask);
339 
340  m_amr->depositParticles<P, particleScalarField>(a_phi,
341  m_realm,
342  m_phase,
343  a_particles,
344  a_deposition,
345  CoarseFineDeposition::HaloNGP,
347 
348  a_particles.transferParticles(a_particles.getMaskParticles());
349 
350  break;
351  }
352  default: {
353  MayDay::Error("ItoSolverImplem.H in function ItoSolver::depositKappaConservative -- logic bust!");
354 
355  break;
356  }
357  }
358 }
359 
360 #include <CD_NamespaceFooter.H>
361 
362 #endif
CoarseFineDeposition
Coarse-fine deposition types (see CD_EBAMRParticleMesh for how these are handled).
Definition: CD_CoarseFineDeposition.H:26
Agglomeration of useful data operations.
DepositionType
Deposition types.
Definition: CD_DepositionType.H:23
Declaration of solver class for Ito diffusion.
File containing some useful static methods related to random number generation.
Vector< RefCountedPtr< LevelData< BaseFab< bool > >> > AMRMask
Alias for cutting down on the typic of booleans defined over AMR grids.
Definition: CD_Realm.H:36
A class for depositing and interpolating particles. Contains various useful routines for interpolatio...
Definition: CD_EBParticleMesh.H:34
void deposit(const List< P > &a_particleList, EBCellFAB &a_rho, const DepositionType a_depositionType, const bool a_forceIrregNGP=false) const
Deposit particle onto the mesh using a standard cloud width.
Definition: CD_EBParticleMeshImplem.H:25
CoarseFineDeposition m_coarseFineDeposition
Coarse-fine deposition strategy.
Definition: CD_ItoSolver.H:1246
virtual void depositParticles()
Deposit particles onto mesh.
Definition: CD_ItoSolver.cpp:1752
void depositKappaConservative(EBAMRCellData &a_phi, ParticleContainer< P > &a_particles, const DepositionType a_deposition, const CoarseFineDeposition a_coarseFineDeposition) const
Compute the cell-centered deposition – this is the main deposition function.
Definition: CD_ItoSolverImplem.H:221
bool m_forceIrregDepositionNGP
NGP deposition in cut cells or not.
Definition: CD_ItoSolver.H:1156
void depositParticlesNGP(LevelData< EBCellFAB > &a_output, const ParticleContainer< P > &a_particles, const int a_level) const noexcept
Do an NGP deposit on a specific grid level. Used for IO.
Definition: CD_ItoSolverImplem.H:85
std::string m_realm
Realm where this solve lives.
Definition: CD_ItoSolver.H:1084
DepositionType m_deposition
Deposition method when depositing particles to the mesh.
Definition: CD_ItoSolver.H:1241
std::string m_name
Solver name.
Definition: CD_ItoSolver.H:1109
RealVect randomGaussian() const
Draw a random N-dimensional Gaussian number from a normal distribution with zero with and unit standa...
Definition: CD_ItoSolverImplem.H:30
std::map< WhichContainer, ParticleContainer< ItoParticle > > m_particleContainers
Various particle containers with identifiers.
Definition: CD_ItoSolver.H:1286
int m_haloBuffer
Size of refinement boundary halo.
Definition: CD_ItoSolver.H:1141
int m_verbosity
Verbosity level for this solver.
Definition: CD_ItoSolver.H:1131
void addParticles(ListBox< ItoParticle > &a_inputParticles, const int a_lvl, const DataIndex a_dit, const bool a_destructive)
Add particles to a contain. This adds into a specific grid level and patch. The user can delete the i...
Definition: CD_ItoSolverImplem.H:50
Real m_normalDistributionTruncation
Truncation value for normal distribution.
Definition: CD_ItoSolver.H:1121
RefCountedPtr< AmrMesh > m_amr
AMR; needed for grid stuff.
Definition: CD_ItoSolver.H:1094
virtual void redistributeAMR(EBAMRCellData &a_phi) const
Redistribute mass in an AMR context.
Definition: CD_ItoSolver.cpp:1777
phase::which_phase m_phase
Phase where this solver lives.
Definition: CD_ItoSolver.H:1104
Templated class for holding particles on an AMR hierarchy with particle remapping.
Definition: CD_ParticleContainer.H:50
void transferMaskParticles(const Vector< RefCountedPtr< LevelData< BaseFab< bool >>>> &a_mask)
Copy particles to the mask particle data holder.
Definition: CD_ParticleContainerImplem.H:1599
bool isOrganizedByCell() const
Is cell-sorted or not.
Definition: CD_ParticleContainerImplem.H:224
void copyMaskParticles(const Vector< RefCountedPtr< LevelData< BaseFab< bool >>>> &a_mask) const
Copy particles to mask particle data holder.
Definition: CD_ParticleContainerImplem.H:1533
static Real getNormal01()
Get a number from a normal distribution centered on zero and variance 1.
Definition: CD_RandomImplem.H:163
Real min(const Real &a_input) noexcept
Get the minimum of the input, reduced over MPI ranks (in the Chombo communicator)
Definition: CD_ParallelOpsImplem.H:58