chombo-discharge
CD_KMCSingleStateReactionImplem.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_KMCSingleStateReactionImplem_H
13 #define CD_KMCSingleStateReactionImplem_H
14 
15 // Our includes
17 #include <CD_NamespaceHeader.H>
18 
19 template <typename State, typename T>
20 inline KMCSingleStateReaction<State, T>::KMCSingleStateReaction(const std::list<size_t>& a_reactants,
21  const std::list<size_t>& a_products) noexcept
22 {
23  m_reactants = a_reactants;
24  m_products = a_products;
25 
26  this->computeStateChanges();
27 }
28 
29 template <typename State, typename T>
31 {}
32 
33 template <typename State, typename T>
34 inline void
36 {
37  // Consumed particles.
38  for (const auto& r : m_reactants) {
39  if (m_stateChange.find(r) == m_stateChange.end()) {
40  m_stateChange.emplace(r, -1);
41  }
42  else {
43  m_stateChange[r]--;
44  }
45  }
46 
47  // Produced particles.
48  for (const auto& p : m_products) {
49  if (m_stateChange.find(p) == m_stateChange.end()) {
50  m_stateChange.emplace(p, +1);
51  }
52  else {
53  m_stateChange[p]++;
54  }
55  }
56 
57  // Compute the propensity factor that we need when there are bi- or tri-particle reactions involving the same species. We need to do this
58  // 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
59  // 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
60  //
61  // a = rate * factor * N * (N-1) * (N-2) ...
62  //
63  // For this to make sense we have
64  //
65  // a = rate * N * (N-1) * (N-2) ... (N-k+1) * (N-k)!/(k! * (N-k)!)
66  // = rate * N * (N-1) * (N-2) ... * 1/k!
67  //
68  // so the factor is just 1/k! (for each species).
69 
70  m_propensityFactor = 1.0;
71 
72  std::map<size_t, size_t> reactantNumbers;
73  for (const auto& r : m_reactants) {
74  if (reactantNumbers.find(r) == reactantNumbers.end()) {
75  reactantNumbers.emplace(r, 1);
76  }
77  else {
78  reactantNumbers[r]++;
79  }
80  }
81 
82  for (const auto& rn : reactantNumbers) {
83  m_propensityFactor *= 1.0 / factorial(rn.second);
84  }
85 }
86 
87 template <typename State, typename T>
88 inline Real&
90 {
91  return m_rate;
92 }
93 
94 template <typename State, typename T>
95 inline T
96 KMCSingleStateReaction<State, T>::population(const size_t& a_reactant, const State& a_state) const noexcept
97 {
98  return a_state[a_reactant];
99 }
100 
101 template <typename State, typename T>
102 inline Real
103 KMCSingleStateReaction<State, T>::propensity(const State& a_state) const noexcept
104 {
105  Real A = m_rate * m_propensityFactor;
106 
107  State tmp = a_state;
108 
109  for (const auto& r : m_reactants) {
110  A *= tmp[r];
111 
112  tmp[r]--;
113  }
114 
115  return A;
116 }
117 
118 template <typename State, typename T>
119 inline T
121 {
123 
124  for (const auto& s : m_stateChange) {
125 
126  const size_t rI = s.first;
127  const T nuIJ = s.second;
128 
129  if (nuIJ < 0) {
130  Lj = std::min(Lj, a_state[rI] / std::abs(nuIJ));
131  }
132  }
133 
134  return Lj;
135 }
136 
137 template <typename State, typename T>
138 inline std::list<size_t>
140 {
141  return m_reactants;
142 }
143 
144 template <typename State, typename T>
145 inline T
146 KMCSingleStateReaction<State, T>::getStateChange(const size_t a_particleReactant) const noexcept
147 {
148  T nuIJ = 0;
149 
150  if (m_stateChange.find(a_particleReactant) != m_stateChange.end()) {
151  nuIJ = m_stateChange.at(a_particleReactant);
152  }
153 
154  return nuIJ;
155 }
156 
157 template <typename State, typename T>
158 inline void
159 KMCSingleStateReaction<State, T>::advanceState(State& a_state, const T& a_numReactions) const noexcept
160 {
161  for (const auto& s : m_stateChange) {
162  a_state[s.first] += a_numReactions * s.second;
163  }
164 }
165 
166 #include <CD_NamespaceFooter.H>
167 
168 #endif
Declaration of a simple reaction type for advancing "single states" in Kinetic Monte Carlo codes.
std::list< size_t > getReactants() const noexcept
Get the reactants involved in the reaction.
Definition: CD_KMCSingleStateReactionImplem.H:139
virtual ~KMCSingleStateReaction()
Destructor.
Definition: CD_KMCSingleStateReactionImplem.H:30
Real propensity(const State &a_state) const noexcept
Compute the propensity function for this reaction type.
Definition: CD_KMCSingleStateReactionImplem.H:103
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_KMCSingleStateReactionImplem.H:96
T getStateChange(const size_t a_reactant) const noexcept
Get the state change due to a change in the input reactant species.
Definition: CD_KMCSingleStateReactionImplem.H:146
void computeStateChanges() noexcept
Compute state change.
Definition: CD_KMCSingleStateReactionImplem.H:35
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_KMCSingleStateReactionImplem.H:120
void advanceState(State &a_state, const T &a_numReactions) const noexcept
Advance the incoming state with the number of reactions.
Definition: CD_KMCSingleStateReactionImplem.H:159
KMCSingleStateReaction()=default
Disallowed constructor. Use the full constructor.
Real & rate() const noexcept
Get modifiable reaction rate.
Definition: CD_KMCSingleStateReactionImplem.H:89
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