chombo-discharge
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 #include <limits>
16 
17 // Our includes
19 #include <CD_NamespaceHeader.H>
20 
21 template <typename State, typename T>
22 inline KMCDualStateReaction<State, T>::KMCDualStateReaction(const std::list<size_t>& a_lhsReactives,
23  const std::list<size_t>& a_rhsReactives,
24  const std::list<size_t>& a_rhsNonReactives) noexcept
25 {
26  m_lhsReactives = a_lhsReactives;
27  m_rhsReactives = a_rhsReactives;
28  m_rhsNonReactives = a_rhsNonReactives;
29 
30  CH_assert(a_lhsReactives.size() > 0);
31 
32  this->computeStateChanges();
33 }
34 
35 template <typename State, typename T>
37 {}
38 
39 template <typename State, typename T>
40 inline void
42 {
43  // Consumed species.
44  for (const auto& r : m_lhsReactives) {
45  if (m_reactiveStateChange.find(r) == m_reactiveStateChange.end()) {
46  m_reactiveStateChange.emplace(r, -1);
47  }
48  else {
49  m_reactiveStateChange[r]--;
50  }
51  }
52 
53  // Produced species.
54  for (const auto& p : m_rhsReactives) {
55  if (m_reactiveStateChange.find(p) == m_reactiveStateChange.end()) {
56  m_reactiveStateChange.emplace(p, +1);
57  }
58  else {
59  m_reactiveStateChange[p]++;
60  }
61  }
62 
63  // Produced photons.
64  for (const auto& p : m_rhsNonReactives) {
65  if (m_nonReactiveStateChange.find(p) == m_nonReactiveStateChange.end()) {
66  m_nonReactiveStateChange.emplace(p, +1);
67  }
68  else {
69  m_nonReactiveStateChange[p]++;
70  }
71  }
72 
73  // Compute the propensity factor that we need when there are bi- or tri-particle reactions involving the same species. We need to do this
74  // 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
75  // 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
76  //
77  // a = rate * factor * N * (N-1) * (N-2) ...
78  //
79  // For this to make sense we have
80  //
81  // a = rate * N * (N-1) * (N-2) ... (N-k+1) * (N-k)!/(k! * (N-k)!)
82  // = rate * N * (N-1) * (N-2) ... * 1/k!
83  //
84  // so the factor is just 1/k! (for each species).
85 
86  m_propensityFactor = 1.0;
87 
88  std::map<size_t, size_t> reactantNumbers;
89  for (const auto& r : m_lhsReactives) {
90  if (reactantNumbers.find(r) == reactantNumbers.end()) {
91  reactantNumbers.emplace(r, 1);
92  }
93  else {
94  reactantNumbers[r]++;
95  }
96  }
97 
98  // Factorial function.
99  auto factorial = [](const T& N) -> T {
100  T fac = (T)1;
101  for (T i = 2; i <= N; i++) {
102  fac *= i;
103  }
104 
105  return fac;
106  };
107 
108  for (const auto& rn : reactantNumbers) {
109  m_propensityFactor *= 1.0 / factorial(rn.second);
110  }
111 }
112 
113 template <typename State, typename T>
114 inline Real&
116 {
117  return m_rate;
118 }
119 
120 template <typename State, typename T>
121 inline T
122 KMCDualStateReaction<State, T>::population(const size_t& a_reactant, const State& a_state) const noexcept
123 {
124  const auto& reactiveState = a_state.getReactiveState();
125 
126  CH_assert(reactiveState.size() > a_reactant);
127 
128  return reactiveState[a_reactant];
129 }
130 
131 template <typename State, typename T>
132 inline Real
133 KMCDualStateReaction<State, T>::propensity(const State& a_state) const noexcept
134 {
135 #ifndef NDEBUG
136  this->sanityCheck(a_state);
137 #endif
138 
139  Real A = m_rate * m_propensityFactor;
140 
141  auto reactiveState = a_state.getReactiveState();
142 
143  for (const auto& r : m_lhsReactives) {
144  A *= reactiveState[r];
145 
146  reactiveState[r]--;
147  }
148 
149  return A;
150 }
151 
152 template <typename State, typename T>
153 inline T
155 {
156 #ifndef NDEBUG
157  this->sanityCheck(a_state);
158 #endif
159 
161 
162  const auto& reactiveState = a_state.getReactiveState();
163 
164  for (const auto& s : m_reactiveStateChange) {
165 
166  const size_t rI = s.first;
167  const T nuIJ = s.second;
168 
169  if (nuIJ < 0) {
170  Lj = std::min(Lj, reactiveState[rI] / std::abs(nuIJ));
171  }
172  }
173 
174  return Lj;
175 }
176 
177 template <typename State, typename T>
178 inline std::list<size_t>
180 {
181  return m_lhsReactives;
182 }
183 
184 template <typename State, typename T>
185 inline std::list<size_t>
187 {
188  return m_rhsReactives;
189 }
190 
191 template <typename State, typename T>
192 inline std::list<size_t>
194 {
195  return m_rhsNonReactives;
196 }
197 
198 template <typename State, typename T>
199 inline T
200 KMCDualStateReaction<State, T>::getStateChange(const size_t a_particleReactant) const noexcept
201 {
202  T nuIJ = 0;
203 
204  if (m_reactiveStateChange.find(a_particleReactant) != m_reactiveStateChange.end()) {
205  nuIJ = m_reactiveStateChange.at(a_particleReactant);
206  }
207 
208  return nuIJ;
209 }
210 
211 template <typename State, typename T>
212 inline void
213 KMCDualStateReaction<State, T>::advanceState(State& a_state, const T& a_numReactions) const noexcept
214 {
215 #ifndef NDEBUG
216  this->sanityCheck(a_state);
217 #endif
218  CH_assert(a_state.isValidState());
219 
220  auto& reactiveState = a_state.getReactiveState();
221  auto& photonState = a_state.getNonReactiveState();
222 
223  for (const auto& s : m_reactiveStateChange) {
224  reactiveState[s.first] += a_numReactions * s.second;
225  }
226 
227  for (const auto& s : m_nonReactiveStateChange) {
228  photonState[s.first] += a_numReactions * s.second;
229  }
230 
231  CH_assert(a_state.isValidState());
232 }
233 
234 template <typename State, typename T>
235 inline void
236 KMCDualStateReaction<State, T>::sanityCheck(const State& a_state) const noexcept
237 {
238  const auto& reactiveState = a_state.getReactiveState();
239  const auto& photonState = a_state.getNonReactiveState();
240 
241  for (const auto& idx : m_lhsReactives) {
242  CH_assert(reactiveState.size() > idx);
243  }
244 
245  for (const auto& idx : m_rhsReactives) {
246  CH_assert(reactiveState.size() > idx);
247  }
248 
249  for (const auto& idx : m_rhsNonReactives) {
250  CH_assert(photonState.size() > idx);
251  }
252 }
253 
254 #include <CD_NamespaceFooter.H>
255 
256 #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:200
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:236
void computeStateChanges() noexcept
Compute state change.
Definition: CD_KMCDualStateReactionImplem.H:41
std::list< size_t > getNonReactiveProducts() const noexcept
Get the non-reactive products from the reaction.
Definition: CD_KMCDualStateReactionImplem.H:193
T population(const size_t &a_reactant, const State &a_state) const noexcept
Get the population of the reactant in the input state.
Definition: CD_KMCDualStateReactionImplem.H:122
KMCDualStateReaction()=default
Disallowed constructor. Use the full constructor.
virtual ~KMCDualStateReaction()
Destructor.
Definition: CD_KMCDualStateReactionImplem.H:36
std::list< size_t > getReactiveProducts() const noexcept
Get the products from the reaction.
Definition: CD_KMCDualStateReactionImplem.H:186
Real propensity(const State &a_state) const noexcept
Compute the propensity function for this reaction type.
Definition: CD_KMCDualStateReactionImplem.H:133
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:154
std::list< size_t > getReactants() const noexcept
Get the reactants in the reaction.
Definition: CD_KMCDualStateReactionImplem.H:179
Real & rate() const noexcept
Get modifiable reaction rate.
Definition: CD_KMCDualStateReactionImplem.H:115
void advanceState(State &a_state, const T &a_numReactions) const noexcept
Advance the incoming state with the number of reactions.
Definition: CD_KMCDualStateReactionImplem.H:213
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:176
Real min(const Real &a_input) noexcept
Get the minimum of the input, reduced over MPI ranks (in the Chombo communicator)
Definition: CD_ParallelOpsImplem.H:58