Flow123d  jenkins-Flow123d-windows32-release-multijob-28
pade_approximant.cc
Go to the documentation of this file.
1 #include "reaction/reaction.hh"
4 #include "system/global_defs.h"
5 
6 #include "mesh/mesh.h"
7 #include "armadillo"
8 
9 using namespace arma;
10 using namespace std;
11 using namespace Input::Type;
12 
14  = Record("Substep", "Equation for reading information about radioactive decays.")
15  .declare_key("parent", String(), Default::obligatory(),
16  "Identifier of an isotope.")
17  .declare_key("half_life", Double(), Default::optional(),
18  "Half life of the parent substance.")
19  .declare_key("kinetic", Double(), Default::optional(),
20  "Kinetic constants describing first order reactions.")
21  .declare_key("products", Array(String()), Default::obligatory(),
22  "Identifies isotopes which decays parental atom to.")
23  .declare_key("branch_ratios", Array(Double()), Default("1.0"), //default is one product, with ratio = 1.0
24  "Decay chain branching percentage.");
25 
26 
28  = Record("PadeApproximant", "Abstract record with an information about pade approximant parameters.")
30  .declare_key("decays", Array( PadeApproximant::input_type_one_decay_substep ), Default::obligatory(),
31  "Description of particular decay chain substeps.")
32  .declare_key("nom_pol_deg", Integer(), Default("2"),
33  "Polynomial degree of the nominator of Pade approximant.")
34  .declare_key("den_pol_deg", Integer(), Default("2"),
35  "Polynomial degree of the nominator of Pade approximant");
36 
37 
39  : LinearReaction(init_mesh, in_rec)
40 {
41 }
42 
44 {
45 }
46 
48 {
50 
51  // init from input
52  nominator_degree_ = input_record_.val<int>("nom_pol_deg");
53  denominator_degree_ = input_record_.val<int>("den_pol_deg");
54  if((nominator_degree_ + denominator_degree_) < 0){
55  xprintf(UsrErr, "You did not specify Pade approximant required polynomial degrees.");
56  }
57 }
58 
60 {
62 }
63 
65 {
66  // create decay matrix
67  mat r_reaction_matrix_ = zeros(n_substances_, n_substances_);
68  unsigned int reactant_index, product_index; //global indices of the substances
69  double exponent; //temporary variable
70  for (unsigned int i_decay = 0; i_decay < half_lives_.size(); i_decay++) {
71  reactant_index = substance_ids_[i_decay][0];
72  exponent = log(2) * time_->dt() / half_lives_[i_decay];
73  r_reaction_matrix_(reactant_index, reactant_index) = -exponent;
74 
75  for (unsigned int i_product = 1; i_product < substance_ids_[i_decay].size(); ++i_product){
76  product_index = substance_ids_[i_decay][i_product];
77  r_reaction_matrix_(product_index, reactant_index) = exponent * bifurcation_[i_decay][i_product-1];
78  }
79  }
80  //DBGMSG("reactions_matrix_created\n");
81  //r_reaction_matrix_.print();
82 
83  //compute Pade Approximant
84  mat nominator_matrix(n_substances_, n_substances_),
85  denominator_matrix(n_substances_, n_substances_),
86  pade_approximant_matrix(n_substances_, n_substances_);
87 
88  nominator_matrix.fill(0);
89  denominator_matrix.fill(0);
90  pade_approximant_matrix.fill(0);
91 
92  std::vector<double> nominator_coefs(nominator_degree_+1),
93  denominator_coefs(denominator_degree_+1);
94 
95  // compute Pade approximant polynomials for the function e^x
96  compute_exp_coefs(nominator_degree_, denominator_degree_, nominator_coefs, denominator_coefs);
97  // evaluation of polynomials of Pade approximant where x = -kt = R
98  evaluate_matrix_polynomial(nominator_matrix, r_reaction_matrix_, nominator_coefs);
99  evaluate_matrix_polynomial(denominator_matrix, r_reaction_matrix_, denominator_coefs);
100  // compute P(R(t)) / Q(R(t))
101  pade_approximant_matrix = nominator_matrix * inv(denominator_matrix);
102  //pade_approximant_matrix.print();
103 
104  // write matrix to reaction matrix
105  unsigned int rows, cols;
106  for(rows = 0; rows < n_substances_; rows++)
107  {
108  for(cols = 0; cols < n_substances_ ; cols++)
109  {
110  reaction_matrix_[rows][cols] = pade_approximant_matrix(rows,cols);
111  }
112  }
113  //print_reaction_matrix();
114 }
115 
116 void PadeApproximant::compute_exp_coefs(unsigned int nominator_degree,
117  unsigned int denominator_degree,
118  std::vector< double >& nominator_coefs,
119  std::vector< double >& denominator_coefs)
120 {
121  // compute factorials in forward
122  std::vector<unsigned int> factorials(nominator_degree+denominator_degree+1);
123  factorials[0] = 1;
124  for(unsigned int i = 1; i < factorials.size(); i++)
125  factorials[i] = factorials[i-1]*i;
126 
127  int sign; // variable for denominator sign alternation
128 
129  for(int j = nominator_degree; j >= 0; j--)
130  {
131  nominator_coefs[j] =
132  (double)(factorials[nominator_degree + denominator_degree - j] * factorials[nominator_degree])
133  / (factorials[nominator_degree + denominator_degree] * factorials[j] * factorials[nominator_degree - j]);
134  //DBGMSG("p(%d)=%f\n",j,nominator_coefs[j]);
135  }
136 
137  for(int i = denominator_degree; i >= 0; i--)
138  {
139  if(i % 2 == 0) sign = 1; else sign = -1;
140  denominator_coefs[i] = sign *
141  (double)(factorials[nominator_degree + denominator_degree - i] * factorials[denominator_degree])
142  / (factorials[nominator_degree + denominator_degree] * factorials[i] * factorials[denominator_degree - i]);
143  //DBGMSG("q(%d)=%f\n",i,denominator_coefs[i]);
144  }
145 }
146 
147 void PadeApproximant::evaluate_matrix_polynomial(mat& polynomial_matrix,
148  const mat& reaction_matrix,
149  const std::vector< double >& coefs)
150 {
151  //DBGMSG("evaluate_matrix_polynomial\n");
152  mat identity = eye(n_substances_, n_substances_);
153 
154  ///Horner scheme for evaluating polynomial a0 + [a1 + [a2 + [a3 +...]*R(t)]*R(t)]*R(t)
155  for(int i = coefs.size()-1; i >= 0; i--)
156  {
157  polynomial_matrix = coefs[i] * identity + (polynomial_matrix * reaction_matrix);
158  }
159  //polynomial_matrix.print();
160 }
161 
162 // unsigned int PadeApproximant::factorial(int k)
163 // {
164 // ASSERT(k >= 0, "Cannot compute factorial of negative number.");
165 //
166 // unsigned int fact = 1;
167 // while(k > 1)
168 // {
169 // fact *= k;
170 // k--;
171 // }
172 // return fact;
173 // }
PadeApproximant(Mesh &mesh, Input::Record in_rec)
Constructor.
int nominator_degree_
Computes factorial of k.
void initialize() override
Prepares the object to usage.
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:39
???
void compute_exp_coefs(unsigned int nominator_degree, unsigned int denominator_degree, std::vector< double > &nominator_coefs, std::vector< double > &denominator_coefs)
Evaluates nominator and denominator coeficients of PadeApproximant for exponencial function...
static Input::Type::Record input_type
Definition: mesh.h:108
Record & derive_from(AbstractRecord &parent)
Definition: type_record.cc:172
std::vector< std::vector< double > > reaction_matrix_
Class for declaration of the integral input data.
Definition: type_base.hh:341
Class for declaration of inputs sequences.
Definition: type_base.hh:230
std::vector< double > half_lives_
static Input::Type::AbstractRecord input_type
Definition: reaction.hh:24
int denominator_degree_
Degree of the polynomial in the denominator.
Global macros to enhance readability and debugging, general constants.
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:376
unsigned int n_substances_
void initialize() override
Prepares the object to usage.
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
void modify_reaction_matrix(void) override
Definition: system.hh:75
std::vector< std::vector< unsigned int > > substance_ids_
~PadeApproximant(void)
Destructor.
Input::Record input_record_
Definition: equation.hh:230
std::vector< std::vector< double > > bifurcation_
void zero_time_step() override
double dt() const
void evaluate_matrix_polynomial(mat &polynomial_matrix, const mat &reaction_matrix, const std::vector< double > &coefs)
Evaluates the matrix polynomial by Horner scheme.
void zero_time_step() override
static Input::Type::Record input_type_one_decay_substep
Record type proxy class.
Definition: type_record.hh:161
TimeGovernor * time_
Definition: equation.hh:228
Record & declare_key(const string &key, const KeyType &type, const Default &default_value, const string &description)
Definition: type_record.cc:390