Flow123d  release_1.8.2-1603-g0109a2b
pade_approximant.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file pade_approximant.cc
15  * @brief
16  */
17 
18 #include <armadillo>
19 
20 #include "system/global_defs.h"
21 #include "input/accessors.hh"
22 #include "input/factory.hh"
23 #include "system/sys_profiler.hh"
26 
27 
28 FLOW123D_FORCE_LINK_IN_CHILD(padeApproximant)
29 
30 
31 using namespace Input::Type;
32 
33 
34 const Record & PadeApproximant::get_input_type() {
35  return Record("PadeApproximant", "Record with an information about pade approximant parameters.")
37  .declare_key("nominator_degree", Integer(1), Default("2"),
38  "Polynomial degree of the nominator of Pade approximant.")
39  .declare_key("denominator_degree", Integer(1), Default("2"),
40  "Polynomial degree of the nominator of Pade approximant")
41  .close();
42 }
43 
45  Input::register_class< PadeApproximant, Input::Record >("PadeApproximant") +
47 
49 {
50  //DBGMSG("PadeApproximant constructor.\n");
51  nominator_degree_ = in_rec.val<int>("nominator_degree");
52  denominator_degree_ = in_rec.val<int>("denominator_degree");
53 }
54 
55 PadeApproximant::PadeApproximant(unsigned int nominator_degree, unsigned int denominator_degree)
56 : nominator_degree_(nominator_degree), denominator_degree_(denominator_degree)
57 {
58 }
59 
61 {
62 }
63 
64 void PadeApproximant::update_solution(arma::vec& init_vector, arma::vec& output_vec)
65 {
66  if(step_changed_)
67  {
68  solution_matrix_ = system_matrix_*step_; //coefficients multiplied by time
70  step_changed_ = false;
71  }
72 
73  output_vec = solution_matrix_ * init_vector;
74 }
75 
76 
77 void PadeApproximant::approximate_matrix(arma::mat &matrix)
78 {
79  START_TIMER("ODEAnalytic::compute_matrix");
80 
81  OLD_ASSERT(matrix.n_rows == matrix.n_cols, "Matrix is not square.");
82 
83  unsigned int size = matrix.n_rows;
84 
85  //compute Pade Approximant
86  arma::mat nominator_matrix(size, size),
87  denominator_matrix(size, size);
88 
89  nominator_matrix.fill(0);
90  denominator_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, matrix, nominator_coefs);
99  evaluate_matrix_polynomial(denominator_matrix, matrix, denominator_coefs);
100  // compute P(R(t)) / Q(R(t))
101  matrix = nominator_matrix * inv(denominator_matrix);
102 }
103 
104 void PadeApproximant::compute_exp_coefs(unsigned int nominator_degree,
105  unsigned int denominator_degree,
106  std::vector< double >& nominator_coefs,
107  std::vector< double >& denominator_coefs)
108 {
109  // compute factorials in forward
110  std::vector<unsigned int> factorials(nominator_degree+denominator_degree+1);
111  factorials[0] = 1;
112  for(unsigned int i = 1; i < factorials.size(); i++)
113  factorials[i] = factorials[i-1]*i;
114 
115  int sign; // variable for denominator sign alternation
116 
117  for(int j = nominator_degree; j >= 0; j--)
118  {
119  nominator_coefs[j] =
120  (double)(factorials[nominator_degree + denominator_degree - j] * factorials[nominator_degree])
121  / (factorials[nominator_degree + denominator_degree] * factorials[j] * factorials[nominator_degree - j]);
122  }
123 
124  for(int i = denominator_degree; i >= 0; i--)
125  {
126  if(i % 2 == 0) sign = 1; else sign = -1;
127  denominator_coefs[i] = sign *
128  (double)(factorials[nominator_degree + denominator_degree - i] * factorials[denominator_degree])
129  / (factorials[nominator_degree + denominator_degree] * factorials[i] * factorials[denominator_degree - i]);
130  }
131 }
132 
133 void PadeApproximant::evaluate_matrix_polynomial(arma::mat& polynomial_matrix,
134  const arma::mat& input_matrix,
135  const std::vector< double >& coefs)
136 {
137  arma::mat identity = arma::eye(input_matrix.n_rows, input_matrix.n_cols);
138 
139  ///Horner scheme for evaluating polynomial a0 + [a1 + [a2 + [a3 +...]*R(t)]*R(t)]*R(t)
140  for(int i = coefs.size()-1; i >= 0; i--)
141  {
142  polynomial_matrix = coefs[i] * identity + (polynomial_matrix * input_matrix);
143  }
144  //polynomial_matrix.print();
145 }
This class implements the Pade approximation of exponential function.
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.
unsigned int size() const
Returns number of keys in the Record.
Definition: type_record.hh:578
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:50
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...
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:460
virtual Record & derive_from(Abstract &parent)
Method to derive new Record from an AbstractRecord parent.
Definition: type_record.cc:193
#define OLD_ASSERT(...)
Definition: global_defs.h:128
int denominator_degree_
Degree of the polynomial in the denominator.
Global macros to enhance readability and debugging, general constants.
static Input::Type::Abstract & get_input_type()
PadeApproximant()
Hide default constructor.
Accessor to the data with type Type::Record.
Definition: accessors.hh:277
static const Input::Type::Record & get_input_type()
const Ret val(const string &key) const
#define START_TIMER(tag)
Starts a timer with specified tag.
static const int registrar
Registrar of class to factory.
Record & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Declares a new key of the Record.
Definition: type_record.cc:459
bool step_changed_
flag is true if the step has been changed
const Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:271
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:171
#define FLOW123D_FORCE_LINK_IN_CHILD(x)
Definition: global_defs.h:246