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