Flow123d  jenkins-Flow123d-linux-release-multijob-198
pade_approximant.cc
Go to the documentation of this file.
1 
2 #include <armadillo>
3 
4 #include "system/global_defs.h"
5 #include "input/accessors.hh"
6 #include "system/sys_profiler.hh"
9 
10 
11 using namespace Input::Type;
12 
13 
15  = Record("PadeApproximant", "Record with an information about pade approximant parameters.")
17  .declare_key("nominator_degree", Integer(1), Default("2"),
18  "Polynomial degree of the nominator of Pade approximant.")
19  .declare_key("denominator_degree", Integer(1), Default("2"),
20  "Polynomial degree of the nominator of Pade approximant");
21 
23 {
24  //DBGMSG("PadeApproximant constructor.\n");
25  nominator_degree_ = in_rec.val<int>("nominator_degree");
26  denominator_degree_ = in_rec.val<int>("denominator_degree");
27 }
28 
29 PadeApproximant::PadeApproximant(unsigned int nominator_degree, unsigned int denominator_degree)
30 : nominator_degree_(nominator_degree), denominator_degree_(denominator_degree)
31 {
32 }
33 
35 {
36 }
37 
38 void PadeApproximant::update_solution(arma::vec& init_vector, arma::vec& output_vec)
39 {
40  if(step_changed_)
41  {
42  solution_matrix_ = system_matrix_*step_; //coefficients multiplied by time
44  step_changed_ = false;
45  }
46 
47  output_vec = solution_matrix_ * init_vector;
48 }
49 
50 
51 void PadeApproximant::approximate_matrix(arma::mat &matrix)
52 {
53  START_TIMER("ODEAnalytic::compute_matrix");
54 
55  ASSERT(matrix.n_rows == matrix.n_cols, "Matrix is not square.");
56 
57  unsigned int size = matrix.n_rows;
58 
59  //compute Pade Approximant
60  arma::mat nominator_matrix(size, size),
61  denominator_matrix(size, size);
62 
63  nominator_matrix.fill(0);
64  denominator_matrix.fill(0);
65 
66  std::vector<double> nominator_coefs(nominator_degree_+1),
67  denominator_coefs(denominator_degree_+1);
68 
69  // compute Pade approximant polynomials for the function e^x
70  compute_exp_coefs(nominator_degree_, denominator_degree_, nominator_coefs, denominator_coefs);
71  // evaluation of polynomials of Pade approximant where x = -kt = R
72  evaluate_matrix_polynomial(nominator_matrix, matrix, nominator_coefs);
73  evaluate_matrix_polynomial(denominator_matrix, matrix, denominator_coefs);
74  // compute P(R(t)) / Q(R(t))
75  matrix = nominator_matrix * inv(denominator_matrix);
76 }
77 
78 void PadeApproximant::compute_exp_coefs(unsigned int nominator_degree,
79  unsigned int denominator_degree,
80  std::vector< double >& nominator_coefs,
81  std::vector< double >& denominator_coefs)
82 {
83  // compute factorials in forward
84  std::vector<unsigned int> factorials(nominator_degree+denominator_degree+1);
85  factorials[0] = 1;
86  for(unsigned int i = 1; i < factorials.size(); i++)
87  factorials[i] = factorials[i-1]*i;
88 
89  int sign; // variable for denominator sign alternation
90 
91  for(int j = nominator_degree; j >= 0; j--)
92  {
93  nominator_coefs[j] =
94  (double)(factorials[nominator_degree + denominator_degree - j] * factorials[nominator_degree])
95  / (factorials[nominator_degree + denominator_degree] * factorials[j] * factorials[nominator_degree - j]);
96  }
97 
98  for(int i = denominator_degree; i >= 0; i--)
99  {
100  if(i % 2 == 0) sign = 1; else sign = -1;
101  denominator_coefs[i] = sign *
102  (double)(factorials[nominator_degree + denominator_degree - i] * factorials[denominator_degree])
103  / (factorials[nominator_degree + denominator_degree] * factorials[i] * factorials[denominator_degree - i]);
104  }
105 }
106 
107 void PadeApproximant::evaluate_matrix_polynomial(arma::mat& polynomial_matrix,
108  const arma::mat& input_matrix,
109  const std::vector< double >& coefs)
110 {
111  arma::mat identity = arma::eye(input_matrix.n_rows, input_matrix.n_cols);
112 
113  ///Horner scheme for evaluating polynomial a0 + [a1 + [a2 + [a3 +...]*R(t)]*R(t)]*R(t)
114  for(int i = coefs.size()-1; i >= 0; i--)
115  {
116  polynomial_matrix = coefs[i] * identity + (polynomial_matrix * input_matrix);
117  }
118  //polynomial_matrix.print();
119 }
arma::mat system_matrix_
the square matrix of ODE system
void approximate_matrix(arma::mat &matrix)
int nominator_degree_
Degree of the polynomial in the nominator.
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::AbstractRecord input_type
static Input::Type::Record input_type
Record & derive_from(AbstractRecord &parent)
Definition: type_record.cc:197
void update_solution(arma::vec &init_vector, arma::vec &output_vec) override
Updates solution of the ODEs system.
Class for declaration of the integral input data.
Definition: type_base.hh:355
int denominator_degree_
Degree of the polynomial in the denominator.
Global macros to enhance readability and debugging, general constants.
#define ASSERT(...)
Definition: global_defs.h:121
PadeApproximant()
Hide default constructor.
Accessor to the data with type Type::Record.
Definition: accessors.hh:327
const Ret val(const string &key) const
#define START_TIMER(tag)
Starts a timer with specified tag.
bool step_changed_
flag is true if the step has been changed
void evaluate_matrix_polynomial(arma::mat &polynomial_matrix, const arma::mat &input_matrix, const std::vector< double > &coefs)
Evaluates the matrix polynomial by Horner scheme.
~PadeApproximant(void)
Destructor.
double step_
the step of the numerical method
arma::mat solution_matrix_
Solution matrix .
Record type proxy class.
Definition: type_record.hh:169
Record & declare_key(const string &key, const KeyType &type, const Default &default_value, const string &description)
Definition: type_record.cc:430