Flow123d  jenkins-Flow123d-windows32-release-multijob-51
linear_reaction.cc
Go to the documentation of this file.
1 #include <math.h>
2 
3 #include "reaction/reaction.hh"
6 #include "system/global_defs.h"
7 #include "system/sys_profiler.hh"
8 
9 #include "la/distribution.hh"
10 #include "mesh/mesh.h"
11 
12 using namespace std;
13 using namespace Input::Type;
14 
16  = Record("Substep", "Equation for reading information about radioactive decays.")
17  .declare_key("parent", String(), Default::obligatory(),
18  "Identifier of an isotope.")
19  .declare_key("half_life", Double(), Default::optional(),
20  "Half life of the parent substance.")
21  .declare_key("kinetic", Double(), Default::optional(),
22  "Kinetic constants describing first order reactions.")
23  .declare_key("products", Array(String()), Default::obligatory(),
24  "Identifies isotopes which decays parental atom to.")
25  .declare_key("branch_ratios", Array(Double()), Default("1.0"), // default is one product, with ratio == 1.0
26  "Decay chain branching percentage.");
27 
28 
30  = Record("LinearReactions", "Information for a decision about the way to simulate radioactive decay.")
32  .declare_key("decays", Array( LinearReaction::input_type_one_decay_substep ), Default::obligatory(),
33  "Description of particular decay chain substeps.");
34 
35 
36 
37 
39  : ReactionTerm(init_mesh, in_rec)
40 {
41 }
42 
44 {
45 }
46 
48 {
49  ASSERT(distribution_ != nullptr, "Distribution has not been set yet.\n");
50  ASSERT(time_ != nullptr, "Time governor has not been set yet.\n");
51  ASSERT_LESS(0, names_.size());
52 
53  n_substances_ = names_.size();
55 
56  // allocation
57  prev_conc_.resize(n_substances_);
58  reaction_matrix_.resize(n_substances_);
59  for(unsigned int i_subst = 0; i_subst < n_substances_; i_subst++)
60  reaction_matrix_[i_subst].resize(n_substances_);
61 }
62 
63 
65 {
66  ASSERT(distribution_ != nullptr, "Distribution has not been set yet.\n");
67  ASSERT(time_ != nullptr, "Time governor has not been set yet.\n");
68  ASSERT_LESS(0, names_.size());
69 
70  //nothing is to be computed at zero_time_step
71 }
72 
73 
75 {
76  unsigned int rows, cols;
77  for(rows = 0; rows < n_substances_;rows++){
78  for(cols = 0; cols < n_substances_; cols++){
79  if(rows == cols) reaction_matrix_[rows][cols] = 1.0;
80  else reaction_matrix_[rows][cols] = 0.0;
81  }
82  }
83 }
84 
85 
86 void LinearReaction::modify_reaction_matrix(void) //All the parameters are supposed to be known
87 {
88  ASSERT(reaction_matrix_.size() > 0, "Reaction matrix is not allocated.\n");
89 
90  unsigned int parent_idx, product_idx, // global indices of substances
91  i_decay, i_product; // local indices of substances
92  double relative_timestep, // exponent of 0.5
93  temp_power; // temporary power of 0.5
94 
95  // cycle over reactions/over rows/over parents
96  for (i_decay = 0; i_decay < half_lives_.size(); i_decay++) {
97  // setting diagonal elements
98  parent_idx = substance_ids_[i_decay][0];
99  relative_timestep = time_->dt() / half_lives_[i_decay];
100  temp_power = pow(0.5, relative_timestep);
101  reaction_matrix_[parent_idx][parent_idx] = temp_power;
102 
103  // cycle over products of specific reaction/row/parent
104  for (i_product = 1; i_product < substance_ids_[i_decay].size(); ++i_product) {
105  product_idx = substance_ids_[i_decay][i_product];
106  reaction_matrix_[product_idx][parent_idx]
107  = (1 - temp_power)* bifurcation_[i_decay][i_product-1];
108  }
109  }
110 }
111 
112 double **LinearReaction::compute_reaction(double **concentrations, int loc_el) //multiplication of concentrations array by reaction matrix
113 {
114  unsigned int cols, rows;
115 
116  // row vector of previous concentrations = column vector of **concentrations (c_p = c')
117  for(rows = 0; rows < n_substances_; rows++){
118  prev_conc_[rows] = concentrations[rows][loc_el];
119  concentrations[rows][loc_el] = 0.0;
120  }
121 
122  // row vector of previous concentrations * reaction matrix = row vector of new concentrations
123  // row vector of new concentrations is written as column vector to **concentrations (c' = c_p*R)
124  for(rows = 0; rows < n_substances_; rows++){
125  for(cols = 0; cols < n_substances_; cols++){
126  concentrations[rows][loc_el] += reaction_matrix_[rows][cols]*prev_conc_[cols];
127  }
128  }
129 
130  return concentrations;
131 }
132 
133 // raise warning if sum of ratios is not one
135 {
136  unsigned int idx;
137 
138  Input::Array decay_array = input_record_.val<Input::Array>("decays");
139 
140  substance_ids_.resize( decay_array.size() );
141  half_lives_.resize( decay_array.size() );
142  bifurcation_.resize( decay_array.size() );
143 
144  int i_decay=0;
145  for (Input::Iterator<Input::Record> dec_it = decay_array.begin<Input::Record>(); dec_it != decay_array.end(); ++dec_it, ++i_decay)
146  {
147  //half-lives determining part
148  Input::Iterator<double> it_hl = dec_it->find<double>("half_life");
149  if (it_hl) {
150  half_lives_[i_decay] = *it_hl;
151  } else {
152  it_hl = dec_it->find<double>("kinetic");
153  if (it_hl) {
154  half_lives_[i_decay] = log(2)/(*it_hl);
155  } else {
156  xprintf(UsrErr, "Missing half-life or kinetic in the %d-th reaction.\n", i_decay);
157  }
158  }
159 
160  //indices determining part
161  string parent_name = dec_it->val<string>("parent");
162  Input::Array product_array = dec_it->val<Input::Array>("products");
163  Input::Array ratio_array = dec_it->val<Input::Array>("branch_ratios"); // has default value [ 1.0 ]
164 
165  // substance_ids contains also parent id
166  if (product_array.size() > 0) substance_ids_[i_decay].resize( product_array.size()+1 );
167  else xprintf(UsrErr,"Empty array of products in the %d-th reaction.\n", i_decay);
168 
169 
170  // set parent index
171  idx = find_subst_name(parent_name);
172  if (idx < names_.size()) substance_ids_[i_decay][0] = idx;
173  else xprintf(UsrErr,"Wrong name of parent substance in the %d-th reaction.\n", i_decay);
174 
175  // set products
176  unsigned int i_product = 1;
177  for(Input::Iterator<string> product_it = product_array.begin<string>(); product_it != product_array.end(); ++product_it, i_product++)
178  {
179  idx = find_subst_name(*product_it);
180  if (idx < names_.size()) substance_ids_[i_decay][i_product] = idx;
181  else xprintf(Warn,"Wrong name of %d-th product in the %d-th reaction.\n", i_product-1 , i_decay);
182  }
183 
184  //bifurcation determining part
185  if (ratio_array.size() == product_array.size() ) ratio_array.copy_to( bifurcation_[i_decay] );
186  else xprintf(UsrErr,"Number of branches %d has to match number of products %d in the %d-th reaction.\n",
187  ratio_array.size(), product_array.size(), i_decay);
188 
189  }
190 }
191 
193 {
194  if(time_->is_changed_dt())
195  {
198  }
199 
200  START_TIMER("linear reaction step");
201 
202  for (unsigned int loc_el = 0; loc_el < distribution_->lsize(); loc_el++)
204 
205  END_TIMER("linear reaction step");
206 }
207 
208 
210 {
211  unsigned int cols,rows;
212 
213  if(reaction_matrix_.size() == n_substances_){
214  if(time_ != NULL)
215  xprintf(Msg,"\ntime_step %f,Reaction matrix looks as follows:\n",time_->dt());
216  for(rows = 0; rows < n_substances_; rows++){
217  for(cols = 0; cols < n_substances_; cols++){
218  xprintf(Msg,"%f\t",reaction_matrix_[rows][cols]);
219  }
220  xprintf(Msg,"\n");
221  }
222  }else{
223  xprintf(Msg,"\nReaction matrix needs to be allocated.\n");
224  }
225  return;
226 }
227 
229  unsigned int i;
230 
231  xprintf(Msg, "\nHalf-lives are defined as:\n");
232  for (i = 0; i < half_lives_.size(); i++) {
233  xprintf(Msg, "parent_id: %d half_life: %f\n",substance_ids_[i][0], half_lives_[i]);
234  }
235 }
236 
237 unsigned int LinearReaction::find_subst_name(const string &name)
238 {
239 
240  unsigned int k=0;
241  for(; k < names_.size(); k++)
242  if (name == names_[k]) return k;
243 
244  return k;
245 }
void reset_reaction_matrix()
Resets reaction matrix as eye matrix.
Iterator< ValueType > begin() const
void update_solution(void) override
Updates the solution.
Accessor to input data conforming to declared Array.
Definition: accessors.hh:521
Definition: system.hh:72
void initialize() override
Prepares the object to usage.
double ** concentration_matrix_
Definition: reaction.hh:95
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:39
vector< string > names_
Names belonging to substances.
Definition: reaction.hh:109
???
Definition: mesh.h:108
Record & derive_from(AbstractRecord &parent)
Definition: type_record.cc:169
~LinearReaction(void)
Destructor.
std::vector< std::vector< double > > reaction_matrix_
unsigned int find_subst_name(const std::string &name)
virtual void modify_reaction_matrix(void)
void initialize_from_input()
Initializes private members of sorption from the input record.
Class for declaration of inputs sequences.
Definition: type_base.hh:230
std::vector< double > half_lives_
IteratorBase end() const
static Input::Type::AbstractRecord input_type
Definition: reaction.hh:24
Global macros to enhance readability and debugging, general constants.
#define ASSERT(...)
Definition: global_defs.h:121
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:376
static Input::Type::Record input_type
Distribution * distribution_
Pointer to reference to distribution of elements between processors.
Definition: reaction.hh:103
Definition: system.hh:72
unsigned int n_substances_
void print_reaction_matrix(void)
Accessor to the data with type Type::Record.
Definition: accessors.hh:308
const Ret val(const string &key) const
#define xprintf(...)
Definition: system.hh:100
#define ASSERT_LESS(a, b)
Definition: global_defs.h:164
bool is_changed_dt() const
#define START_TIMER(tag)
Starts a timer with specified tag.
Definition: system.hh:72
virtual double ** compute_reaction(double **concentrations, int loc_el) override
Support classes for parallel programing.
LinearReaction(Mesh &init_mesh, Input::Record in_rec)
Constructor.
std::vector< std::vector< unsigned int > > substance_ids_
Input::Record input_record_
Definition: equation.hh:220
std::vector< std::vector< double > > bifurcation_
double dt() const
static Input::Type::Record input_type_one_decay_substep
void zero_time_step() override
#define END_TIMER(tag)
Ends a timer with specified tag.
unsigned int size() const
Record type proxy class.
Definition: type_record.hh:161
std::vector< double > prev_conc_
TimeGovernor * time_
Definition: equation.hh:219
unsigned int lsize(int proc) const
get local size
Record & declare_key(const string &key, const KeyType &type, const Default &default_value, const string &description)
Definition: type_record.cc:386