CppNoddy  0.92
Loading...
Searching...
No Matches
Public Member Functions | List of all members
CppNoddy::Newton< _Type > Class Template Reference

A vector NEWTON iteration class. More...

#include <Newton.h>

Inheritance diagram for CppNoddy::Newton< _Type >:
CppNoddy::ArcLength_base< _Type > CppNoddy::Uncopyable

Public Member Functions

 Newton (Residual< _Type > *ptr_to_residual_object, unsigned max_steps=20, double tolerance=1.e-8, double derivative_step=1.e-8)
 Constructor. More...
 
void iterate (DenseVector< _Type > &x)
 The Newton iteration method. More...
 
void set_monitor_det (bool flag)
 If set then the system will monitor the sign of determinant of the Jacobian matrix and cause an ExceptionBifurcation when it changes sign. More...
 
void solve (DenseVector< _Type > &x)
 Solve the system for an initial guess by Newton iteration, this method is inherited from the ArcLength_base class and this simply points it to the iteration method. More...
 
void arclength_solve (DenseVector< _Type > &x)
 Arc-length solve the system. More...
 
- Public Member Functions inherited from CppNoddy::ArcLength_base< _Type >
 ArcLength_base ()
 
virtual ~ArcLength_base ()
 
void init_arc (DenseVector< _Type > x, _Type *p, const double &length, const double &max_length)
 Initialise the class ready for arc-length continuation. More...
 
virtual void solve (DenseVector< _Type > &x)=0
 Compute a solution for that state & parameter variables that are an arc-length 'ds' from the current state. More...
 
double & ds ()
 Return a handle to the arclength step. More...
 
double & arcstep_multiplier ()
 Used to set the multiplication constant used when increasing or decreasing the arclength step. More...
 
bool & rescale_theta ()
 Handle to the RESCALE_THETA flag. More...
 
double & theta ()
 Set the arclength theta parameter. More...
 
double & desired_arc_proportion ()
 Handle to the desired proportion of the parameter to be used in the arc length solver. More...
 

Additional Inherited Members

- Protected Member Functions inherited from CppNoddy::ArcLength_base< _Type >
void update (const DenseVector< _Type > &x)
 A method called by arclength_solve and init_arc which stores the current converged state and parameter and hence computes the derivatives w.r.t the arc-length. More...
 
double arclength_residual (const DenseVector< _Type > &x) const
 The extra constraint that is to be used to replace the unknown arc length. More...
 
DenseVector< _Type > Jac_arclength_residual (DenseVector< _Type > &x) const
 The derivative of the arclength_residual function with respect to each of the state variables. More...
 
void update_theta (const DenseVector< _Type > &x)
 Automatically update the Keller THETA such that the proportion of the arclength obtained from the parameter is the desired value. More...
 
- Protected Attributes inherited from CppNoddy::ArcLength_base< _Type >
_Type * p_PARAM
 pointer to the parameter in arclength solves More...
 
DenseVector< _Type > LAST_X
 state variable at the last computed solution More...
 
DenseVector< _Type > X_DERIV_S
 derivative of the state variable w.r.t. arc length More...
 
_Type LAST_PARAM
 parameter value at the last computed solution More...
 
_Type PARAM_DERIV_S
 derivative of the parameter w.r.t arc length More...
 
double DS
 size of the arc length step More...
 
double MAX_DS
 maximum arc length step to be taken More...
 
double ARCSTEP_MULTIPLIER
 step change multiplier More...
 
bool INITIALISED
 for the arc-length solver - to show it has been initialised More...
 
double THETA
 the arclength theta More...
 

Detailed Description

template<typename _Type>
class CppNoddy::Newton< _Type >

A vector NEWTON iteration class.

This allows for Newton iteration to be performed for a vector function of a vector unknown. Use templates to allow double or complex.

Definition at line 25 of file Newton.h.

Constructor & Destructor Documentation

◆ Newton()

template<typename _Type >
CppNoddy::Newton< _Type >::Newton ( Residual< _Type > *  ptr_to_residual_object,
unsigned  max_steps = 20,
double  tolerance = 1.e-8,
double  derivative_step = 1.e-8 
)
explicit

Constructor.

Parameters
ptr_to_residual_objectA pointer to an inherited Residual object
max_stepsThe maximum number of iteration steps.
toleranceA tolerance used as a convergence criterion.
derivative_stepA step length used to compute derivatives.

Definition at line 19 of file Newton.cpp.

23 : ArcLength_base< _Type >(),
24 TOL(tolerance),
25 MAX_STEPS(max_steps),
26 p_RESIDUAL(ptr_to_residual_object) {
27 p_RESIDUAL -> delta() = derivative_step;
28 DELTA = derivative_step;
29 MONITOR_DET = false;
30 LAST_DET_SIGN = 1;
31 }
const double delta(0.5)

Member Function Documentation

◆ arclength_solve()

template<typename _Type >
void CppNoddy::Newton< _Type >::arclength_solve ( DenseVector< _Type > &  x)

Arc-length solve the system.

Before this can be called the arc_init method should have been called in order to ensure we know a solution and have derivatives w.r.t. the arc-length parameter.

Definition at line 98 of file Newton.cpp.

98 {
99#ifdef PARANOID
100 if(!this -> INITIALISED) {
101 std::string problem;
102 problem = "The Newton.arclength_solve method has been called, but \n";
103 problem += " you haven't called the arc_init method first. This means \n";
104 problem += " that a starting solution & derivatives thereof are unknown. \n";
105 problem += " Please initialise things appropriately! ";
106 throw ExceptionRuntime(problem);
107 }
108#endif
109#ifdef DEBUG
110 std::cout.precision(6);
111 std::cout << "[ DEBUG ] : Entering arclength_solve of the Newton class with\n";
112 std::cout << "[ DEBUG ] : a parameter of " << *(this -> p_PARAM) << "\n";
113#endif
114 // backup the state/system in case we fail
115 DenseVector<_Type> backup_state(x);
116 _Type backup_parameter(*(this -> p_PARAM));
117
118 int det_sign(1);
119 // init some local vars
120 bool step_succeeded(false);
121 unsigned itn(0);
122 // make a guess at the next solution
123 *(this -> p_PARAM) = this -> LAST_PARAM + this -> PARAM_DERIV_S * this -> DS;
124 x = this -> LAST_X + this -> X_DERIV_S * this -> DS;
125
126 // the order of the system
127 unsigned N = this -> p_RESIDUAL -> get_order();
128 DenseMatrix<_Type> J(N, N, 0.0);
129 DenseVector<_Type> R1(N, 0.0);
130 DenseVector<_Type> R2(N, 0.0);
131 DenseVector<_Type> dR_dp(N, 0.0);
132 //
133 do {
134 // update the residual object to the current guess
135 this -> p_RESIDUAL -> update(x);
136 // get the Jacobian of the system
137 J = this -> p_RESIDUAL -> jacobian();
138 R1 = this -> p_RESIDUAL -> residual();
139 // get the residual of the EXTRA arclength residual
140 double E1 = this -> arclength_residual(x);
141 // compute derivatives w.r.t the parameter
142 *(this -> p_PARAM) += this -> DELTA;
143 this -> p_RESIDUAL -> residual_fn(x, R2);
144 double E2 = this -> arclength_residual(x);
145 *(this -> p_PARAM) -= this -> DELTA;
146 dR_dp = (R2 - R1) / this -> DELTA;
147 _Type dE_dp = (E2 - E1) / this -> DELTA;
148 // bordering algorithm
149 DenseVector<_Type> y(-R1);
150 DenseVector<_Type> z(-dR_dp);
151#ifdef LAPACK
152 DenseLinearSystem<_Type> sys1(&J, &y, "lapack");
153#else
154 DenseLinearSystem<_Type> sys1(&J, &y, "native");
155#endif
156 sys1.set_monitor_det(MONITOR_DET);
157 try {
158 sys1.solve();
159 det_sign = sys1.get_det_sign();
160 } catch ( const ExceptionExternal &error ) {
161 break;
162 }
163 // the solve will have overwritten the LHS, so we need to replace it
164 J = this -> p_RESIDUAL -> jacobian();
165#ifdef LAPACK
166 DenseLinearSystem<_Type> sys2(&J, &z, "lapack");
167#else
168 DenseLinearSystem<_Type> sys2(&J, &z, "native");
169#endif
170 try {
171 sys2.solve();
172 } catch( const ExceptionExternal &error ) {
173 break;
174 }
175 DenseVector<_Type> JacE(this -> Jac_arclength_residual(x));
176 _Type delta_p = - (E1 + Utility::dot(JacE, y)) /
177 (dE_dp + Utility::dot(JacE, z));
178 DenseVector<_Type> delta_x = y + z * delta_p;
179 double max_correction = std::max(delta_x.inf_norm(), std::abs(delta_p));
180 if(max_correction < this -> TOL) {
181 step_succeeded = true;
182 break;
183 }
184 // add the corrections to the state variables
185 x += delta_x;
186 *(this -> p_PARAM) += delta_p;
187 ++itn;
188 if(itn > MAX_STEPS) {
189 step_succeeded = false;
190 break;
191 }
192 } while(true);
193
194 // is this a successful step?
195 if(!step_succeeded) {
196#ifdef DEBUG
197 std::cout << "[ DEBUG ] : REJECTING STEP \n";
198#endif
199 // if not a successful step then restore things
200 x = backup_state;
201 *(this -> p_PARAM) = backup_parameter;
202 // restore the residual object to its initial state
203 this -> p_RESIDUAL -> update(x);
204 // reduce our step length
205 this -> DS /= this -> ARCSTEP_MULTIPLIER;
206 } else {
207 // update the variables needed for arc-length continuation
208 this -> update(x);
209 if(LAST_DET_SIGN * det_sign < 0) {
210 LAST_DET_SIGN = det_sign;
211 std::string problem;
212 problem = "[ INFO ] : Determinant monitor has changed signs in the Newton class.\n";
213 problem += "[ INFO ] : Bifurcation detected.\n";
214 throw ExceptionBifurcation(problem);
215 } else {
216 LAST_DET_SIGN = det_sign;
217 }
218#ifdef DEBUG
219 std::cout << "[ DEBUG ] : Number of iterations = " << itn << "\n";
220 std::cout << "[ DEBUG ] : Parameter p = " << *(this -> p_PARAM)
221 << "; arclength DS = " << this -> DS << "\n";
222#endif
223 if(itn >= 7) {
224 // converging too slowly, so decrease DS
225 this -> DS /= this -> ARCSTEP_MULTIPLIER;
226#ifdef DEBUG
227 std::cout << "[ DEBUG ] : I decreased DS to " << this -> DS << "\n";
228#endif
229 }
230 if(itn <= 2) {
231 if(std::abs(this -> DS * this -> ARCSTEP_MULTIPLIER) < this -> MAX_DS) {
232 // converging too quickly, so increase DS
233 this -> DS *= this -> ARCSTEP_MULTIPLIER;
234#ifdef DEBUG
235 std::cout << "[ DEBUG ] : I increased DS to " << this -> DS << "\n";
236#endif
237 }
238 }
239 }
240 }
_Type * p_PARAM
pointer to the parameter in arclength solves
void update(const DenseVector< _Type > &x)
A method called by arclength_solve and init_arc which stores the current converged state and paramete...
DenseVector< _Type > Jac_arclength_residual(DenseVector< _Type > &x) const
The derivative of the arclength_residual function with respect to each of the state variables.
_Type PARAM_DERIV_S
derivative of the parameter w.r.t arc length
bool INITIALISED
for the arc-length solver - to show it has been initialised
DenseVector< _Type > X_DERIV_S
derivative of the state variable w.r.t. arc length
double DS
size of the arc length step
double ARCSTEP_MULTIPLIER
step change multiplier
double arclength_residual(const DenseVector< _Type > &x) const
The extra constraint that is to be used to replace the unknown arc length.
double MAX_DS
maximum arc length step to be taken
_Type LAST_PARAM
parameter value at the last computed solution
DenseVector< _Type > LAST_X
state variable at the last computed solution
_Type dot(const DenseVector< _Type > &X, const DenseVector< _Type > &Y)
Templated dot product.
Definition: Utility.h:314

References CppNoddy::Utility::dot(), CppNoddy::DenseLinearSystem< _Type >::get_det_sign(), CppNoddy::DenseVector< _Type >::inf_norm(), CppNoddy::DenseLinearSystem< _Type >::set_monitor_det(), and CppNoddy::DenseLinearSystem< _Type >::solve().

Referenced by main().

◆ iterate()

template<typename _Type >
void CppNoddy::Newton< _Type >::iterate ( DenseVector< _Type > &  x)

The Newton iteration method.

Parameters
xAn initial guess vector and returns the solution via this too.

Definition at line 35 of file Newton.cpp.

35 {
36 // length of the vector
37 unsigned N = x.size();
38 // Jacobian
39 DenseMatrix<_Type> J(N, N, 0.0);
40 // NVectors
41 DenseVector<_Type> oldFn(N, 0.0), newFn(N, 0.0);
42 // linear system object - native because no LAPACK complex at the moment
43 DenseLinearSystem<_Type> system(&J, &oldFn, "native");
44 system.set_monitor_det(MONITOR_DET);
45 // iteration counter
46 unsigned itn = 0;
47 do {
48 // increment the counter
49 ++itn;
50
51 // evaluate the residuals and jacobian at the current state
52 p_RESIDUAL -> update(x);
53 // get the residuals
54 oldFn = p_RESIDUAL -> residual();
55#ifdef DEBUG
56 std::cout << " DEBUG: starting with |Residuals| = " << oldFn.inf_norm() << "\n";
57#endif
58
59 if((std::abs(oldFn.inf_norm()) < TOL) || (itn == MAX_STEPS)) {
60 break;
61 }
62 // retrieve the current jacobian
63 J = p_RESIDUAL -> jacobian();
64
65 // linear solver
66 // \todo LU interface to LAPACK for complex matrices
67 system.solve();
68
69#ifdef DEBUG
70 std::cout << " DEBUG: Iteration number = " << itn << "\n";
71 std::cout << " DEBUG: |Newton correction| = " << oldFn.inf_norm() << "\n";
72#endif
73
74 // must *subtract* delta
75 x -= oldFn;
76 } while(true);
77
78 // More the 'MAX_STEPS' iterations currently triggers a failure.
79 if(itn == MAX_STEPS) {
80 std::string problem;
81 problem = " The Newton.iterate method took too many iterations. \n";
82 problem += " At the moment, this is set as a failure. \n";
83 throw ExceptionItn(problem, itn, oldFn.inf_norm());
84 }
85 LAST_DET_SIGN = system.get_det_sign();
86 if(MONITOR_DET) {
87 if(system.get_det_sign() * LAST_DET_SIGN < 0) {
88 std::string problem;
89 problem = "[ INFO ] : Determinant monitor has changed signs in ODE_BVP.\n";
90 problem += "[ INFO ] : Bifurcation detected.\n";
91 throw ExceptionBifurcation(problem);
92 }
93 }
94 }

References CppNoddy::DenseLinearSystem< _Type >::get_det_sign(), CppNoddy::DenseLinearSystem< _Type >::set_monitor_det(), CppNoddy::DenseVector< _Type >::size(), and CppNoddy::DenseLinearSystem< _Type >::solve().

Referenced by main(), and CppNoddy::Newton< _Type >::solve().

◆ set_monitor_det()

template<typename _Type >
void CppNoddy::Newton< _Type >::set_monitor_det ( bool  flag)
inline

If set then the system will monitor the sign of determinant of the Jacobian matrix and cause an ExceptionBifurcation when it changes sign.

Parameters
flagThe value to be set.

Definition at line 47 of file Newton.h.

47 {
48 MONITOR_DET = flag;
49 }

Referenced by main().

◆ solve()

template<typename _Type >
void CppNoddy::Newton< _Type >::solve ( DenseVector< _Type > &  x)
inlinevirtual

Solve the system for an initial guess by Newton iteration, this method is inherited from the ArcLength_base class and this simply points it to the iteration method.

Parameters
xAn initial guess vector, the solution overwrites it.

Implements CppNoddy::ArcLength_base< _Type >.

Definition at line 55 of file Newton.h.

55 {
56 iterate(x);
57 }
void iterate(DenseVector< _Type > &x)
The Newton iteration method.
Definition: Newton.cpp:35

References CppNoddy::Newton< _Type >::iterate().


The documentation for this class was generated from the following files:

© 2012

R.E. Hewitt