chombo-discharge
CD_ItoKMCGodunovStepperImplem.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_ItoKMCGodunovStepperImplem_H
13 #define CD_ItoKMCGodunovStepperImplem_H
14 
15 // Chombo includes
16 #include <ParmParse.H>
17 
18 // Our includes
20 #include <CD_Timer.H>
21 #include <CD_ParallelOps.H>
22 #include <CD_DataOps.H>
23 #include <CD_Units.H>
24 #include <CD_Photon.H>
25 #include <CD_DischargeIO.H>
26 #include <CD_NamespaceHeader.H>
27 
28 using namespace Physics::ItoKMC;
29 
30 template <typename I, typename C, typename R, typename F>
31 ItoKMCGodunovStepper<I, C, R, F>::ItoKMCGodunovStepper(RefCountedPtr<ItoKMCPhysics>& a_physics)
32  : ItoKMCStepper<I, C, R, F>(a_physics)
33 {
34  CH_TIME("ItoKMCGodunovStepper::ItoKMCGodunovStepper");
35 
36  this->m_name = "ItoKMCGodunovStepper";
37  this->m_prevDt = 0.0;
38  this->m_writeCheckpointParticles = false;
39  this->m_readCheckpointParticles = false;
40  this->m_extendConductivityEB = false;
41  this->m_smoothConductivity = false;
42  this->m_canRegridOnRestart = true;
43  this->m_prevDt = 0.0;
44 
45  this->parseOptions();
46 }
47 
48 template <typename I, typename C, typename R, typename F>
50 {
51  CH_TIME("ItoKMCGodunovStepper::~ItoKMCGodunovStepper");
52  if (this->m_verbosity > 5) {
53  pout() << "ItoKMCGodunovStepper::~ItoKMCGodunovStepper" << endl;
54  }
55 }
56 
57 template <typename I, typename C, typename R, typename F>
58 void
60 {
61  CH_TIME("ItoKMCGodunovStepper::allocate");
62  if (this->m_verbosity > 5) {
63  pout() << "ItoKMCGodunovStepper::allocate" << endl;
64  }
65 
67 
68  // Now allocate for the conductivity particles and rho^dagger particles. This is only done in the 'allocate' routine
69  // and not in 'allocateInternals' because that would discard the particles during regrids. That has definitely never
70  // happen, and there's no way I've spent countless hours tracking down such a bug.
71  const int numItoSpecies = this->m_physics->getNumItoSpecies();
72 
73  m_conductivityParticles.resize(numItoSpecies);
74  m_irregularParticles.resize(numItoSpecies);
75  m_rhoDaggerParticles.resize(numItoSpecies);
76 
77  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
78  const int idx = solverIt.index();
79 
80  m_conductivityParticles[idx] = RefCountedPtr<ParticleContainer<PointParticle>>(
82  m_irregularParticles[idx] = RefCountedPtr<ParticleContainer<PointParticle>>(new ParticleContainer<PointParticle>());
83  m_rhoDaggerParticles[idx] = RefCountedPtr<ParticleContainer<PointParticle>>(new ParticleContainer<PointParticle>());
84 
85  (this->m_amr)->allocate(*m_conductivityParticles[idx], this->m_particleRealm);
86  (this->m_amr)->allocate(*m_irregularParticles[idx], this->m_particleRealm);
87  (this->m_amr)->allocate(*m_rhoDaggerParticles[idx], this->m_particleRealm);
88  }
89 }
90 
91 template <typename I, typename C, typename R, typename F>
92 void
94 {
95  CH_TIME("ItoKMCGodunovStepper::allocateInternals");
96  if (this->m_verbosity > 5) {
97  pout() << this->m_name + "::allocateInternals" << endl;
98  }
99 
101 
102  const int numCdrSpecies = this->m_physics->getNumCdrSpecies();
103 
104  m_cdrDivD.resize(numCdrSpecies);
105  for (int i = 0; i < numCdrSpecies; i++) {
106  this->m_amr->allocate(m_cdrDivD[i], this->m_fluidRealm, this->m_plasmaPhase, 1);
107  }
108 
109  this->m_amr->allocate(m_semiImplicitRhoCDR, this->m_fluidRealm, this->m_plasmaPhase, 1);
110  this->m_amr->allocate(m_semiImplicitConductivityCDR, this->m_fluidRealm, this->m_plasmaPhase, 1);
111 }
112 
113 template <typename I, typename C, typename R, typename F>
114 void
116 {
117  CH_TIME("ItoKMCGodunovStepper::barrier");
118  if (this->m_verbosity > 5) {
119  pout() << this->m_name + "::barrier" << endl;
120  }
121 
122  if ((this->m_profile)) {
124  }
125 }
126 
127 template <typename I, typename C, typename R, typename F>
128 void
130 {
131  CH_TIME("ItoKMCGodunovStepper::parseOptions");
132  if (this->m_verbosity > 5) {
133  pout() << this->m_name + "::parseOptions" << endl;
134  }
135 
137 
138  this->parseAlgorithm();
139  this->parseCheckpointParticles();
140 }
141 
142 template <typename I, typename C, typename R, typename F>
143 void
145 {
146  CH_TIME("ItoKMCGodunovStepper::parseRuntimeOptions");
147  if (this->m_verbosity > 5) {
148  pout() << this->m_name + "::parseRuntimeOptions" << endl;
149  }
150 
152 
153  this->parseAlgorithm();
154  this->parseCheckpointParticles();
155 }
156 
157 template <typename I, typename C, typename R, typename F>
158 void
160 {
161  CH_TIME("ItoKMCGodunovStepper::parseAlgorithm");
162  if (this->m_verbosity > 5) {
163  pout() << this->m_name + "::parseAlgorithm" << endl;
164  }
165 
166  ParmParse pp(this->m_name.c_str());
167  std::string str;
168 
169  pp.get("extend_conductivity", m_extendConductivityEB);
170  pp.get("smooth_conductivity", m_smoothConductivity);
171  pp.get("algorithm", str);
172 
173  // Get algorithm
174  if (str == "euler_maruyama") {
175  m_algorithm = WhichAlgorithm::EulerMaruyama;
176  }
177  else {
178  MayDay::Abort("ItoKMCGodunovStepper::parseAlgorithm - unknown algorithm requested");
179  }
180 }
181 
182 template <typename I, typename C, typename R, typename F>
183 void
185 {
186  CH_TIME("ItoKMCGodunovStepper::parseCheckpointParticles");
187  if (this->m_verbosity > 5) {
188  pout() << this->m_name + "::parseCheckpointParticles" << endl;
189  }
190 
191  ParmParse pp(this->m_name.c_str());
192 
193  pp.query("checkpoint_particles", m_writeCheckpointParticles);
194 }
195 
196 template <typename I, typename C, typename R, typename F>
197 Real
199 {
200  CH_TIME("ItoKMCGodunovStepper::advance");
201  if (this->m_verbosity > 5) {
202  pout() << this->m_name + "::advance" << endl;
203  }
204 
205  auto debugCharge = [this](const std::string a_message) -> void {
206  const Real Qtot = this->computeTotalCharge();
207  if (procID() == 0) {
208  std::cout << a_message << " = " << Qtot << "\n";
209  }
210  };
211 
212  // Special flag for telling the class that we have the necessary things in place for doing a regrid. This is
213  // an if-but-maybe situation where the user chose not to checkpoint the particles we need for regrids, yet tries
214  // to restart a simulation and regrid without all the prerequisites being in place. This flag is set to true
215  // because these requirements are checked during the regrid routine.
216  m_canRegridOnRestart = true;
217 
218  m_timer = Timer("ItoKMCGodunovStepper::advance");
219 
220  // debugCharge("advance");
221 
222  // Previous time step is needed when regridding.
223  this->m_prevDt = a_dt;
224 
225  // Done only so we can plot the absorbed photons (advanceReactionNetwork absorbs them)
226  m_timer.startEvent("Deposit photons");
227  for (auto solverIt = (this->m_rte)->iterator(); solverIt.ok(); ++solverIt) {
228  RefCountedPtr<McPhoto> solver = solverIt();
229 
230  EBAMRCellData& phi = solver->getPhi();
231  ParticleContainer<Photon>& photons = solver->getBulkPhotons();
232 
233  solver->depositPhotons<Photon, &Photon::weight>(phi, photons, DepositionType::NGP);
234  }
235  m_timer.stopEvent("Deposit photons");
236 
237  // ====== BEGIN TRANSPORT STEP ======
238  // Semi-implicitly advance the particles and the field.
239  switch (m_algorithm) {
240  case WhichAlgorithm::EulerMaruyama: {
241  this->advanceEulerMaruyama(a_dt);
242 
243  break;
244  }
245  default: {
246  MayDay::Abort("ItoKMCGodunovStepper::advance - logic bust");
247 
248  break;
249  }
250  }
251 
252  // Do intersection test and remove particles that struck the EB or domain. Transfer them to appropriate containers. Then recompute the number of particles per cell.
253  this->barrier();
254  m_timer.startEvent("EB/Particle intersection");
255  if (m_extendConductivityEB) {
256 
257  // TLDR: This hook does a special intersection routine where instead of transferring the particles that were intersected, they
258  // are put in a separate data container. We want to do this in order to reduce artificial gradients in the particle
259  // densities near the EB. The way we do this is that we flag the particles during the intersection; particles that are flagged
260  // are transferred to a container which is added to the conductivity-related particles. The particles are later removed.
261  auto setFlag = [](ItoParticle& p) -> void {
262  p.tmpReal() = 1.0;
263  };
264  auto nonDeletionModifier = [](ItoParticle& p) -> void {
265  p.tmpReal() = -1.0;
266  };
267  auto removeCrit = [](const ItoParticle& p) -> bool {
268  return p.tmpReal() < 0.0;
269  };
270 
271  // Set flag for identifying which particles were intersected by not removed.
272  for (auto it = this->m_ito->iterator(); it.ok(); ++it) {
273  ParticleOps::setData<ItoParticle>(it()->getParticles(ItoSolver::WhichContainer::Bulk), setFlag);
274  }
275 
276  // Intersect particles, but don't remove them.
277  const bool deleteParticles = false;
278  this->intersectParticles(SpeciesSubset::AllMobileOrDiffusive, deleteParticles, nonDeletionModifier);
279 
280  // Particles that were not removed are copied to a separate data container.
281  for (auto it = this->m_ito->iterator(); it.ok(); ++it) {
282  const RefCountedPtr<ItoSolver>& solver = it();
283  const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
284 
285  const int idx = it.index();
286  const int Z = species->getChargeNumber();
287 
288  ParticleContainer<PointParticle>& irregParticles = *m_irregularParticles[idx];
289  ParticleContainer<ItoParticle>& ebParticles = solver->getParticles(ItoSolver::WhichContainer::EB);
290  ParticleContainer<ItoParticle>& bulkParticles = it()->getParticles(ItoSolver::WhichContainer::Bulk);
291 
292  irregParticles.clearParticles();
293 
294  if (Z != 0 && solver->isMobile()) {
295  for (int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
296  const DisjointBoxLayout& dbl = (this->m_amr)->getGrids((this->m_particleRealm))[lvl];
297  const DataIterator& dit = dbl.dataIterator();
298 
299  const int nbox = dit.size();
300 
301 #pragma omp parallel for schedule(runtime)
302  for (int mybox = 0; mybox < nbox; mybox++) {
303  const DataIndex& din = dit[mybox];
304 
305  List<PointParticle>& pointParticles = irregParticles[lvl][din].listItems();
306  const List<ItoParticle>& patchParticles = bulkParticles[lvl][din].listItems();
307 
308  for (ListIterator<ItoParticle> lit(patchParticles); lit.ok(); ++lit) {
309  const ItoParticle& p = lit();
310 
311  if (p.tmpReal() < 0.0) {
312  const RealVect& pos = p.position();
313  const Real& weight = p.weight();
314  const Real& mobility = p.mobility();
315 
316  pointParticles.add(PointParticle(pos, weight * mobility));
317  }
318  }
319  }
320  }
321  }
322  }
323 
324  // Finally, delete the original particles
325  for (auto it = this->m_ito->iterator(); it.ok(); ++it) {
326  ParticleContainer<ItoParticle>& bulkParticles = it()->getParticles(ItoSolver::WhichContainer::Bulk);
327  ParticleOps::removeParticles<ItoParticle>(bulkParticles, removeCrit);
328  }
329  }
330  else {
331  const bool deleteParticles = true;
332 
333  this->intersectParticles(SpeciesSubset::AllMobileOrDiffusive, deleteParticles);
334  }
335 
336  // The intersection tests above may not have caught all particles -- do a cleanup sweep where particles on the wrong side of
337  // the EB are put on the EB.
338  for (auto it = this->m_ito->iterator(); it.ok(); ++it) {
339  const RefCountedPtr<ItoSolver>& solver = it();
340 
341  ParticleContainer<ItoParticle>& ebParticles = solver->getParticles(ItoSolver::WhichContainer::EB);
342  ParticleContainer<ItoParticle>& bulkParticles = solver->getParticles(ItoSolver::WhichContainer::Bulk);
343 
344  this->m_amr->transferIrregularParticles(ebParticles, bulkParticles, this->m_plasmaPhase);
345  }
346 
347  m_timer.stopEvent("EB/Particle intersection");
348 
349  // Remove the run-time configurable particle storage. It is no longer needed.
350  // ====== END TRANSPORT STEP ======
351 
352  // Photon transport
353  this->barrier();
354  m_timer.startEvent("Photon transport");
355  this->advancePhotons(a_dt);
356  m_timer.stopEvent("Photon transport");
357 
358  // Compute the gradients of the various species densities - this is used in the KMC kernels.
359  if ((this->m_physics)->needGradients()) {
360  m_timer.startEvent("Gradient calculation");
361  (this->m_ito)->depositParticles();
362  this->computeDensityGradients();
363  m_timer.stopEvent("Gradient calculation");
364  }
365 
366  // Sort the particles and photons per cell so we can call reaction algorithms
367  this->barrier();
368  m_timer.startEvent("Sort by cell");
369  (this->m_ito)->organizeParticlesByCell(ItoSolver::WhichContainer::Bulk);
370  this->sortPhotonsByCell(McPhoto::WhichContainer::Bulk);
371  this->sortPhotonsByCell(McPhoto::WhichContainer::Source);
372  m_timer.stopEvent("Sort by cell");
373 
374  // Run the Kinetic Monte Carlo reaction kernels.
375  this->barrier();
376  m_timer.startEvent("Reaction network");
377  this->advanceReactionNetwork(a_dt);
378  m_timer.stopEvent("Reaction network");
379 
380  // Sort particles per patch.
381  this->barrier();
382  m_timer.startEvent("Sort by patch");
383  (this->m_ito)->organizeParticlesByPatch(ItoSolver::WhichContainer::Bulk);
384  this->sortPhotonsByPatch(McPhoto::WhichContainer::Bulk);
385  this->sortPhotonsByPatch(McPhoto::WhichContainer::Source);
386  m_timer.stopEvent("Sort by patch");
387 
388  // Resolve secondary emission. We have filled the relevant particles in the transport step. This is done
389  // AFTER the reaction step to improve stability behavior in cathode sheaths.
390  this->barrier();
391  m_timer.startEvent("EB particle injection");
392  this->fillSecondaryEmissionEB(a_dt);
393  this->resolveSecondaryEmissionEB(a_dt);
394  m_timer.stopEvent("EB particle injection");
395 
396  // Remove particles that are inside the EB -- this is not a part of the algorithm, just a safety measure to make sure
397  // we don't do things with particles that lie inside the EB.
398  this->barrier();
399  m_timer.startEvent("Remove covered");
400  this->removeCoveredParticles(SpeciesSubset::AllMobileOrDiffusive, EBRepresentation::Discrete, this->m_toleranceEB);
401  m_timer.stopEvent("Remove covered");
402 
403  // Clear BC data holders.
404  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
405  solverIt()->clear(ItoSolver::WhichContainer::EB);
406  solverIt()->clear(ItoSolver::WhichContainer::Domain);
407  }
408 
409  // Prepare for the next time step
410  this->barrier();
411  m_timer.startEvent("Post-compute v");
412  this->computeDriftVelocities();
413  m_timer.stopEvent("Post-compute v");
414 
415  this->barrier();
416  m_timer.startEvent("Post-compute D");
417  this->computeDiffusionCoefficients();
418  m_timer.stopEvent("Post-compute D");
419 
420  if ((this->m_profile)) {
421  m_timer.eventReport(pout(), false);
422  }
423 
424  m_timer.clear();
425 
426  return a_dt;
427 }
428 
429 template <typename I, typename C, typename R, typename F>
430 void
431 ItoKMCGodunovStepper<I, C, R, F>::preRegrid(const int a_lmin, const int a_oldFinestLevel) noexcept
432 {
433  CH_TIME("ItoKMCGodunovStepper::preRegrid");
434  if (this->m_verbosity > 5) {
435  pout() << "ItoKMCGodunovStepper::preRegrid" << endl;
436  }
437 
438  const int numItoSpecies = (this->m_physics)->getNumItoSpecies();
439  const int numCdrSpecies = (this->m_physics)->getNumCdrSpecies();
440  const int numPlasmaSpecies = (this->m_physics)->getNumPlasmaSpecies();
441  const int numPhotonSpecies = (this->m_physics)->getNumPhotonSpecies();
442 
443  ItoKMCStepper<I, C, R, F>::preRegrid(a_lmin, a_oldFinestLevel);
444 
445  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
446  const int idx = solverIt.index();
447 
448  m_conductivityParticles[idx]->preRegrid(a_lmin);
449  m_irregularParticles[idx]->preRegrid(a_lmin);
450  m_rhoDaggerParticles[idx]->preRegrid(a_lmin);
451  }
452 
453  this->m_amr->allocate(m_scratchSemiImplicitRhoCDR, this->m_fluidRealm, this->m_plasmaPhase, 1);
454  this->m_amr->allocate(m_scratchSemiImplicitConductivityCDR, this->m_fluidRealm, this->m_plasmaPhase, 1);
455 
456  DataOps::copy(m_scratchSemiImplicitRhoCDR, m_semiImplicitRhoCDR);
457  DataOps::copy(m_scratchSemiImplicitConductivityCDR, m_semiImplicitConductivityCDR);
458 
459  // Release unecessary storage.
460  for (int i = 0; i < numCdrSpecies; i++) {
461  m_cdrDivD[i].clear();
462  }
463 
464  m_semiImplicitRhoCDR.clear();
465  m_semiImplicitConductivityCDR.clear();
466 }
467 
468 template <typename I, typename C, typename R, typename F>
469 void
471  const int a_oldFinestLevel,
472  const int a_newFinestLevel) noexcept
473 {
474  CH_TIME("ItoKMCGodunovStepper::regrid");
475  if (this->m_verbosity > 5) {
476  pout() << "ItoKMCGodunovStepper::regrid" << endl;
477  }
478 
479  m_timer = Timer("ItoKMCGodunovStepper::regrid");
480 
481  // A special flag for aborting the simulation if the user did NOT put checkpoint particles in the checkpoint
482  // file but still try to regrid on restart.
483  if (!m_canRegridOnRestart) {
484  const std::string baseErr = "ItoKMCGodunovStepper::regrid -- can't regrid because";
485  const std::string err1 = "checkpoint file does not contain particles. Set Driver.initial_regrids=0";
486 
487  pout() << baseErr + err1 << endl;
488 
489  MayDay::Error((baseErr + err1).c_str());
490  }
491 
492  // Regrid solvers
493  m_timer.startEvent("Regrid ItoSolver");
494  (this->m_ito)->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
495  if (this->m_timeStep == 0) {
496  // Necessary because first time step is not semi-implicit, so it will use the densities from the
497  // Ito and CDr solvers. Howver, ItoSolver does not re-deposit the particles during regrid, so we
498  // enforce it here.
499  (this->m_ito)->depositParticles();
500  }
501  m_timer.stopEvent("Regrid ItoSolver");
502 
503  m_timer.startEvent("Regrid CdrSolver");
504  (this->m_cdr)->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
505  m_timer.stopEvent("Regrid CdrSolver");
506 
507  m_timer.startEvent("Regrid FieldSolver");
508  (this->m_fieldSolver)->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
509  m_timer.stopEvent("Regrid FieldSolver");
510 
511  m_timer.startEvent("Regrid RTE");
512  (this->m_rte)->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
513  m_timer.stopEvent("Regrid RTE");
514 
515  m_timer.startEvent("Regrid SurfaceODESolver");
516  this->m_sigmaSolver->regrid(a_lmin, a_oldFinestLevel, a_newFinestLevel);
517  m_timer.stopEvent("Regrid SurfaceODESolver");
518 
519  // Allocate internal memory for ItoKMCGodunovStepper now....
520  m_timer.startEvent("Allocate internals");
521  this->allocateInternals();
522  m_timer.stopEvent("Allocate internals");
523 
524  // We need to remap/regrid the stored data required for the semi-implicit update as well.
525  m_timer.startEvent("Remap algorithm-particles");
526  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
527  const int idx = solverIt.index();
528  (this->m_amr)->remapToNewGrids(*m_rhoDaggerParticles[idx], a_lmin, a_newFinestLevel);
529  (this->m_amr)->remapToNewGrids(*m_conductivityParticles[idx], a_lmin, a_newFinestLevel);
530  (this->m_amr)->remapToNewGrids(*m_irregularParticles[idx], a_lmin, a_newFinestLevel);
531  }
532  m_timer.stopEvent("Remap algorithm-particles");
533 
534  // Also regrid the space charge density contribution from the CDR equations
535  this->m_amr->interpToNewGrids(m_semiImplicitRhoCDR,
536  m_scratchSemiImplicitRhoCDR,
537  this->m_plasmaPhase,
538  a_lmin,
539  a_oldFinestLevel,
540  a_newFinestLevel,
541  EBCoarseToFineInterp::Type::ConservativePWC);
542 
543  this->m_amr->interpToNewGrids(m_semiImplicitConductivityCDR,
544  m_scratchSemiImplicitConductivityCDR,
545  this->m_plasmaPhase,
546  a_lmin,
547  a_oldFinestLevel,
548  a_newFinestLevel,
549  EBCoarseToFineInterp::Type::ConservativePWC);
550 
551  // Set up the field solver with standard coefficients or with
552  // modified coefficients if we are reusing data from the last time step.
553  m_timer.startEvent("Setup field solver");
554  (this->m_fieldSolver)->setupSolver();
555  this->computeConductivities(m_conductivityParticles);
556  this->setupSemiImplicitPoisson(this->m_prevDt);
557  m_timer.stopEvent("Setup field solver");
558 
559  // Solve the Poisson equation.
560  m_timer.startEvent("Solve Poisson");
561  if (this->m_timeStep == 0) {
562  this->computeSpaceChargeDensity();
563  }
564  else {
565  this->depositPointParticles(m_rhoDaggerParticles, SpeciesSubset::All);
566  this->computeSemiImplicitRho();
567  }
568 
569  const bool converged = this->solvePoisson();
570 
571  if (!converged) {
572  const std::string errMsg = "ItoKMCGodunovStepper::regrid - Poisson solve did not converge after regrid";
573 
574  pout() << errMsg << endl;
575 
576  if (this->m_abortOnFailure) {
577  MayDay::Error(errMsg.c_str());
578  }
579  }
580  m_timer.stopEvent("Solve Poisson");
581 
582  // Regrid superparticles.
583  if (this->m_regridSuperparticles) {
584  m_timer.startEvent("Make superparticles");
585  (this->m_ito)->organizeParticlesByCell(ItoSolver::WhichContainer::Bulk);
586  (this->m_ito)->makeSuperparticles(ItoSolver::WhichContainer::Bulk, (this->m_particlesPerCell));
587  (this->m_ito)->organizeParticlesByPatch(ItoSolver::WhichContainer::Bulk);
588  m_timer.stopEvent("Make superparticles");
589  }
590 
591  // Now let Ihe ito solver deposit its actual particles... In the above it deposit m_rhoDaggerParticles.
592  m_timer.startEvent("Deposit particles");
593  (this->m_ito)->depositParticles();
594  m_timer.stopEvent("Deposit particles");
595 
596  // Recompute new velocities and diffusion coefficients
597  m_timer.startEvent("Prepare next step");
598  this->computeDiffusionCoefficients();
599  this->computeDriftVelocities();
600  m_timer.stopEvent("Prepare next step");
601 
602  m_timer.eventReport(pout(), false);
603 
604  // No reason to have this lying around.
605  this->m_amr->deallocate(m_scratchSemiImplicitRhoCDR);
606 }
607 
608 template <typename I, typename C, typename R, typename F>
609 void
611 {
612  CH_TIME("ItoKMCGodunovStepper::setOldPositions");
613  if (this->m_verbosity > 5) {
614  pout() << this->m_name + "::setOldPositions" << endl;
615  }
616 
617  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
618  RefCountedPtr<ItoSolver>& solver = solverIt();
619 
620  for (int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
621  const DisjointBoxLayout& dbl = (this->m_amr)->getGrids((this->m_particleRealm))[lvl];
622  const DataIterator& dit = dbl.dataIterator();
623 
624  ParticleData<ItoParticle>& particles = solver->getParticles(ItoSolver::WhichContainer::Bulk)[lvl];
625 
626  const int nbox = dit.size();
627 
628 #pragma omp parallel for schedule(runtime)
629  for (int mybox = 0; mybox < nbox; mybox++) {
630  const DataIndex& din = dit[mybox];
631 
632  List<ItoParticle>& particleList = particles[din].listItems();
633 
634  for (ListIterator<ItoParticle> lit(particleList); lit.ok(); ++lit) {
635  ItoParticle& p = lit();
636 
637  p.oldPosition() = p.position();
638  }
639  }
640  }
641  }
642 }
643 
644 template <typename I, typename C, typename R, typename F>
645 void
647  Vector<RefCountedPtr<ParticleContainer<PointParticle>>>& a_particles,
648  const SpeciesSubset a_subset) noexcept
649 {
650  CH_TIME("ItoKMCGodunovStepper::remapPointParticles");
651  if (this->m_verbosity > 5) {
652  pout() << this->m_name + "::remapPointParticles" << endl;
653  }
654 
655  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
656  RefCountedPtr<ItoSolver>& solver = solverIt();
657  const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
658 
659  const int idx = solverIt.index();
660 
661  const bool mobile = solver->isMobile();
662  const bool diffusive = solver->isDiffusive();
663  const bool charged = species->getChargeNumber() != 0;
664 
665  switch (a_subset) {
666  case SpeciesSubset::All: {
667  a_particles[idx]->remap();
668 
669  break;
670  }
671  case SpeciesSubset::AllMobile: {
672  if (mobile) {
673  a_particles[idx]->remap();
674  }
675 
676  break;
677  }
678  case SpeciesSubset::AllDiffusive: {
679  if (diffusive) {
680  a_particles[idx]->remap();
681  }
682 
683  break;
684  }
685  case SpeciesSubset::AllMobileOrDiffusive: {
686  if (mobile || diffusive) {
687  a_particles[idx]->remap();
688  }
689 
690  break;
691  }
692  case SpeciesSubset::AllMobileAndDiffusive: {
693  if (mobile && diffusive) {
694  a_particles[idx]->remap();
695  }
696 
697  break;
698  }
699  case SpeciesSubset::Charged: {
700  if (charged) {
701  a_particles[idx]->remap();
702  }
703 
704  break;
705  }
706  case SpeciesSubset::ChargedMobile: {
707  if (charged && mobile) {
708  a_particles[idx]->remap();
709  }
710 
711  break;
712  }
713  case SpeciesSubset::ChargedDiffusive: {
714  if (charged && diffusive) {
715  a_particles[idx]->remap();
716  }
717 
718  break;
719  }
720  case SpeciesSubset::ChargedMobileOrDiffusive: {
721  if (charged && (mobile || diffusive)) {
722  a_particles[idx]->remap();
723  }
724 
725  break;
726  }
727  case SpeciesSubset::ChargedMobileAndDiffusive: {
728  if (charged && (mobile && diffusive)) {
729  a_particles[idx]->remap();
730  }
731 
732  break;
733  }
734  case SpeciesSubset::Stationary: {
735  if (!mobile && !diffusive) {
736  a_particles[idx]->remap();
737  }
738 
739  break;
740  }
741  default: {
742  MayDay::Abort("ItoKMCGodunovStepper::remapPointParticles - logic bust");
743 
744  break;
745  }
746  }
747  }
748 }
749 
750 template <typename I, typename C, typename R, typename F>
751 void
753  const Vector<RefCountedPtr<ParticleContainer<PointParticle>>>& a_particles,
754  const SpeciesSubset a_subset) noexcept
755 {
756  CH_TIME("ItoKMCGodunovStepper::depositPointParticles");
757  if (this->m_verbosity > 5) {
758  pout() << this->m_name + "::depositPointParticles" << endl;
759  }
760 
761  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
762  RefCountedPtr<ItoSolver>& solver = solverIt();
763  const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
764 
765  const int idx = solverIt.index();
766 
767  const bool mobile = solver->isMobile();
768  const bool diffusive = solver->isDiffusive();
769  const bool charged = species->getChargeNumber() != 0;
770 
771  switch (a_subset) {
772  case SpeciesSubset::All: {
773  solver->depositParticles<PointParticle, &PointParticle::weight>(solver->getPhi(), *a_particles[idx]);
774 
775  break;
776  }
777  case SpeciesSubset::AllMobile: {
778  if (mobile) {
779  solver->depositParticles<PointParticle, &PointParticle::weight>(solver->getPhi(), *a_particles[idx]);
780  }
781 
782  break;
783  }
784  case SpeciesSubset::AllDiffusive: {
785  if (diffusive) {
786  solver->depositParticles<PointParticle, &PointParticle::weight>(solver->getPhi(), *a_particles[idx]);
787  }
788 
789  break;
790  }
791  case SpeciesSubset::AllMobileOrDiffusive: {
792  if (mobile || diffusive) {
793  solver->depositParticles<PointParticle, &PointParticle::weight>(solver->getPhi(), *a_particles[idx]);
794  }
795  break;
796  }
797  case SpeciesSubset::AllMobileAndDiffusive: {
798  if (mobile && diffusive) {
799  solver->depositParticles<PointParticle, &PointParticle::weight>(solver->getPhi(), *a_particles[idx]);
800  }
801  break;
802  }
803  case SpeciesSubset::Charged: {
804  if (charged) {
805  solver->depositParticles<PointParticle, &PointParticle::weight>(solver->getPhi(), *a_particles[idx]);
806  }
807  break;
808  }
809  case SpeciesSubset::ChargedMobile: {
810  if (charged && mobile) {
811  solver->depositParticles<PointParticle, &PointParticle::weight>(solver->getPhi(), *a_particles[idx]);
812  }
813  break;
814  }
815  case SpeciesSubset::ChargedDiffusive: {
816  if (charged && diffusive) {
817  solver->depositParticles<PointParticle, &PointParticle::weight>(solver->getPhi(), *a_particles[idx]);
818  }
819 
820  break;
821  }
822  case SpeciesSubset::ChargedMobileOrDiffusive: {
823  if (charged && (mobile || diffusive)) {
824  solver->depositParticles<PointParticle, &PointParticle::weight>(solver->getPhi(), *a_particles[idx]);
825  }
826 
827  break;
828  }
829  case SpeciesSubset::ChargedMobileAndDiffusive: {
830  if (charged && (mobile && diffusive)) {
831  solver->depositParticles<PointParticle, &PointParticle::weight>(solver->getPhi(), *a_particles[idx]);
832  }
833 
834  break;
835  }
836  case SpeciesSubset::Stationary: {
837  if (!mobile && !diffusive) {
838  solver->depositParticles<PointParticle, &PointParticle::weight>(solver->getPhi(), *a_particles[idx]);
839  }
840 
841  break;
842  }
843  default: {
844  MayDay::Abort("ItoKMCGodunovStepper::depositPointParticles - logic bust");
845 
846  break;
847  }
848  }
849  }
850 }
851 
852 template <typename I, typename C, typename R, typename F>
853 void
855  const Vector<RefCountedPtr<ParticleContainer<PointParticle>>>& a_particles,
856  const SpeciesSubset a_subset) noexcept
857 {
858  CH_TIME("ItoKMCGodunovStepper::clearPointParticles");
859  if (this->m_verbosity > 5) {
860  pout() << this->m_name + "::clearPointParticles" << endl;
861  }
862 
863  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
864  RefCountedPtr<ItoSolver>& solver = solverIt();
865  const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
866 
867  const int idx = solverIt.index();
868 
869  const bool mobile = solver->isMobile();
870  const bool diffusive = solver->isDiffusive();
871  const bool charged = species->getChargeNumber() != 0;
872 
873  switch (a_subset) {
874  case SpeciesSubset::All: {
875  a_particles[idx]->clearParticles();
876 
877  break;
878  }
879  case SpeciesSubset::AllMobile: {
880  if (mobile) {
881  a_particles[idx]->clearParticles();
882  }
883 
884  break;
885  }
886  case SpeciesSubset::AllDiffusive: {
887  if (diffusive) {
888  a_particles[idx]->clearParticles();
889  }
890 
891  break;
892  }
893  case SpeciesSubset::AllMobileOrDiffusive: {
894  if (mobile || diffusive) {
895  a_particles[idx]->clearParticles();
896  }
897 
898  break;
899  }
900  case SpeciesSubset::AllMobileAndDiffusive: {
901  if (mobile && diffusive) {
902  a_particles[idx]->clearParticles();
903  }
904 
905  break;
906  }
907  case SpeciesSubset::Charged: {
908  if (charged) {
909  a_particles[idx]->clearParticles();
910  }
911 
912  break;
913  }
914  case SpeciesSubset::ChargedMobile: {
915  if (charged && mobile) {
916  a_particles[idx]->clearParticles();
917  }
918 
919  break;
920  }
921  case SpeciesSubset::ChargedDiffusive: {
922  if (charged && diffusive) {
923  a_particles[idx]->clearParticles();
924  }
925 
926  break;
927  }
928  case SpeciesSubset::ChargedMobileOrDiffusive: {
929  if (charged && (mobile || diffusive)) {
930  a_particles[idx]->clearParticles();
931  }
932 
933  break;
934  }
935  case SpeciesSubset::ChargedMobileAndDiffusive: {
936  if (charged && (mobile && diffusive)) {
937  a_particles[idx]->clearParticles();
938  }
939 
940  break;
941  }
942  case SpeciesSubset::Stationary: {
943  if (!mobile && !diffusive) {
944  a_particles[idx]->clearParticles();
945  }
946 
947  break;
948  }
949  default: {
950  MayDay::Abort("ItoKMCGodunovStepper::clearPointParticles - logic bust");
951 
952  break;
953  }
954  }
955  }
956 }
957 
958 template <typename I, typename C, typename R, typename F>
959 void
961  const Vector<RefCountedPtr<ParticleContainer<PointParticle>>>& a_particles) noexcept
962 {
963  CH_TIME("ItoKMCGodunovStepper::computeConductivities");
964  if (this->m_verbosity > 5) {
965  pout() << this->m_name + "::computeConductivities" << endl;
966  }
967 
968  this->computeCellConductivity((this->m_conductivityCell), a_particles);
969  this->computeFaceConductivity();
970 }
971 
972 template <typename I, typename C, typename R, typename F>
973 void
975  EBAMRCellData& a_conductivityCell,
976  const Vector<RefCountedPtr<ParticleContainer<PointParticle>>>& a_particles) noexcept
977 {
978  CH_TIME("ItoKMCGodunovStepper::computeCellConductivity(EBAMRCellData, PointParticle");
979  if (this->m_verbosity > 5) {
980  pout() << this->m_name + "::computeCellConductivity(EBAMRCellData, PointParticle)" << endl;
981  }
982 
983  DataOps::setValue(a_conductivityCell, 0.0);
984 
985  // Contribution from Ito solvers.
986  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
987  RefCountedPtr<ItoSolver>& solver = solverIt();
988  const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
989 
990  const int idx = solverIt.index();
991  const int Z = species->getChargeNumber();
992 
993  if (Z != 0 && solver->isMobile()) {
994  // Deposit on the particle realm.
995  DataOps::setValue(this->m_particleScratch1, 0.0);
996  solver->depositParticles<PointParticle, &PointParticle::weight>(this->m_particleScratch1, *a_particles[idx]);
997 
998  // Copy to fluid realm and add to total conductivity.
999  (this->m_amr)->copyData(this->m_fluidScratch1, this->m_particleScratch1);
1000  DataOps::incr(a_conductivityCell, this->m_fluidScratch1, 1.0 * std::abs(Z));
1001  }
1002  }
1003 
1004  // Contribution from CDR solvers.
1005  DataOps::setValue(m_semiImplicitConductivityCDR, 0.0);
1006  for (auto solverIt = (this->m_cdr)->iterator(); solverIt.ok(); ++solverIt) {
1007  const RefCountedPtr<CdrSolver>& solver = solverIt();
1008  const RefCountedPtr<CdrSpecies>& species = solver->getSpecies();
1009 
1010  const int index = solverIt.index();
1011  const int Z = species->getChargeNumber();
1012 
1013  if (Z != 0 && solver->isMobile()) {
1014  const EBAMRCellData& phi = solver->getPhi();
1015  const EBAMRCellData& mu = this->m_cdrMobilities[index];
1016 
1017  DataOps::copy(this->m_fluidScratch1, phi);
1018  DataOps::multiply(this->m_fluidScratch1, mu);
1019 
1020  DataOps::incr(a_conductivityCell, this->m_fluidScratch1, 1.0 * std::abs(Z));
1021  }
1022  }
1023 
1024  // Conductivity is mobility * weight * Q
1025  DataOps::scale(a_conductivityCell, Units::Qe);
1026 
1027  // Coarsen, update ghost cells and interpolate to centroids. User can ask for bi/tri-linear filtering.
1028  (this->m_amr)->arithmeticAverage(a_conductivityCell, this->m_fluidRealm, (this->m_plasmaPhase));
1029  (this->m_amr)->interpGhostPwl(a_conductivityCell, this->m_fluidRealm, (this->m_plasmaPhase));
1030 
1031  if (this->m_smoothConductivity) {
1032  const Real alpha = 0.5;
1033  const int stride = 1;
1034 
1035  DataOps::filterSmooth(a_conductivityCell, alpha, stride, true);
1036 
1037  (this->m_amr)->arithmeticAverage(a_conductivityCell, this->m_fluidRealm, (this->m_plasmaPhase));
1038  (this->m_amr)->interpGhostPwl(a_conductivityCell, this->m_fluidRealm, (this->m_plasmaPhase));
1039  }
1040 
1041  (this->m_amr)->interpToCentroids(a_conductivityCell, this->m_fluidRealm, (this->m_plasmaPhase));
1042 }
1043 
1044 template <typename I, typename C, typename R, typename F>
1045 void
1047 {
1048  CH_TIME("ItoKMCGodunovStepper::computeFaceConductivity");
1049  if (this->m_verbosity > 5) {
1050  pout() << this->m_name + "::computeFaceConductivity" << endl;
1051  }
1052 
1053  DataOps::setValue((this->m_conductivityFace), 0.0);
1054  DataOps::setValue((this->m_conductivityEB), 0.0);
1055 
1056  // Average the cell-centered conductivity to faces. Note that this includes one "ghost face", which we need
1057  // because the multigrid solver will interpolate face-centered conductivities to face centroids.
1058  const Average average = Average::Arithmetic;
1059  const int tanGhost = 1;
1060  const Interval interv(0, 0);
1061 
1062  DataOps::averageCellToFace((this->m_conductivityFace),
1063  (this->m_conductivityCell),
1064  (this->m_amr)->getDomains(),
1065  tanGhost,
1066  interv,
1067  interv,
1068  average);
1069 
1070  // Set the EB conductivity.
1071  DataOps::incr((this->m_conductivityEB), (this->m_conductivityCell), 1.0);
1072 }
1073 
1074 template <typename I, typename C, typename R, typename F>
1075 void
1077 {
1078  CH_TIME("ItoKMCGodunovStepper::computeSemiImplicitRho");
1079  if (this->m_verbosity > 5) {
1080  pout() << this->m_name + "::computeSemiImplicitRho" << endl;
1081  }
1082 
1083  MFAMRCellData& rho = this->m_fieldSolver->getRho();
1084  EBAMRCellData rhoPhase = this->m_amr->alias(this->m_plasmaPhase, rho);
1085 
1086  DataOps::setValue(rho, 0.0);
1087 
1088  // Contribution from Ito solvers.
1089  for (auto solverIt = this->m_ito->iterator(); solverIt.ok(); ++solverIt) {
1090  const RefCountedPtr<ItoSolver>& solver = solverIt();
1091  const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1092  const int Z = species->getChargeNumber();
1093 
1094  if (Z != 0) {
1095  (this->m_amr)->copyData(this->m_fluidScratch1, solver->getPhi());
1096 
1097  DataOps::incr(rhoPhase, this->m_fluidScratch1, 1.0 * Z * Units::Qe);
1098  }
1099  }
1100 
1101  // Contribution from CDR equations
1102  DataOps::incr(rhoPhase, m_semiImplicitRhoCDR, 1.0);
1103 
1104  // Sync across levels
1105  this->m_amr->arithmeticAverage(rho, this->m_fluidRealm);
1106  this->m_amr->interpGhostPwl(rho, this->m_fluidRealm);
1107 
1108  this->m_amr->interpToCentroids(rhoPhase, this->m_fluidRealm, this->m_plasmaPhase);
1109 }
1110 
1111 template <typename I, typename C, typename R, typename F>
1112 void
1114 {
1115  CH_TIME("ItoKMCGodunovStepper::setupSemiImplicitPoisson");
1116  if (this->m_verbosity > 5) {
1117  pout() << this->m_name + "::setupSemiImplicitPoisson" << endl;
1118  }
1119 
1120  // Set coefficients as usual
1121  (this->m_fieldSolver)->setPermittivities();
1122 
1123  // Get the permittivities
1124  // Get the permittivities on the faces.
1125  MFAMRCellData& permCell = (this->m_fieldSolver)->getPermittivityCell();
1126  MFAMRFluxData& permFace = (this->m_fieldSolver)->getPermittivityFace();
1127  MFAMRIVData& permEB = (this->m_fieldSolver)->getPermittivityEB();
1128 
1129  // Get handles to the gas-phase permittivities.
1130  EBAMRFluxData permFaceGas = (this->m_amr)->alias((this->m_plasmaPhase), permFace);
1131  EBAMRIVData permEBGas = (this->m_amr)->alias((this->m_plasmaPhase), permEB);
1132 
1133  // Increment the field solver permittivities by a_factor*sigma. After this, the "permittivities" are
1134  // given by epsr + a_factor*sigma
1135  DataOps::incr(permFaceGas, (this->m_conductivityFace), a_dt / Units::eps0);
1136  DataOps::incr(permEBGas, (this->m_conductivityEB), a_dt / Units::eps0);
1137 
1138  // Coarsen coefficients.
1139  (this->m_amr)->arithmeticAverage(permFaceGas, this->m_fluidRealm, (this->m_plasmaPhase));
1140  (this->m_amr)->arithmeticAverage(permEBGas, this->m_fluidRealm, (this->m_plasmaPhase));
1141 
1142  // Set up the solver with the "permittivities"
1143  (this->m_fieldSolver)->setSolverPermittivities(permCell, permFace, permEB);
1144 }
1145 
1146 template <typename I, typename C, typename R, typename F>
1147 void
1149  Vector<RefCountedPtr<ParticleContainer<PointParticle>>>& a_particles,
1150  const EBRepresentation a_representation,
1151  const Real a_tolerance) const noexcept
1152 {
1153  CH_TIME("ItoKMCGodunovStepper::removeCoveredPointParticles");
1154  if (this->m_verbosity > 5) {
1155  pout() << this->m_name + "::removeCoveredPointParticles" << endl;
1156  }
1157 
1158  for (int i = 0; i < a_particles.size(); i++) {
1159  if (a_particles[i] != nullptr) {
1160  ParticleContainer<PointParticle>& particles = *a_particles[i];
1161 
1162  switch (a_representation) {
1163  case EBRepresentation::Discrete: {
1164  (this->m_amr)->removeCoveredParticlesDiscrete(particles, (this->m_plasmaPhase), a_tolerance);
1165 
1166  break;
1167  }
1168  case EBRepresentation::ImplicitFunction: {
1169  (this->m_amr)->removeCoveredParticlesIF(particles, (this->m_plasmaPhase), a_tolerance);
1170 
1171  break;
1172  }
1173  case EBRepresentation::Voxel: {
1174  (this->m_amr)->removeCoveredParticlesVoxels(particles, (this->m_plasmaPhase));
1175 
1176  break;
1177  }
1178  default: {
1179  MayDay::Error("ItoKMCGodunovStepper::removeCoveredParticles - logic bust");
1180  }
1181  }
1182  }
1183  }
1184 }
1185 
1186 template <typename I, typename C, typename R, typename F>
1187 void
1189  Vector<RefCountedPtr<ParticleContainer<PointParticle>>>& a_conductivityParticles) noexcept
1190 {
1191  CH_TIME("ItoKMCGodunovStepper::copyConductivityParticles");
1192  if (this->m_verbosity > 5) {
1193  pout() << this->m_name + "::copyConductivityParticles" << endl;
1194  }
1195 
1196  // Clear particles first.
1197  this->clearPointParticles(a_conductivityParticles, SpeciesSubset::All);
1198 
1199  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1200  const RefCountedPtr<ItoSolver>& solver = solverIt();
1201  const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1202 
1203  const int idx = solverIt.index();
1204  const int Z = species->getChargeNumber();
1205 
1206  if (Z != 0 && solver->isMobile()) {
1207  const ParticleContainer<ItoParticle>& solverParticles = solver->getParticles(ItoSolver::WhichContainer::Bulk);
1208 
1209  for (int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
1210  const DisjointBoxLayout& dbl = (this->m_amr)->getGrids((this->m_particleRealm))[lvl];
1211  const DataIterator& dit = dbl.dataIterator();
1212 
1213  const int nbox = dit.size();
1214 
1215 #pragma omp parallel for schedule(runtime)
1216  for (int mybox = 0; mybox < nbox; mybox++) {
1217  const DataIndex& din = dit[mybox];
1218 
1219  const List<ItoParticle>& patchParticles = solverParticles[lvl][din].listItems();
1220 
1221  List<PointParticle>& pointParticles = (*a_conductivityParticles[idx])[lvl][din].listItems();
1222  List<PointParticle>& irregParticles = (*m_irregularParticles[idx])[lvl][din].listItems();
1223 
1224  for (ListIterator<ItoParticle> lit(patchParticles); lit.ok(); ++lit) {
1225  const ItoParticle& p = lit();
1226  const RealVect& pos = p.position();
1227  const Real& weight = p.weight();
1228  const Real& mobility = p.mobility();
1229 
1230  pointParticles.add(PointParticle(pos, weight * mobility));
1231  }
1232 
1233  pointParticles.catenate(irregParticles);
1234  }
1235  }
1236  }
1237  }
1238 }
1239 
1240 template <typename I, typename C, typename R, typename F>
1241 void
1243 {
1244  CH_TIME("ItoKMCGodunovStepper::advanceEulerMaruyama");
1245  if (this->m_verbosity > 5) {
1246  pout() << this->m_name + "::advanceEulerMaruyama" << endl;
1247  }
1248 
1249  // Store X^k positions.
1250  this->setOldPositions();
1251 
1252  // Diffuse the particles. This copies onto m_rhoDaggerParticles and stores the hop on the full particles. We need
1253  // to remap the particles species that made a diffusion hop.
1254  this->barrier();
1255  m_timer.startEvent("Diffuse particles");
1256  this->diffuseParticlesEulerMaruyama(m_rhoDaggerParticles, a_dt);
1257  this->remapPointParticles(m_rhoDaggerParticles, SpeciesSubset::ChargedDiffusive);
1258  m_timer.stopEvent("Diffuse particles");
1259 
1260  // Perform the diffusive CDR advance.
1261  this->barrier();
1262  m_timer.startEvent("Diffuse CDR");
1263  this->computeDiffusionTermCDR(m_semiImplicitRhoCDR, a_dt);
1264  m_timer.stopEvent("Diffuse CDR");
1265 
1266  // Compute the conductivity on the mesh. This deposits q_e * Z * w * mu on the mesh.
1267  this->barrier();
1268  m_timer.startEvent("Compute conductivities");
1269  this->copyConductivityParticles(m_conductivityParticles);
1270  this->computeConductivities(m_conductivityParticles);
1271  m_timer.stopEvent("Compute conductivities");
1272 
1273  // Set up the semi-implicit Poisson solver with the computed conductivities.
1274  this->barrier();
1275  m_timer.startEvent("Setup Poisson");
1276  this->setupSemiImplicitPoisson(a_dt);
1277  m_timer.stopEvent("Setup Poisson");
1278 
1279  // Compute space charge density arising from the new particle positions X^k + sqrt(2*D*dt)*W. Only need to
1280  // do the diffusive and charged species.
1281  this->barrier();
1282  m_timer.startEvent("Deposit point particles");
1283  this->depositPointParticles(m_rhoDaggerParticles, SpeciesSubset::Charged);
1284  this->computeSemiImplicitRho();
1285  m_timer.stopEvent("Deposit point particles");
1286 
1287  // Solve the semi-implicit Poisson equation.
1288  this->barrier();
1289  m_timer.startEvent("Solve Poisson");
1290  const bool converged = this->solvePoisson();
1291  if (!converged) {
1292  const std::string
1293  errMsg = "ItoKMCGodunovStepper::advanceEulerMaruyama - Poisson solve did not converge after regrid";
1294 
1295  pout() << errMsg << endl;
1296 
1297  if (this->m_abortOnFailure) {
1298  MayDay::Error(errMsg.c_str());
1299  }
1300  }
1301  m_timer.stopEvent("Solve Poisson");
1302 
1303  // Recompute velocities with the new electric field. This interpolates the velocities to the current particle positions, i.e.
1304  // we compute V^(k+1)(X^k) = mu^k * E^(k+1)(X^k)
1305  this->barrier();
1306  m_timer.startEvent("Step-compute v");
1307 #if 1 // This is what the algorithm says.
1308  this->setCdrVelocityFunctions();
1309  this->setItoVelocityFunctions();
1310  (this->m_ito)->interpolateVelocities();
1311  this->multiplyCdrVelocitiesByMobilities();
1312 #else // Have to use this for LEA - need to debug.
1313  this->computeDriftVelocities();
1314 #endif
1315  m_timer.stopEvent("Step-compute v");
1316 
1317  // Finalize the Euler-Maruyama update.
1318  this->barrier();
1319  m_timer.startEvent("Euler-Maruyama step");
1320  this->stepEulerMaruyamaParticles(a_dt);
1321  this->remapParticles(SpeciesSubset::AllMobileOrDiffusive);
1322  this->stepEulerMaruyamaCDR(a_dt);
1323  m_timer.stopEvent("Euler-Maruyama step");
1324 }
1325 
1326 template <typename I, typename C, typename R, typename F>
1327 void
1329  Vector<RefCountedPtr<ParticleContainer<PointParticle>>>& a_rhoDaggerParticles,
1330  const Real a_dt) noexcept
1331 {
1332  CH_TIME("ItoKMCGodunovStepper::diffuseParticlesEulerMaruyama");
1333  if (this->m_verbosity > 5) {
1334  pout() << this->m_name + "::diffuseParticlesEulerMaruyama" << endl;
1335  }
1336 
1337  this->clearPointParticles(a_rhoDaggerParticles, SpeciesSubset::All);
1338 
1339  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1340  RefCountedPtr<ItoSolver>& solver = solverIt();
1341  const RefCountedPtr<ItoSpecies>& species = solver->getSpecies();
1342 
1343  const int idx = solverIt.index();
1344 
1345  const bool diffusive = solver->isDiffusive();
1346  const int Z = species->getChargeNumber();
1347 
1348  for (int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
1349  const DisjointBoxLayout& dbl = (this->m_amr)->getGrids((this->m_particleRealm))[lvl];
1350  const DataIterator& dit = dbl.dataIterator();
1351 
1352  ParticleData<ItoParticle>& particles = solver->getParticles(ItoSolver::WhichContainer::Bulk)[lvl];
1353 
1354  const int nbox = dit.size();
1355 
1356 #pragma omp parallel for schedule(runtime)
1357  for (int mybox = 0; mybox < nbox; mybox++) {
1358  const DataIndex& din = dit[mybox];
1359 
1360  List<ItoParticle>& itoParticles = particles[din].listItems();
1361  List<PointParticle>& pointParticles = (*a_rhoDaggerParticles[idx])[lvl][din].listItems();
1362 
1363  for (ListIterator<ItoParticle> lit(itoParticles); lit.ok(); ++lit) {
1364  ItoParticle& p = lit();
1365  const Real& weight = p.weight();
1366  const RealVect& pos = p.position();
1367 
1368  // Compute a particle hop and store it on the run-time storage.
1369  RealVect& hop = p.tmpVect();
1370  if (diffusive) {
1371  hop = sqrt(2.0 * p.diffusion() * a_dt) * solver->randomGaussian();
1372  }
1373  else {
1374  hop = RealVect::Zero;
1375  }
1376 
1377  if (Z != 0) {
1378  pointParticles.add(PointParticle(pos + hop, weight));
1379  }
1380  }
1381  }
1382  }
1383  }
1384 }
1385 
1386 template <typename I, typename C, typename R, typename F>
1387 void
1388 ItoKMCGodunovStepper<I, C, R, F>::computeDiffusionTermCDR(EBAMRCellData& a_semiImplicitRhoCDR, const Real a_dt) noexcept
1389 {
1390  CH_TIME("ItoKMCGodunovStepper::diffuseCDREulerMaruyama");
1391  if (this->m_verbosity > 5) {
1392  pout() << this->m_name + "::diffuseCDREulerMaruyama" << endl;
1393  }
1394 
1395  DataOps::setValue(a_semiImplicitRhoCDR, 0.0);
1396 
1397  for (auto solverIt = this->m_cdr->iterator(); solverIt.ok(); ++solverIt) {
1398  const RefCountedPtr<CdrSolver>& solver = solverIt();
1399  const RefCountedPtr<CdrSpecies>& species = solver->getSpecies();
1400 
1401  const int index = solverIt.index();
1402  const int Z = species->getChargeNumber();
1403 
1404  const EBAMRCellData& phi = solver->getPhi();
1405 
1406  // Compute finite-volume approximation to div(D*grad(phi))
1407  if (solver->isDiffusive()) {
1408  solver->computeDivD(m_cdrDivD[index], solver->getPhi(), false, false, false);
1409  }
1410 
1411  // Update the space charge density arising from the update phi^dagger = phi^k + dt * div(D*grad(phi^k))
1412  if (Z != 0) {
1413  DataOps::incr(a_semiImplicitRhoCDR, phi, 1.0 * Z);
1414  if (solver->isDiffusive()) {
1415  DataOps::incr(a_semiImplicitRhoCDR, m_cdrDivD[index], 1.0 * Z * a_dt);
1416  }
1417  }
1418  }
1419 
1420  DataOps::scale(a_semiImplicitRhoCDR, Units::Qe);
1421 
1422  this->m_amr->arithmeticAverage(a_semiImplicitRhoCDR, this->m_fluidRealm, this->m_plasmaPhase);
1423  this->m_amr->interpGhostPwl(a_semiImplicitRhoCDR, this->m_fluidRealm, this->m_plasmaPhase);
1424 }
1425 
1426 template <typename I, typename C, typename R, typename F>
1427 void
1429 {
1430  CH_TIME("ItoKMCGodunovStepper::stepEulerMaruyamaParticles");
1431  if (this->m_verbosity > 5) {
1432  pout() << this->m_name + "::stepEulerMaruyamaParticles" << endl;
1433  }
1434 
1435  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1436  RefCountedPtr<ItoSolver>& solver = solverIt();
1437 
1438  const bool mobile = solver->isMobile();
1439  const bool diffusive = solver->isDiffusive();
1440 
1441  const Real f = mobile ? a_dt : 0.0;
1442  const Real g = diffusive ? 1.0 : 0.0;
1443 
1444  if (mobile || diffusive) {
1445  for (int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
1446  const DisjointBoxLayout& dbl = (this->m_amr)->getGrids((this->m_particleRealm))[lvl];
1447  const DataIterator& dit = dbl.dataIterator();
1448 
1449  ParticleData<ItoParticle>& particles = solver->getParticles(ItoSolver::WhichContainer::Bulk)[lvl];
1450 
1451  const int nbox = dit.size();
1452 
1453 #pragma omp parallel for schedule(runtime)
1454  for (int mybox = 0; mybox < nbox; mybox++) {
1455  const DataIndex& din = dit[mybox];
1456 
1457  List<ItoParticle>& particleList = particles[din].listItems();
1458 
1459  for (ListIterator<ItoParticle> lit(particleList); lit.ok(); ++lit) {
1460  ItoParticle& p = lit();
1461 
1462  // Add in the diffusion hop and advective contribution.
1463  const RealVect& hop = p.tmpVect();
1464  p.position() = p.oldPosition() + f * p.velocity() + g * hop;
1465  }
1466  }
1467  }
1468  }
1469  }
1470 }
1471 
1472 template <typename I, typename C, typename R, typename F>
1473 void
1475 {
1476  CH_TIME("ItoKMCGodunovStepper::stepEulerMaruyamaCDR");
1477  if (this->m_verbosity > 5) {
1478  pout() << this->m_name + "::stepEulerMaruyamaCDR" << endl;
1479  }
1480 
1481  for (auto solverIt = (this->m_cdr)->iterator(); solverIt.ok(); ++solverIt) {
1482  RefCountedPtr<CdrSolver>& solver = solverIt();
1483 
1484  const int index = solverIt.index();
1485 
1486  EBAMRCellData& phi = solver->getPhi();
1487 
1488  this->m_amr->conservativeAverage(phi, this->m_fluidRealm, this->m_plasmaPhase);
1489  this->m_amr->interpGhostPwl(phi, this->m_fluidRealm, this->m_plasmaPhase);
1490 
1491  // Add in the advective term -- BC comes later.
1492  if (solver->isMobile()) {
1493  DataOps::setValue(solver->getEbFlux(), 0.0);
1494 
1495  // Compute the FV approximation to the advective term and do the Euler advance. If the underlying
1496  // CDR solver is a CTU solver, we also add in the transverse terms.
1497  solver->computeDivF(this->m_fluidScratch1, phi, 0.5 * a_dt, false, true, true);
1498 
1499  DataOps::incr(phi, this->m_fluidScratch1, -a_dt);
1500  }
1501 
1502  // Add in the diffusion term.
1503  if (solver->isDiffusive()) {
1504  DataOps::incr(phi, this->m_cdrDivD[index], a_dt);
1505  }
1506 
1507  DataOps::floor(phi, 0.0);
1508  }
1509 
1510  this->coarsenCDRSolvers();
1511 }
1512 
1513 #ifdef CH_USE_HDF5
1514 template <typename I, typename C, typename R, typename F>
1515 void
1516 ItoKMCGodunovStepper<I, C, R, F>::writeCheckpointHeader(HDF5HeaderData& a_header) const noexcept
1517 {
1518  CH_TIME("ItoKMCGodunovStepper::writeCheckpointHeader");
1519  if (this->m_verbosity > 5) {
1520  pout() << this->m_name + "::writeCheckpointHeader" << endl;
1521  }
1522 
1523  a_header.m_real["prev_dt"] = this->m_prevDt;
1524  a_header.m_int["checkpoint_particles"] = m_writeCheckpointParticles ? 1 : 0;
1525 }
1526 #endif
1527 
1528 #ifdef CH_USE_HDF5
1529 template <typename I, typename C, typename R, typename F>
1530 void
1531 ItoKMCGodunovStepper<I, C, R, F>::readCheckpointHeader(HDF5HeaderData& a_header) noexcept
1532 {
1533  CH_TIME("ItoKMCGodunovStepper::readCheckpointHeader");
1534  if (this->m_verbosity > 5) {
1535  pout() << this->m_name + "::readCheckpointHeader" << endl;
1536  }
1537 
1538  this->m_prevDt = a_header.m_real["prev_dt"];
1539  m_readCheckpointParticles = (a_header.m_int["checkpoint_particles"] != 0) ? true : false;
1540  m_canRegridOnRestart = m_readCheckpointParticles;
1541 }
1542 #endif
1543 
1544 #ifdef CH_USE_HDF5
1545 template <typename I, typename C, typename R, typename F>
1546 void
1547 ItoKMCGodunovStepper<I, C, R, F>::writeCheckpointData(HDF5Handle& a_handle, const int a_lvl) const noexcept
1548 {
1549  CH_TIME("ItoKMCGodunovStepper::writeCheckpointData");
1550  if (this->m_verbosity > 5) {
1551  pout() << this->m_name + "::writeCheckpointData" << endl;
1552  }
1553 
1555 
1556  // Write the point-particles.
1557  if (m_writeCheckpointParticles) {
1558  for (int i = 0; i < (this->m_physics)->getNumItoSpecies(); i++) {
1559  const std::string identifierSigma = "ItoKMCGodunovStepper::conductivityParticles_" + std::to_string(i);
1560  const std::string identifierRho = "ItoKMCGodunovStepper::spaceChargeParticles_" + std::to_string(i);
1561 
1562  const ParticleContainer<PointParticle>& conductivityParticles = *m_conductivityParticles[i];
1563  const ParticleContainer<PointParticle>& rhoDaggerParticles = *m_rhoDaggerParticles[i];
1564 
1565  writeParticlesToHDF(a_handle, conductivityParticles[a_lvl], identifierSigma);
1566  writeParticlesToHDF(a_handle, rhoDaggerParticles[a_lvl], identifierRho);
1567  }
1568  }
1569 
1570  // Write data required for the semi-implicit regrid.
1571  if (this->m_physics->getNumCdrSpecies() > 0) {
1572  write(a_handle, *m_semiImplicitRhoCDR[a_lvl], "ItoKMCGodunovStepper::semiImplicitRhoCDR");
1573  write(a_handle, *m_semiImplicitConductivityCDR[a_lvl], "ItoKMCGodunovStepper::semiImplicitConductivityCDR");
1574  }
1575 }
1576 #endif
1577 
1578 #ifdef CH_USE_HDF5
1579 template <typename I, typename C, typename R, typename F>
1580 void
1581 ItoKMCGodunovStepper<I, C, R, F>::readCheckpointData(HDF5Handle& a_handle, const int a_lvl) noexcept
1582 {
1583  CH_TIME("ItoKMCGodunovStepper::readCheckpointData");
1584  if (this->m_verbosity > 5) {
1585  pout() << this->m_name + "::readCheckpointData" << endl;
1586  }
1587 
1589 
1590  // Write the point-particles.
1591  if (m_readCheckpointParticles) {
1592  for (int i = 0; i < (this->m_physics)->getNumItoSpecies(); i++) {
1593  const std::string identifierSigma = "ItoKMCGodunovStepper::conductivityParticles_" + std::to_string(i);
1594  const std::string identifierRho = "ItoKMCGodunovStepper::spaceChargeParticles_" + std::to_string(i);
1595 
1596  ParticleContainer<PointParticle>& conductivityParticles = *m_conductivityParticles[i];
1597  ParticleContainer<PointParticle>& rhoDaggerParticles = *m_rhoDaggerParticles[i];
1598 
1599  readParticlesFromHDF(a_handle, conductivityParticles[a_lvl], identifierSigma);
1600  readParticlesFromHDF(a_handle, rhoDaggerParticles[a_lvl], identifierRho);
1601  }
1602  }
1603 
1604  // Read in data that is required for the semi-implicit regrid.
1605  if (this->m_physics->getNumCdrSpecies() > 0) {
1606  const Interval interv(0, 0);
1607 
1608  read<EBCellFAB>(a_handle,
1609  *m_semiImplicitRhoCDR[a_lvl],
1610  "ItoKMCGodunovStepper::semiImplicitRhoCDR",
1611  this->m_amr->getGrids(this->m_fluidRealm)[a_lvl],
1612  interv,
1613  false);
1614 
1615  read<EBCellFAB>(a_handle,
1616  *m_semiImplicitConductivityCDR[a_lvl],
1617  "ItoKMCGodunovStepper::semiImplicitConductivityCDR",
1618  this->m_amr->getGrids(this->m_fluidRealm)[a_lvl],
1619  interv,
1620  false);
1621  }
1622 }
1623 #endif
1624 
1625 template <typename I, typename C, typename R, typename F>
1626 void
1628 {
1629  CH_TIME("ItoKMCGodunovStepper::postPlot");
1630  if (this->m_verbosity > 5) {
1631  pout() << this->m_name + "::postPlot" << endl;
1632  }
1633 
1634  this->m_physicsPlotVariables.clear();
1635 
1636  this->plotParticles();
1637 }
1638 
1639 template <typename I, typename C, typename R, typename F>
1640 void
1642 {
1643  CH_TIME("ItoKMCGodunovStepper::plotParticles");
1644  if (this->m_verbosity > 2) {
1645  pout() << this->m_name + "::plotParticles" << endl;
1646  }
1647 
1648  bool plotParticles = false;
1649 
1650  ParmParse pp(this->m_name.c_str());
1651 
1652  pp.query("plot_particles", plotParticles);
1653 
1654  if (plotParticles) {
1655 
1656  for (auto solverIt = (this->m_ito)->iterator(); solverIt.ok(); ++solverIt) {
1657  const RefCountedPtr<ItoSolver>& solver = solverIt();
1658  const ParticleContainer<ItoParticle>& particles = solver->getParticles(ItoSolver::WhichContainer::Bulk);
1659 
1660  // Create the output folder
1661  std::string cmd = "mkdir -p particles/" + solver->getName();
1662  int success = 0;
1663  if (procID() == 0) {
1664  success = system(cmd.c_str());
1665  }
1666 
1667  if (success != 0) {
1668  MayDay::Error("ItoKMCGodunovStepper::plotParticles - could not create 'particles' directory");
1669  }
1670 
1671  // Set plot file name
1672  const std::string prefix = "./particles/" + solver->getName() + "/" + solver->getName();
1673  char fileChar[1000];
1674  sprintf(fileChar, "%s.step%07d.%dd.h5part", prefix.c_str(), this->m_timeStep, SpaceDim);
1675 
1676  // Plot the particles
1677  DischargeIO::writeH5Part(std::string(fileChar),
1678  (const ParticleContainer<GenericParticle<5, 3>>&)particles,
1681  this->m_amr->getProbLo(),
1682  this->m_time);
1683  }
1684  }
1685 }
1686 
1687 #include <CD_NamespaceFooter.H>
1688 
1689 #endif
Average
Various averaging methods.
Definition: CD_Average.H:24
Agglomeration of useful data operations.
Silly, but useful functions that override standard Chombo HDF5 IO.
EBRepresentation
Enum for putting some logic into how we think about EBs. This is just a simply supporting class for v...
Definition: CD_EBRepresentation.H:22
Declaration of a class which uses a semi-implicit Godunov method for Ito plasma equations.
SpeciesSubset
Enum for differentiating between types of particles.
Definition: CD_ItoKMCStepper.H:40
Agglomeration of basic MPI reductions.
Declaration of a photon class for particle methods.
Implementation of CD_Timer.H.
Declaration of various useful units.
static void scale(MFAMRCellData &a_lhs, const Real &a_scale) noexcept
Scale data by factor.
Definition: CD_DataOps.cpp:2384
static void floor(EBAMRCellData &a_lhs, const Real a_value)
Floor values in data holder. This sets all values below a_value to a_value.
Definition: CD_DataOps.cpp:1380
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 filterSmooth(EBAMRCellData &a_data, const Real a_alpha, const int a_stride, const bool a_zeroEB) noexcept
Apply a convolved filter phi = alpha * phi_i + 0.5*(1-alpha) * [phi_(i+s) + phi_(i-s)] in each direct...
Definition: CD_DataOps.cpp:660
static void multiply(EBAMRCellData &a_lhs, const EBAMRCellData &a_rhs)
Multiply data holder by another data holder.
Definition: CD_DataOps.cpp:2142
static void incr(MFAMRCellData &a_lhs, const MFAMRCellData &a_rhs, const Real a_scale) noexcept
Function which increments data in the form a_lhs = a_lhs + a_rhs*a_scale for all components.
Definition: CD_DataOps.cpp:787
static void averageCellToFace(EBAMRFluxData &a_faceData, const EBAMRCellData &a_cellData, const Vector< ProblemDomain > &a_domains)
Average all components of the cell-centered data to faces.
Definition: CD_DataOps.cpp:153
static void copy(MFAMRCellData &a_dst, const MFAMRCellData &a_src)
Copy data from one data holder to another.
Definition: CD_DataOps.cpp:1118
RealVect & position()
Get the particle position.
Definition: CD_GenericParticleImplem.H:47
A particle class for use with ItoSolvers, i.e. drifting Brownian walkers.
Definition: CD_ItoParticle.H:40
Real & diffusion()
Get particle diffusion coefficient.
Definition: CD_ItoParticleImplem.H:95
Real & mobility()
Get mobility coefficient.
Definition: CD_ItoParticleImplem.H:83
RealVect & oldPosition()
Get the old particle position.
Definition: CD_ItoParticleImplem.H:119
RealVect & tmpVect()
Return scratch RealVect storage.
Definition: CD_ItoParticleImplem.H:173
static std::vector< std::string > s_vectVariables
Naming convention for vector fields.
Definition: CD_ItoParticle.H:50
Real & weight()
Get particle weight.
Definition: CD_ItoParticleImplem.H:71
static std::vector< std::string > s_realVariables
Naming convention for scalar fields.
Definition: CD_ItoParticle.H:45
RealVect & velocity()
Get the particle velocity.
Definition: CD_ItoParticleImplem.H:131
Real & tmpReal()
Return scratch scalar storage.
Definition: CD_ItoParticleImplem.H:161
Templated class for holding particles on an AMR hierarchy with particle remapping.
Definition: CD_ParticleContainer.H:50
void clearParticles()
Clear all particles.
Definition: CD_ParticleContainerImplem.H:1670
AMRParticles< P > & getParticles()
Get all particles on all levels.
Definition: CD_ParticleContainerImplem.H:270
Particle class for usage with Monte Carlo radiative transfer.
Definition: CD_Photon.H:29
Real & weight()
Get photon weight.
Definition: CD_PhotonImplem.H:40
Implementation of ItoKMCStepper that uses a semi-implicit split-step formalism for advancing the Ito-...
Definition: CD_ItoKMCGodunovStepper.H:29
virtual void setupSemiImplicitPoisson(const Real a_dt) noexcept
Set up the semi-implicit Poisson solver.
Definition: CD_ItoKMCGodunovStepperImplem.H:1113
virtual void regrid(const int a_lmin, const int a_oldFinestLevel, const int a_newFinestLevel) noexcept override
Regrid methods – puts all data on the new mesh.
Definition: CD_ItoKMCGodunovStepperImplem.H:470
virtual void computeDiffusionTermCDR(EBAMRCellData &m_semiImplicitRhoCDR, const Real a_dt) noexcept
Compute the diffusion term for the CDR equations as well as the resulting CDR-contributions to the sp...
Definition: CD_ItoKMCGodunovStepperImplem.H:1388
virtual void allocate() noexcept override
Allocate storage required for advancing the equations.
Definition: CD_ItoKMCGodunovStepperImplem.H:59
bool m_readCheckpointParticles
If true, then the HDF5 checkpoint file contained particles that we can read.
Definition: CD_ItoKMCGodunovStepper.H:152
virtual Real advance(const Real a_dt) override
Advance the Ito-Poisson-KMC system over a_dt.
Definition: CD_ItoKMCGodunovStepperImplem.H:198
virtual void allocateInternals() noexcept override
Allocate "internal" storage.
Definition: CD_ItoKMCGodunovStepperImplem.H:93
virtual void copyConductivityParticles(Vector< RefCountedPtr< ParticleContainer< PointParticle >>> &a_conductivityParticles) noexcept
Copy particles from the ItoSolver into PointParticles whose weight are ItoParticle::m_weight * ItoPar...
Definition: CD_ItoKMCGodunovStepperImplem.H:1188
virtual void stepEulerMaruyamaCDR(const Real a_dt) noexcept
Step the CDR equations according to the regular Euler-Maruyama scheme.
Definition: CD_ItoKMCGodunovStepperImplem.H:1474
virtual void depositPointParticles(const Vector< RefCountedPtr< ParticleContainer< PointParticle >>> &a_particles, const SpeciesSubset a_subset) noexcept
Deposit the input point particles on the mesh.
Definition: CD_ItoKMCGodunovStepperImplem.H:752
virtual void parseAlgorithm() noexcept
Parse advancement algorithm.
Definition: CD_ItoKMCGodunovStepperImplem.H:159
virtual void postPlot() noexcept override
Perform post-plot operations.
Definition: CD_ItoKMCGodunovStepperImplem.H:1627
virtual void parseRuntimeOptions() noexcept override
Parse run-time options.
Definition: CD_ItoKMCGodunovStepperImplem.H:144
virtual void remapPointParticles(Vector< RefCountedPtr< ParticleContainer< PointParticle >>> &a_particles, const SpeciesSubset a_subset) noexcept
Remap the input point particles.
Definition: CD_ItoKMCGodunovStepperImplem.H:646
bool m_canRegridOnRestart
If true, then the class supports regrid-on-restart.
Definition: CD_ItoKMCGodunovStepper.H:158
virtual void computeFaceConductivity() noexcept
Compute the cell-centered conductivity.
Definition: CD_ItoKMCGodunovStepperImplem.H:1046
virtual void clearPointParticles(const Vector< RefCountedPtr< ParticleContainer< PointParticle >>> &a_particles, const SpeciesSubset a_subset) noexcept
Clear the input particle data holders.
Definition: CD_ItoKMCGodunovStepperImplem.H:854
virtual void computeConductivities(const Vector< RefCountedPtr< ParticleContainer< PointParticle >>> &a_particles) noexcept
Compute all conductivities (cell, face, and EB) from the input point particles.
Definition: CD_ItoKMCGodunovStepperImplem.H:960
virtual ~ItoKMCGodunovStepper()
Destructor. Does nothing.
Definition: CD_ItoKMCGodunovStepperImplem.H:49
bool m_extendConductivityEB
For achieving a slightly smoother gradient in the conductivity near the EB.
Definition: CD_ItoKMCGodunovStepper.H:163
virtual void setOldPositions() noexcept
Set the starting positions for the ItoSolver particles.
Definition: CD_ItoKMCGodunovStepperImplem.H:610
bool m_smoothConductivity
Smooth the conductivity or not.
Definition: CD_ItoKMCGodunovStepper.H:168
bool m_writeCheckpointParticles
If true, then the particles are checkpointed so we can regrid on checkpoint-restart.
Definition: CD_ItoKMCGodunovStepper.H:147
virtual void removeCoveredPointParticles(Vector< RefCountedPtr< ParticleContainer< PointParticle >>> &a_particles, const EBRepresentation a_representation, const Real a_tolerance) const noexcept
Remove covered particles.
Definition: CD_ItoKMCGodunovStepperImplem.H:1148
virtual void computeSemiImplicitRho() noexcept
Set up the space charge density for the regrid operation.
Definition: CD_ItoKMCGodunovStepperImplem.H:1076
virtual void computeCellConductivity(EBAMRCellData &a_conductivityCell, const Vector< RefCountedPtr< ParticleContainer< PointParticle >>> &a_particles) noexcept
Compute the cell-centered conductivity.
Definition: CD_ItoKMCGodunovStepperImplem.H:974
virtual void advanceEulerMaruyama(const Real a_dt) noexcept
Advance the particles using the Euler-Maruyama scheme.
Definition: CD_ItoKMCGodunovStepperImplem.H:1242
virtual void preRegrid(const int a_lmin, const int a_oldFinestLevel) noexcept override
Perform pre-regrid operations.
Definition: CD_ItoKMCGodunovStepperImplem.H:431
virtual void plotParticles() const noexcept
Utility function for plotting the ItoSolver particles. These are written in a particles folder.
Definition: CD_ItoKMCGodunovStepperImplem.H:1641
ItoKMCGodunovStepper()=delete
Disallowed default constructor. Use the full constructor.
virtual void diffuseParticlesEulerMaruyama(Vector< RefCountedPtr< ParticleContainer< PointParticle >>> &a_rhoDaggerParticles, const Real a_dt) noexcept
Perform the diffusive Ito advance in the Euler-Maruyama step.
Definition: CD_ItoKMCGodunovStepperImplem.H:1328
virtual void parseCheckpointParticles() noexcept
Parse checkpoint-restart functionality.
Definition: CD_ItoKMCGodunovStepperImplem.H:184
virtual void barrier() const noexcept
Set an MPI barrier if using debug mode.
Definition: CD_ItoKMCGodunovStepperImplem.H:115
virtual void parseOptions() noexcept override
Parse options.
Definition: CD_ItoKMCGodunovStepperImplem.H:129
virtual void stepEulerMaruyamaParticles(const Real a_dt) noexcept
Step the particles according to the regular Euler-Maruyama scheme.
Definition: CD_ItoKMCGodunovStepperImplem.H:1428
Base time stepper class that advances the Ito-KMC-Poisson system of equations. If you want a differen...
Definition: CD_ItoKMCStepper.H:60
virtual void parseRuntimeOptions() noexcept override
Parse runtime configurable options.
Definition: CD_ItoKMCStepperImplem.H:106
std::string m_name
Time stepper name.
Definition: CD_ItoKMCStepper.H:367
virtual void parseOptions() noexcept
Parse options.
Definition: CD_ItoKMCStepperImplem.H:86
virtual void preRegrid(const int a_lmin, const int a_oldFinestLevel) noexcept override
Perform pre-regrid operations - storing relevant data from the old grids.
Definition: CD_ItoKMCStepperImplem.H:1547
Real m_prevDt
Previous time step.
Definition: CD_ItoKMCStepper.H:501
virtual void allocateInternals() noexcept
Allocate "internal" storage.
Definition: CD_ItoKMCStepperImplem.H:524
virtual void allocate() noexcept override
Allocate storage for solvers.
Definition: CD_ItoKMCStepperImplem.H:506
A particle class that only has a position and a weight.
Definition: CD_PointParticle.H:29
Real & weight()
Get weight.
Definition: CD_PointParticleImplem.H:38
Class which is used for run-time monitoring of events.
Definition: CD_Timer.H:31
void writeH5Part(const std::string a_filename, const ParticleContainer< GenericParticle< M, N >> &a_particles, const std::vector< std::string > a_realVars=std::vector< std::string >(), const std::vector< std::string > a_vectVars=std::vector< std::string >(), const RealVect a_shift=RealVect::Zero, const Real a_time=0.0) noexcept
A shameless copy of Chombo's writeEBHDF5 but including the lower-left corner of the physical domain a...
Definition: CD_DischargeIOImplem.H:26
Real average(const Real &a_val) noexcept
Compute the average (across MPI ranks) of the input value.
Definition: CD_ParallelOpsImplem.H:500
void barrier() noexcept
MPI barrier.
Definition: CD_ParallelOpsImplem.H:25
constexpr Real eps0
Permittivity of free space.
Definition: CD_Units.H:29
constexpr Real R
Universal gas constant.
Definition: CD_Units.H:64
constexpr Real Qe
Elementary charge.
Definition: CD_Units.H:34