Flow123d  jenkins-Flow123d-windows32-release-multijob-51
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 
81  //compute Pade Approximant
82  mat nominator_matrix(n_substances_, n_substances_),
83  denominator_matrix(n_substances_, n_substances_),
84  pade_approximant_matrix(n_substances_, n_substances_);
85 
86  nominator_matrix.fill(0);
87  denominator_matrix.fill(0);
88  pade_approximant_matrix.fill(0);
89 
90  std::vector<double> nominator_coefs(nominator_degree_+1),
91  denominator_coefs(denominator_degree_+1);
92 
93  // compute Pade approximant polynomials for the function e^x
94  compute_exp_coefs(nominator_degree_, denominator_degree_, nominator_coefs, denominator_coefs);
95  // evaluation of polynomials of Pade approximant where x = -kt = R
96  evaluate_matrix_polynomial(nominator_matrix, r_reaction_matrix_, nominator_coefs);
97  evaluate_matrix_polynomial(denominator_matrix, r_reaction_matrix_, denominator_coefs);
98  // compute P(R(t)) / Q(R(t))
99  pade_approximant_matrix = nominator_matrix * inv(denominator_matrix);
100  //pade_approximant_matrix.print();
101 
102  // write matrix to reaction matrix
103  unsigned int rows, cols;
104  for(rows = 0; rows < n_substances_; rows++)
105  {
106  for(cols = 0; cols < n_substances_ ; cols++)
107  {
108  reaction_matrix_[rows][cols] = pade_approximant_matrix(rows,cols);
109  }
110  }
111 }
112 
113 void PadeApproximant::compute_exp_coefs(unsigned int nominator_degree,
114  unsigned int denominator_degree,
115  std::vector< double >& nominator_coefs,
116  std::vector< double >& denominator_coefs)
117 {
118  // compute factorials in forward
119  std::vector<unsigned int> factorials(nominator_degree+denominator_degree+1);
120  factorials[0] = 1;
121  for(unsigned int i = 1; i < factorials.size(); i++)
122  factorials[i] = factorials[i-1]*i;
123 
124  int sign; // variable for denominator sign alternation
125 
126  for(int j = nominator_degree; j >= 0; j--)
127  {
128  nominator_coefs[j] =
129  (double)(factorials[nominator_degree + denominator_degree - j] * factorials[nominator_degree])
130  / (factorials[nominator_degree + denominator_degree] * factorials[j] * factorials[nominator_degree - j]);
131  }
132 
133  for(int i = denominator_degree; i >= 0; i--)
134  {
135  if(i % 2 == 0) sign = 1; else sign = -1;
136  denominator_coefs[i] = sign *
137  (double)(factorials[nominator_degree + denominator_degree - i] * factorials[denominator_degree])
138  / (factorials[nominator_degree + denominator_degree] * factorials[i] * factorials[denominator_degree - i]);
139  }
140 }
141 
142 void PadeApproximant::evaluate_matrix_polynomial(mat& polynomial_matrix,
143  const mat& reaction_matrix,
144  const std::vector< double >& coefs)
145 {
146  mat identity = eye(n_substances_, n_substances_);
147 
148  ///Horner scheme for evaluating polynomial a0 + [a1 + [a2 + [a3 +...]*R(t)]*R(t)]*R(t)
149  for(int i = coefs.size()-1; i >= 0; i--)
150  {
151  polynomial_matrix = coefs[i] * identity + (polynomial_matrix * reaction_matrix);
152  }
153 }
PadeApproximant(Mesh &mesh, Input::Record in_rec)
Constructor.
int nominator_degree_
Degree of the polynomial in the nominator.
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:169
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:100
void modify_reaction_matrix(void) override
Definition: system.hh:72
std::vector< std::vector< unsigned int > > substance_ids_
~PadeApproximant(void)
Destructor.
Input::Record input_record_
Definition: equation.hh:220
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:219
Record & declare_key(const string &key, const KeyType &type, const Default &default_value, const string &description)
Definition: type_record.cc:386