libode
Easy to compile, fast ODE integrators as C++ classes
Loading...
Searching...
No Matches
ode_newton.cc
Go to the documentation of this file.
1
2
3#include "ode_newton.h"
4
5namespace ode {
6
7OdeNewton::OdeNewton (unsigned long n) {
8
9 //size of system
10 n_ = n;
11 //allocate an array for evaluating F
12 f_ = new double[n];
13 //allocate 2D array for evaluating J
14 J_ = new double*[n];
15 for (unsigned long i=0; i<n; i++) J_[i] = new double[n];
16 //update array
17 delx_ = new double[n];
18 //permutation array
19 p_ = new int[n];
20 //error tolerance
21 tol_Newton_ = 1e-8;
22 //iteration limit
23 iter_Newton_ = 250;
24 //Jacobian update interval
25 iJLU_ = 1;
26 //JLU counter
27 nJLU_ = 0;
28 //number of times the LU decomposed matrix is used to solve a matrix eq
29 n_solve_LU_ = 0;
30 //iteration interval for checking solution integrity
31 icheck_ = 2;
32 //whether to use only a single evaluation and LU decomposition of Jac
33 modified_ = false;
34 //whether to do no Jac evaluations and LU decomposition at all
35 ignore_JLU_ = false;
36}
37
39 delete [] f_;
40 for (unsigned long i=0; i<n_; i++) delete [] J_[i];
41 delete [] J_;
42 delete [] delx_;
43 delete [] p_;
44}
45
46void OdeNewton::err (double *errx, double *errf) {
47
48 double tx, tf, mx = 0, my = 0;
49
50 for (unsigned long i=0; i<n_; i++) {
51 if ( (tx = fabs(delx_[i])) > mx ) mx = tx;
52 if ( (tf = fabs(f_[i])) > my ) my = tf;
53 }
54 *errx = mx;
55 *errf = my;
56}
57
58void OdeNewton::JLU (double *x) {
59
60 //evaluate the Jacobian matrix
61 J_Newton(x, J_);
62 //crout LU decompose the Jacobian, storing the result
63 ode_crout_LU(J_, n_, p_);
64 //increment counter
65 nJLU_++;
66}
67
68void OdeNewton::solve_LU_(double **LU, int *p, double *b, int n, double *out) {
69 ode_solve_LU(LU, p, b, n, out);
70 n_solve_LU_++;
71}
72
73int OdeNewton::check_integrity (double *x) {
74
75 for (unsigned long i=0; i<n_; i++) {
76 //any nans?
77 if ( std::isnan(x[i]) ) return(2);
78 //any infs?
79 if ( !std::isfinite(x[i]) ) return(3);
80 }
81 return(0);
82}
83
84int OdeNewton::solve_Newton (double *x) {
85
86 unsigned long i, iter;
87 int suc; //success (or failure) code, which is zero for success
88 double errx, errf;
89
90 //initialize the update vector
91 for (i=0; i<n_; i++) delx_[i] = INFINITY;
92 //initialize the error estimates
93 err(&errx, &errf);
94
95 //if modified Newton's, use only a single evaluation and LU decomposition of J
96 if ( modified_ && (!ignore_JLU_) ) JLU(x);
97
98 //iterate
99 iter = 0;
100 while ( (errx > tol_Newton_) || (errf > tol_Newton_) ) {
101 //evaluate and LU decompose the Jacobian
102 if ( (!ignore_JLU_) && (!modified_) && (iter % iJLU_ == 0) ) JLU(x);
103 //evaluate the function
104 f_Newton(x, f_);
105 //swap the sign of y
106 for (i=0; i<n_; i++) f_[i] = -f_[i];
107 //solve the matrix equation
108 solve_LU_(J_, p_, f_, n_, delx_);
109 //update x
110 for (i=0; i<n_; i++) x[i] += delx_[i];
111 //update the error estimate
112 err(&errx, &errf);
113 //increment the counter
114 iter++;
115 //check iteration limits
116 if ( iter > iter_Newton_ ) return(1);
117 //check for nans and infs
118 if ( iter % icheck_ == 0 ) {
119 suc = check_integrity(x);
120 if ( suc != 0 ) return(suc);
121 }
122 }
123
124 return(0);
125}
126
127} // namespace ode
virtual void J_Newton(double *x, double **J)=0
evaluates the Jacobian matrix of the function being zeroed
int solve_Newton(double *x)
Solve the system of equations.
Definition ode_newton.cc:84
OdeNewton(unsigned long n)
constructs
Definition ode_newton.cc:7
virtual ~OdeNewton()
destructs
Definition ode_newton.cc:38
virtual void f_Newton(double *x, double *f)=0
evaluates the function being zeroed
void ode_solve_LU(double **LU, int *p, double *b, int n, double *out)
Solves a matrix equation where the matrix has already be crout LU decomposed.
Definition ode_linalg.cc:76
void ode_crout_LU(double **A, int n, int *p)
Crout LU decomposition.
Definition ode_linalg.cc:29