chombo-discharge
Loading...
Searching...
No Matches
CD_KMCDualStateReactionImplem.H
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021-2026 SINTEF Energy Research
3 *
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
13#ifndef CD_KMCDUALSTATEREACTIONIMPLEM_H
14#define CD_KMCDUALSTATEREACTIONIMPLEM_H
15
16// Std includes
17#include <limits>
18
19// Chombo includes
20#include <CH_Timer.H>
21
22// Our includes
24#include <CD_NamespaceHeader.H>
25
26template <typename State, typename T>
30{
31 CH_TIME("KMCDualStateReaction::KMCDualStateReaction");
32
33 m_lhsReactives = a_lhsReactives;
34 m_rhsReactives = a_rhsReactives;
35 m_rhsNonReactives = a_rhsNonReactives;
36
37 CH_assert(a_lhsReactives.size() > 0);
38
39 this->computeStateChanges();
40}
41
42template <typename State, typename T>
44{
45 CH_TIME("KMCDualStateReaction::~KMCDualStateReaction");
46}
47
48template <typename State, typename T>
49inline void
51{
52 CH_TIME("KMCDualStateReaction::computeStateChanges");
53
54 // Consumed species.
55 for (const auto& r : m_lhsReactives) {
56 if (m_reactiveStateChange.find(r) == m_reactiveStateChange.end()) {
57 m_reactiveStateChange.emplace(r, -1);
58 }
59 else {
60 m_reactiveStateChange[r]--;
61 }
62 }
63
64 // Produced species.
65 for (const auto& p : m_rhsReactives) {
66 if (m_reactiveStateChange.find(p) == m_reactiveStateChange.end()) {
67 m_reactiveStateChange.emplace(p, +1);
68 }
69 else {
70 m_reactiveStateChange[p]++;
71 }
72 }
73
74 // Produced photons.
75 for (const auto& p : m_rhsNonReactives) {
76 if (m_nonReactiveStateChange.find(p) == m_nonReactiveStateChange.end()) {
77 m_nonReactiveStateChange.emplace(p, +1);
78 }
79 else {
80 m_nonReactiveStateChange[p]++;
81 }
82 }
83
84 // Compute the propensity factor that we need when there are bi- or tri-particle reactions involving the same species. We need to do this
85 // because for biparticle reactions of N particles of the same type, there are 0.5 * N * (N-1) unique pairs of particles. Or in general when
86 // we have a k-order reaction we have 'N choose k' = N!/(k! * (N-k)!) combinations. In the propensity function we compute the propensity as
87 //
88 // a = rate * factor * N * (N-1) * (N-2) ...
89 //
90 // For this to make sense we have
91 //
92 // a = rate * N * (N-1) * (N-2) ... (N-k+1) * (N-k)!/(k! * (N-k)!)
93 // = rate * N * (N-1) * (N-2) ... * 1/k!
94 //
95 // so the factor is just 1/k! (for each species).
96
97 m_propensityFactor = 1.0;
98
100 for (const auto& r : m_lhsReactives) {
101 if (reactantNumbers.find(r) == reactantNumbers.end()) {
102 reactantNumbers.emplace(r, 1);
103 }
104 else {
106 }
107 }
108
109 // Factorial function.
110 auto factorial = [](const T& N) -> T {
111 T fac = (T)1;
112 for (T i = 2; i <= N; i++) {
113 fac *= i;
114 }
115
116 return fac;
117 };
118
119 for (const auto& rn : reactantNumbers) {
120 m_propensityFactor *= 1.0 / factorial(rn.second);
121 }
122}
123
124template <typename State, typename T>
125inline Real&
130
131template <typename State, typename T>
132inline T
134{
135 CH_TIME("KMCDualStateReaction::population");
136
137 const auto& reactiveState = a_state.getReactiveState();
138
140
142}
143
144template <typename State, typename T>
145inline Real
147{
148 CH_TIME("KMCDualStateReaction::propensity");
149#ifndef NDEBUG
150 this->sanityCheck(a_state);
151#endif
152
153 Real A = m_rate * m_propensityFactor;
154
155 auto reactiveState = a_state.getReactiveState();
156
157 for (const auto& r : m_lhsReactives) {
158 A *= reactiveState[r];
159
160 reactiveState[r]--;
161 }
162
163 return A;
164}
165
166template <typename State, typename T>
167inline T
169{
170 CH_TIME("KMCDualStateReaction::computeCriticalNumberOfReactions");
171
172#ifndef NDEBUG
173 this->sanityCheck(a_state);
174#endif
175
176 T Lj = std::numeric_limits<T>::max();
177
178 const auto& reactiveState = a_state.getReactiveState();
179
180 for (const auto& s : m_reactiveStateChange) {
181
182 const size_t rI = s.first;
183 const T nuIJ = s.second;
184
185 if (nuIJ < 0) {
186 Lj = std::min(Lj, reactiveState[rI] / std::abs(nuIJ));
187 }
188 }
189
190 return Lj;
191}
192
193template <typename State, typename T>
196{
197 return m_lhsReactives;
198}
199
200template <typename State, typename T>
206
207template <typename State, typename T>
213
214template <typename State, typename T>
215inline T
217{
218 CH_TIME("KMCDualStateReaction::getStateChange");
219
220 T nuIJ = 0;
221
222 if (m_reactiveStateChange.find(a_particleReactant) != m_reactiveStateChange.end()) {
223 nuIJ = m_reactiveStateChange.at(a_particleReactant);
224 }
225
226 return nuIJ;
227}
228
229template <typename State, typename T>
230inline void
232{
233 CH_TIME("KMCDualStateReaction::advanceState");
234
235#ifndef NDEBUG
236 this->sanityCheck(a_state);
237#endif
238 CH_assert(a_state.isValidState());
239
240 auto& reactiveState = a_state.getReactiveState();
241 auto& photonState = a_state.getNonReactiveState();
242
243 for (const auto& s : m_reactiveStateChange) {
244 reactiveState[s.first] += a_numReactions * s.second;
245 }
246
247 for (const auto& s : m_nonReactiveStateChange) {
248 photonState[s.first] += a_numReactions * s.second;
249 }
250
251 CH_assert(a_state.isValidState());
252}
253
254template <typename State, typename T>
255inline void
257{
258 CH_TIME("KMCDualStateReaction::sanityCheck");
259
260 const auto& reactiveState = a_state.getReactiveState();
261 const auto& photonState = a_state.getNonReactiveState();
262
263 for (const auto& idx : m_lhsReactives) {
264 CH_assert(reactiveState.size() > idx);
265 }
266
267 for (const auto& idx : m_rhsReactives) {
268 CH_assert(reactiveState.size() > idx);
269 }
270
271 for (const auto& idx : m_rhsNonReactives) {
272 CH_assert(photonState.size() > idx);
273 }
274}
275
276#include <CD_NamespaceFooter.H>
277
278#endif
Declaration of a simple plasma reaction type for Kinetic Monte Carlo.
T getStateChange(const size_t a_reactant) const noexcept
Get the state change due to a change in the input reactant.
Definition CD_KMCDualStateReactionImplem.H:216
void sanityCheck(const State &a_state) const noexcept
Debugging function which ensures that the class data holders do not reach out of the incoming state.
Definition CD_KMCDualStateReactionImplem.H:256
void computeStateChanges() noexcept
Compute state change vectors from the reactant/product lists.
Definition CD_KMCDualStateReactionImplem.H:50
std::list< size_t > getNonReactiveProducts() const noexcept
Get the non-reactive products from the reaction.
Definition CD_KMCDualStateReactionImplem.H:209
KMCDualStateReaction()=default
Default constructor.
virtual ~KMCDualStateReaction()
Destructor.
Definition CD_KMCDualStateReactionImplem.H:43
std::list< size_t > getReactiveProducts() const noexcept
Get the products from the reaction.
Definition CD_KMCDualStateReactionImplem.H:202
Real propensity(const State &a_state) const noexcept
Compute the propensity function for this reaction type.
Definition CD_KMCDualStateReactionImplem.H:146
T computeCriticalNumberOfReactions(const State &a_state) const noexcept
Compute the number of times the reaction can fire before exhausting one of the reactants.
Definition CD_KMCDualStateReactionImplem.H:168
std::list< size_t > getReactants() const noexcept
Get the reactants in the reaction.
Definition CD_KMCDualStateReactionImplem.H:195
Real & rate() const noexcept
Get modifiable reaction rate.
Definition CD_KMCDualStateReactionImplem.H:126
void advanceState(State &a_state, const T &a_numReactions) const noexcept
Advance the incoming state with the number of reactions.
Definition CD_KMCDualStateReactionImplem.H:231
static T population(const size_t &a_reactant, const State &a_state) noexcept
Get the population of the reactant in the input state.
Definition CD_KMCDualStateReactionImplem.H:133
Base class for a tracer particle solver. This solver can advance particles in a pre-defined velocity ...
Definition CD_TracerParticleSolver.H:38
TracerParticleSolver()
Default constructor.
Definition CD_TracerParticleSolverImplem.H:26