13#ifndef CD_ITOKMCBACKGROUNDEVALUATORIMPLEM_H
14#define CD_ITOKMCBACKGROUNDEVALUATORIMPLEM_H
18#include <CD_NamespaceHeader.H>
20using namespace Physics::ItoKMC;
22template <
typename I,
typename C,
typename R,
typename F>
26 CH_TIME(
"ItoKMCBackgroundEvaluator::ItoKMCBackgroundEvaluator");
29 m_maxFieldExitCrit = std::numeric_limits<Real>::max();
30 m_relFieldExitCrit = std::numeric_limits<Real>::max();
31 m_maxFieldChange = -1.0;
32 m_relFieldChange = -1.0;
33 m_electrodeCharge = 0.0;
35 m_opticalSolver =
"2PN2";
36 m_maxInitialTimeStep = 0.0;
39 this->m_name =
"ItoKMCBackgroundEvaluator";
43 ParmParse pp(this->m_name.c_str());
44 pp.query(
"max_field_exit_crit", m_maxFieldExitCrit);
45 pp.query(
"rel_field_exit_crit", m_relFieldExitCrit);
46 pp.query(
"optical_solver", m_opticalSolver);
47 pp.query(
"max_initial_time_step", m_maxInitialTimeStep);
50template <
typename I,
typename C,
typename R,
typename F>
54 CH_TIME(
"ItoKMCBackgroundEvaluator::postInitialize");
55 if (this->m_verbosity > 5) {
56 pout() <<
"ItoKMCBackgroundEvaluator::postInitialize" << endl;
61 this->computeBackgroundField();
64template <
typename I,
typename C,
typename R,
typename F>
68 CH_TIME(
"ItoKMCBackgroundEvaluator::postRegrid");
69 if (this->m_verbosity > 5) {
70 pout() <<
"ItoKMCBackgroundEvaluator::postRegrid" << endl;
75 this->computeBackgroundField();
78template <
typename I,
typename C,
typename R,
typename F>
82 CH_TIME(
"ItoKMCBackgroundEvaluator::postCheckpointSetup");
83 if (this->m_verbosity > 5) {
84 pout() <<
"ItoKMCBackgroundEvaluator::postCheckpointSetup" << endl;
89 this->computeBackgroundField();
92template <
typename I,
typename C,
typename R,
typename F>
96 CH_TIME(
"ItoKMCBackgroundEvaluator::advance");
97 if (this->m_verbosity > 5) {
98 pout() <<
"ItoKMCBackgroundEvaluator::advance" << endl;
103 const std::pair<Real, Real> fieldChange = this->evaluateSpaceChargeEffects();
104 const Real electrodeQ = this->integrateElectrodeSurfaceCharge();
105 const Real ohmicQ = this->integrateOhmicCharge();
106 const std::pair<Real, Real> opticalEmissions = this->integrateOpticalExcitations();
108 m_relFieldChange = fieldChange.first;
109 m_maxFieldChange = fieldChange.second;
110 m_electrodeCharge = electrodeQ;
111 m_ohmicCharge = ohmicQ;
112 m_sumOpticalPhi = opticalEmissions.first;
113 m_sumOpticalSrc = opticalEmissions.second;
115 bool abortCondition =
false;
116 if ((m_maxFieldChange > m_maxFieldExitCrit) && (m_maxFieldExitCrit > 0.0)) {
117 pout() <<
"ItoKMCBackgroundEvaluator -- stopping because the max field (in any cell) "
118 <<
"changed by more than specified threshold (max_field_exit_crit)" << endl;
119 abortCondition =
true;
121 if ((m_relFieldChange > m_relFieldExitCrit) && (m_relFieldExitCrit > 0.0)) {
122 pout() <<
"ItoKMCBackgroundEvaluator -- stopping because the relative field change in a cell "
123 <<
"is larger than specified threshold (rel_field_exit_crit)" << endl;
124 abortCondition =
true;
126 if (abortCondition) {
127 this->m_keepGoing =
false;
133template <
typename I,
typename C,
typename R,
typename F>
137 CH_TIME(
"ItoKMCBackgroundEvaluator::computeDt");
138 if (this->m_verbosity > 5) {
139 pout() <<
"ItoKMCBackgroundEvaluator::computeDt" << endl;
144 if (this->m_timeStep == 0 && m_maxInitialTimeStep > 0.0 && newDt > m_maxInitialTimeStep)
145 newDt = m_maxInitialTimeStep;
150template <
typename I,
typename C,
typename R,
typename F>
154 CH_TIME(
"ItoKMCBackgroundEvaluator::printStepReport");
155 if (this->m_verbosity > 5) {
156 pout() <<
"ItoKMCBackgroundEvaluator::printStepReport" << endl;
159 std::ios::fmtflags oldFlags = pout().flags();
164 const std::string whitespace =
" ";
165 pout().precision(12);
166 pout() << whitespace +
"Delta E(max) = " << 100.0 * m_maxFieldChange <<
" (%)" << endl;
167 pout() << whitespace +
"Delta E(rel) = " << 100.0 * m_relFieldChange <<
" (%)" << endl;
168 pout() << whitespace +
"Q (electrode) = " << std::scientific << m_electrodeCharge <<
" (C)" << endl;
169 pout() << whitespace +
"Q (ohmic) = " << std::scientific << m_ohmicCharge <<
" (C)" << endl;
170 pout() << whitespace +
"Sum (phi_optical) = " << std::scientific << m_sumOpticalPhi << endl;
171 pout() << whitespace +
"Sum (src_optical) = " << std::scientific << m_sumOpticalSrc <<
" (1/s)" << endl;
173 pout().flags(oldFlags);
176template <
typename I,
typename C,
typename R,
typename F>
180 CH_TIME(
"ItoKMCBackgroundEvaluator::computeBackgroundField");
181 if (this->m_verbosity > 5) {
182 pout() <<
"ItoKMCBackgroundEvaluator::computeBackgroundField" << endl;
191 (this->m_amr)->allocate(phi, this->m_fluidRealm, 1);
192 (this->m_amr)->allocate(rho, this->m_fluidRealm, 1);
193 (this->m_amr)->allocate(sigma, this->m_fluidRealm, this->m_plasmaPhase, 1);
194 (this->m_amr)->allocate(m_backgroundField, this->m_fluidRealm, SpaceDim);
198 (this->m_amr)->copyData(phi, (this->m_fieldSolver)->getPotential());
205 (this->m_fieldSolver)->setPermittivities();
207 const MFAMRCellData& permCell = (this->m_fieldSolver)->getPermittivityCell();
208 const MFAMRFluxData& permFace = (this->m_fieldSolver)->getPermittivityFace();
209 const MFAMRIVData& permEB = (this->m_fieldSolver)->getPermittivityEB();
211 (this->m_fieldSolver)->setSolverPermittivities(permCell, permFace, permEB);
214 (this->m_fieldSolver)->solve(phi, rho, sigma,
false);
215 (this->m_fieldSolver)->computeElectricField(m_backgroundField, phi);
218template <
typename I,
typename C,
typename R,
typename F>
222 CH_TIME(
"ItoKMCBackgroundEvaluator::evaluateSpaceChargeEffects");
223 if (this->m_verbosity > 5) {
224 pout() <<
"ItoKMCBackgroundEvaluator::evaluateSpaceChargeEffects" << endl;
227 EBAMRCellData poissonNorm;
228 EBAMRCellData laplaceNorm;
229 EBAMRCellData poissonField;
230 EBAMRCellData laplaceField;
231 EBAMRCellData deltaE;
233 (this->m_amr)->allocate(poissonNorm, this->m_fluidRealm, this->m_plasmaPhase, 1);
234 (this->m_amr)->allocate(laplaceNorm, this->m_fluidRealm, this->m_plasmaPhase, 1);
235 (this->m_amr)->allocate(poissonField, this->m_fluidRealm, this->m_plasmaPhase, SpaceDim);
236 (this->m_amr)->allocate(laplaceField, this->m_fluidRealm, this->m_plasmaPhase, SpaceDim);
237 (this->m_amr)->allocate(deltaE, this->m_fluidRealm, this->m_plasmaPhase, 1);
240 const MFAMRCellData electricField = (this->m_fieldSolver)->getElectricField();
242 DataOps::copy(poissonField, (this->m_amr)->alias(this->m_plasmaPhase, electricField));
243 DataOps::copy(laplaceField, (this->m_amr)->alias(this->m_plasmaPhase, m_backgroundField));
245 (this->m_amr)->interpToCentroids(poissonField, this->m_fluidRealm, this->m_plasmaPhase);
246 (this->m_amr)->interpToCentroids(laplaceField, this->m_fluidRealm, this->m_plasmaPhase);
251 (this->m_amr)->getNotCoveredCells(this->m_fluidRealm, this->m_plasmaPhase),
252 (this->m_amr)->getMultiCutVofIterator(this->m_fluidRealm, this->m_plasmaPhase));
255 (this->m_amr)->getNotCoveredCells(this->m_fluidRealm, this->m_plasmaPhase),
256 (this->m_amr)->getMultiCutVofIterator(this->m_fluidRealm, this->m_plasmaPhase));
263 (this->m_amr)->getMultiCutVofIterator(this->m_fluidRealm, this->m_plasmaPhase));
265 (this->m_amr)->arithmeticAverage(deltaE, this->m_fluidRealm, this->m_plasmaPhase);
266 (this->m_amr)->interpGhost(deltaE, this->m_fluidRealm, this->m_plasmaPhase);
272 Real relChange = -1.0;
273 Real maxChange = -1.0;
275 Real maxSpaceChargeField = 0.0;
276 Real minSpaceChargeField = 0.0;
277 Real maxBackgroundField = 0.0;
278 Real minBackgroundField = 0.0;
284 (this->m_amr)->getMultiCutVofIterator(this->m_fluidRealm, this->m_plasmaPhase));
289 (this->m_amr)->getMultiCutVofIterator(this->m_fluidRealm, this->m_plasmaPhase));
291 for (
int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
292 const DisjointBoxLayout& dbl = (this->m_amr)->getGrids(this->m_fluidRealm)[lvl];
293 const DataIterator& dit = dbl.dataIterator();
294 const EBISLayout& ebisl = (this->m_amr)->getEBISLayout(this->m_fluidRealm, this->m_plasmaPhase)[lvl];
296 const int nbox = dit.size();
298#pragma omp parallel for schedule(runtime) reduction(max : relChange)
299 for (
int mybox = 0; mybox < nbox; mybox++) {
300 const DataIndex& din = dit[mybox];
301 const Box box = dbl[din];
302 const EBISBox& ebisbox = ebisl[din];
303 const BaseFab<bool>& validCells = (*(this->m_amr)->getValidCells(this->m_fluidRealm)[lvl])[din];
305 const EBCellFAB& data = (*deltaE[lvl])[din];
306 const FArrayBox& dataReg = data.getFArrayBox();
308 auto regularKernel = [&](
const IntVect& iv) ->
void {
309 if (validCells(iv) && ebisbox.isRegular(iv)) {
310 relChange = std::max(relChange, std::abs(dataReg(iv, 0)));
314 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
315 if (validCells(vof.gridIndex()) && ebisbox.isIrregular(vof.gridIndex())) {
316 relChange = std::max(relChange, std::abs(data(vof, 0)));
320 VoFIterator& vofit = (*(this->m_amr)->getVofIterator(this->m_fluidRealm, this->m_plasmaPhase)[lvl])[din];
323 BoxLoops::loop<D_DECL(1, 1, 1)>(box, regularKernel);
329 maxChange = maxSpaceChargeField / maxBackgroundField - 1.0;
331 return std::make_pair(relChange, maxChange);
334template <
typename I,
typename C,
typename R,
typename F>
338 CH_TIME(
"ItoKMCBackgroundEvaluator::integrateElectrodeSurfaceCharge");
339 if (this->m_verbosity > 5) {
340 pout() <<
"ItoKMCBackgroundEvaluator::integrateElectrodeSurfaceCharge" << endl;
345 const Real eps =
Units::eps0 * this->m_computationalGeometry->getGasPermittivity();
347 const MFAMRCellData& electricFieldCell = (this->m_fieldSolver)->getElectricField();
348 const MFAMRCellData& permittivityCell = (this->m_fieldSolver)->getPermittivityCell();
349 const EBAMRCellData permittivity = (this->m_amr)->alias(this->m_plasmaPhase, permittivityCell);
352 EBAMRCellData electricField;
353 (this->m_amr)->allocate(electricField, this->m_fluidRealm, this->m_plasmaPhase, SpaceDim);
354 DataOps::copy(electricField, (this->m_amr)->alias(this->m_plasmaPhase, electricFieldCell));
355 (this->m_amr)->interpToCentroids(electricField, this->m_fluidRealm, this->m_plasmaPhase);
357 for (
int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
358 const DisjointBoxLayout& dbl = (this->m_amr)->getGrids(this->m_fluidRealm)[lvl];
359 const EBISLayout& ebisl = (this->m_amr)->getEBISLayout(this->m_fluidRealm, this->m_plasmaPhase)[lvl];
360 const DataIterator& dit = dbl.dataIterator();
361 const Real dx = (this->m_amr)->getDx()[lvl];
362 const Real dA = std::pow(dx, SpaceDim - 1);
364 const int numBoxes = dit.size();
366#pragma omp parallel for schedule(runtime) reduction(+ : Enorm)
367 for (
int mybox = 0; mybox < numBoxes; mybox++) {
368 const DataIndex& din = dit[mybox];
369 const EBISBox& ebisbox = ebisl[din];
370 const EBCellFAB& E = (*electricField[lvl])[din];
371 const EBCellFAB& eps = (*permittivity[lvl])[din];
372 const BaseFab<bool>& validCells = (*(this->m_amr)->getValidCells(this->m_fluidRealm)[lvl])[din];
374 auto kernel = [&](
const VolIndex& vof) ->
void {
375 if (ebisbox.isIrregular(vof.gridIndex()) && validCells(vof.gridIndex(), 0)) {
376 const RealVect normalVector = ebisbox.normal(vof);
377 const RealVect e = RealVect(D_DECL(E(vof, 0), E(vof, 1), E(vof, 2)));
378 const Real areaFrac = ebisbox.bndryArea(vof);
380 Enorm += eps(vof, 0) * e.dotProduct(normalVector) * areaFrac * dA;
384 VoFIterator& vofit = (*(this->m_amr)->getVofIterator(this->m_fluidRealm, this->m_plasmaPhase)[lvl])[din];
393template <
typename I,
typename C,
typename R,
typename F>
397 CH_TIME(
"ItoKMCBackgroundEvaluator::integrateOhmicCharge");
398 if (this->m_verbosity > 5) {
399 pout() <<
"ItoKMCBackgroundEvaluator::integrateOhmicCharge" << endl;
405template <
typename I,
typename C,
typename R,
typename F>
409 CH_TIME(
"ItoKMCBackgroundEvaluator::integrateOpticalExcitations");
410 if (this->m_verbosity > 5) {
411 pout() <<
"ItoKMCBackgroundEvaluator::integrateOpticalExcitations" << endl;
418 const RefCountedPtr<CdrSolver>& solver = solverIt();
420 if (solver->getName() == m_opticalSolver) {
421 for (
int lvl = 0; lvl <= (this->m_amr)->getFinestLevel(); lvl++) {
422 const DisjointBoxLayout& dbl = (this->m_amr)->getGrids(this->m_fluidRealm)[lvl];
423 const EBISLayout& ebisl = (this->m_amr)->getEBISLayout(this->m_fluidRealm, this->m_plasmaPhase)[lvl];
424 const DataIterator& dit = dbl.dataIterator();
425 const Real dx = (this->m_amr)->getDx()[lvl];
426 const Real dV = std::pow(dx, SpaceDim);
428 const int numBoxes = dit.size();
430#pragma omp parallel for schedule(runtime) reduction(+ : sumPhi, sumSrc)
431 for (
int mybox = 0; mybox < numBoxes; mybox++) {
432 const DataIndex& din = dit[mybox];
433 const Box cellBox = dbl[din];
434 const EBISBox& ebisbox = ebisl[din];
435 const BaseFab<bool>& validCells = (*(this->m_amr)->getValidCells(this->m_fluidRealm)[lvl])[din];
437 const EBCellFAB& phi = (*(solver->getPhi()[lvl]))[din];
438 const EBCellFAB& src = (*(solver->getSource()[lvl]))[din];
440 const FArrayBox& phiReg = phi.getFArrayBox();
441 const FArrayBox& srcReg = src.getFArrayBox();
443 auto regularKernel = [&](
const IntVect& iv) ->
void {
444 if (ebisbox.isRegular(iv) && validCells(iv)) {
445 sumPhi += phiReg(iv, 0) * dV;
446 sumSrc += srcReg(iv, 0) * dV;
450 auto irregularKernel = [&](
const VolIndex& vof) ->
void {
451 if (ebisbox.isIrregular(vof.gridIndex()) && validCells(vof.gridIndex(), 0)) {
452 const Real kappa = ebisbox.volFrac(vof);
457 sumPhi += kappa * phi(vof, 0) * dV;
458 sumSrc += kappa * src(vof, 0) * dV;
462 VoFIterator& vofit = (*(this->m_amr)->getVofIterator(this->m_fluidRealm, this->m_plasmaPhase)[lvl])[din];
465 BoxLoops::loop<D_DECL(1, 1, 1)>(cellBox, regularKernel);
475 return std::make_pair(sumPhi, sumSrc);
478#include <CD_NamespaceFooter.H>
Declaration of the Physics::ItoKMC::ItoKMCBackgroundEvaluator TimeStepper.
Iterator class for CdrLayout. This allows iteration through solvers (or subsets of solvers).
Definition CD_CdrIterator.H:29
virtual bool ok() const
Check if the iterator is valid.
Definition CD_CdrIteratorImplem.H:77
static void getMaxMin(Real &max, Real &min, EBAMRCellData &a_data, const int a_comp, const Vector< RefCountedPtr< LayoutData< VoFIterator > > > &a_vofIter)
Get maximum and minimum value of specified component.
Definition CD_DataOps.cpp:1711
static void vectorLength(EBAMRCellData &a_lhs, const EBAMRCellData &a_rhs, const EBAMRCellData &a_notCovered, const Vector< RefCountedPtr< LayoutData< VoFIterator > > > &a_vofIter)
Compute the vector length of a data holder. Sets a_lhs = |a_rhs| where a_rhs contains SpaceDim compon...
Definition CD_DataOps.cpp:3500
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:820
static void setValue(LevelData< MFInterfaceFAB< T > > &a_lhs, const T &a_value)
Set value in an MFInterfaceFAB data holder.
Definition CD_DataOpsImplem.H:24
static void divideFallback(EBAMRCellData &a_numerator, const EBAMRCellData &a_denominator, const Real a_fallback, const Vector< RefCountedPtr< LayoutData< VoFIterator > > > &a_vofIter)
Divide data. If the denominator is zero, set the value to a fallback option.
Definition CD_DataOps.cpp:1387
static void copy(MFAMRCellData &a_dst, const MFAMRCellData &a_src)
Copy data from one data holder to another.
Definition CD_DataOps.cpp:1201
virtual void postRegrid() noexcept override final
Post-regrid operations. Computes the background field.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:66
virtual Real integrateElectrodeSurfaceCharge() const noexcept
Compute total charge on electrode.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:336
virtual void computeBackgroundField() noexcept
Computes the background field. I.e., it allocates and fills m_backgroundField.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:178
virtual std::pair< Real, Real > evaluateSpaceChargeEffects() noexcept
Evaluate the maximum change in the background field.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:220
virtual void printStepReport() noexcept override final
Print a new step report. This is the old one plus the maximum field change.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:152
ItoKMCBackgroundEvaluator(RefCountedPtr< ItoKMCPhysics > &a_physics) noexcept
Constructor.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:23
virtual Real integrateOhmicCharge() const noexcept
Compute the total ohmic current through the electrode.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:395
virtual Real advance(const Real a_dt) override
Advance the system by a_dt, including background-field evaluation.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:94
virtual void postInitialize() noexcept override final
Post-initialization operations. Computes the background field.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:52
virtual void postCheckpointSetup() noexcept override final
Post-checkpoint operations. Computes the background field.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:80
virtual Real computeDt() override
Compute a time step for the advance method.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:135
virtual std::pair< Real, Real > integrateOpticalExcitations() const noexcept
Integrate the sum of the optical excitations.
Definition CD_ItoKMCBackgroundEvaluatorImplem.H:407
Implementation of ItoKMCStepper that uses a semi-implicit split-step formalism for advancing the Ito-...
Definition CD_ItoKMCGodunovStepper.H:31
virtual Real advance(const Real a_dt) override
Advance the Ito-Poisson-KMC system over a_dt.
Definition CD_ItoKMCGodunovStepperImplem.H:359
virtual Real computeDt() override
Compute a time step used for the advance method.
Definition CD_ItoKMCGodunovStepperImplem.H:339
ALWAYS_INLINE void loop(const Box &a_computeBox, Functor &&kernel)
Launch a C++ kernel over a regular grid with compile-time per-dimension strides.
Definition CD_BoxLoopsImplem.H:39
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:177
Real sum(const Real &a_value) noexcept
Compute the sum across all MPI ranks.
Definition CD_ParallelOpsImplem.H:354
constexpr Real eps0
Permittivity of free space.
Definition CD_Units.H:30