Flow123d  jenkins-Flow123d-windows32-release-multijob-28
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  //print_half_lives();
112  //print_reaction_matrix(); //just for control print
113 }
114 
115 double **LinearReaction::compute_reaction(double **concentrations, int loc_el) //multiplication of concentrations array by reaction matrix
116 {
117  unsigned int cols, rows;
118 
119  // row vector of previous concentrations = column vector of **concentrations (c_p = c')
120  for(rows = 0; rows < n_substances_; rows++){
121  prev_conc_[rows] = concentrations[rows][loc_el];
122  concentrations[rows][loc_el] = 0.0;
123  }
124 
125  // row vector of previous concentrations * reaction matrix = row vector of new concentrations
126  // row vector of new concentrations is written as column vector to **concentrations (c' = c_p*R)
127  for(rows = 0; rows < n_substances_; rows++){
128  for(cols = 0; cols < n_substances_; cols++){
129  concentrations[rows][loc_el] += reaction_matrix_[rows][cols]*prev_conc_[cols];
130  }
131  }
132 
133  return concentrations;
134 }
135 
136 // raise warning if sum of ratios is not one
138 {
139  unsigned int idx;
140 
141  Input::Array decay_array = input_record_.val<Input::Array>("decays");
142 
143  substance_ids_.resize( decay_array.size() );
144  half_lives_.resize( decay_array.size() );
145  bifurcation_.resize( decay_array.size() );
146 
147  int i_decay=0;
148  for (Input::Iterator<Input::Record> dec_it = decay_array.begin<Input::Record>(); dec_it != decay_array.end(); ++dec_it, ++i_decay)
149  {
150  //half-lives determining part
151  Input::Iterator<double> it_hl = dec_it->find<double>("half_life");
152  if (it_hl) {
153  half_lives_[i_decay] = *it_hl;
154  } else {
155  it_hl = dec_it->find<double>("kinetic");
156  if (it_hl) {
157  half_lives_[i_decay] = log(2)/(*it_hl);
158  } else {
159  xprintf(UsrErr, "Missing half-life or kinetic in the %d-th reaction.\n", i_decay);
160  }
161  }
162 
163  //indices determining part
164  string parent_name = dec_it->val<string>("parent");
165  Input::Array product_array = dec_it->val<Input::Array>("products");
166  Input::Array ratio_array = dec_it->val<Input::Array>("branch_ratios"); // has default value [ 1.0 ]
167 
168  // substance_ids contains also parent id
169  if (product_array.size() > 0) substance_ids_[i_decay].resize( product_array.size()+1 );
170  else xprintf(UsrErr,"Empty array of products in the %d-th reaction.\n", i_decay);
171 
172 
173  // set parent index
174  idx = find_subst_name(parent_name);
175  if (idx < names_.size()) substance_ids_[i_decay][0] = idx;
176  else xprintf(UsrErr,"Wrong name of parent substance in the %d-th reaction.\n", i_decay);
177 
178  // set products
179  unsigned int i_product = 1;
180  for(Input::Iterator<string> product_it = product_array.begin<string>(); product_it != product_array.end(); ++product_it, i_product++)
181  {
182  idx = find_subst_name(*product_it);
183  if (idx < names_.size()) substance_ids_[i_decay][i_product] = idx;
184  else xprintf(Warn,"Wrong name of %d-th product in the %d-th reaction.\n", i_product-1 , i_decay);
185  }
186 
187  //bifurcation determining part
188  if (ratio_array.size() == product_array.size() ) ratio_array.copy_to( bifurcation_[i_decay] );
189  else xprintf(UsrErr,"Number of branches %d has to match number of products %d in the %d-th reaction.\n",
190  ratio_array.size(), product_array.size(), i_decay);
191 
192  }
193 }
194 
196 {
197  //DBGMSG("LinearReactions - update solution\n");
198  if(time_->is_changed_dt())
199  {
202  }
203 
204  START_TIMER("linear reaction step");
205 
206  for (unsigned int loc_el = 0; loc_el < distribution_->lsize(); loc_el++)
208 
209  END_TIMER("linear reaction step");
210 }
211 
212 
214 {
215  unsigned int cols,rows;
216 
217  //DBGMSG("r mat: %p\n", reaction_matrix);
218  if(reaction_matrix_.size() == n_substances_){
219  if(time_ != NULL)
220  xprintf(Msg,"\ntime_step %f,Reaction matrix looks as follows:\n",time_->dt());
221  for(rows = 0; rows < n_substances_; rows++){
222  for(cols = 0; cols < n_substances_; cols++){
223  xprintf(Msg,"%f\t",reaction_matrix_[rows][cols]);
224  }
225  xprintf(Msg,"\n");
226  }
227  }else{
228  xprintf(Msg,"\nReaction matrix needs to be allocated.\n");
229  }
230  return;
231 }
232 
234  unsigned int i;
235 
236  xprintf(Msg, "\nHalf-lives are defined as:\n");
237  for (i = 0; i < half_lives_.size(); i++) {
238  xprintf(Msg, "parent_id: %d half_life: %f\n",substance_ids_[i][0], half_lives_[i]);
239  }
240 }
241 
242 unsigned int LinearReaction::find_subst_name(const string &name)
243 {
244 
245  unsigned int k=0;
246  for(; k < names_.size(); k++)
247  if (name == names_[k]) return k;
248 
249  return k;
250 }
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:75
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:172
~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:120
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:75
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:104
#define ASSERT_LESS(a, b)
Definition: global_defs.h:163
bool is_changed_dt() const
#define START_TIMER(tag)
Starts a timer with specified tag.
Definition: system.hh:75
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:230
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:228
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:390