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

A templated object for real/complex vector system of first-order ordinary differential equations. More...

#include <ODE_BVP.h>

Inheritance diagram for CppNoddy::ODE_BVP< _Type, _Xtype >:
CppNoddy::ArcLength_base< _Type > CppNoddy::Uncopyable

Public Member Functions

 ODE_BVP (Equation_1matrix< _Type, _Xtype > *ptr_to_equation, const DenseVector< _Xtype > &nodes, Residual< _Type > *ptr_to_left_residual, Residual< _Type > *ptr_to_right_residual)
 The class is defined by a vector function for the system. More...
 
virtual ~ODE_BVP ()
 Destructor. More...
 
virtual void actions_before_linear_solve (BandedMatrix< _Type > &a, DenseVector< _Type > &b)
 A virtual method that is called prior to the linear solve stage of the solve2() method. More...
 
void solve2 ()
 Formulate and solve the ODE using Newton iteration and a second-order finite difference scheme. More...
 
std::pair< unsigned, unsigned > adapt (const double &adapt_tol)
 Adapt the computational mesh ONCE. More...
 
void adapt_until (const double &adapt_tol)
 Adaptively solve the system until no refinements or unrefinements are applied. More...
 
void set_monitor_det (bool flag)
 Set the flag that determines if the determinant will be monitored The default is to monitor. More...
 
void init_arc (_Type *p, const double &length, const double &max_length)
 Initialise the class ready for arc length continuation. More...
 
double arclength_solve (const double &step)
 Arc-length solve the system. More...
 
OneD_Node_Mesh< _Type, _Xtype > & solution ()
 
double & tolerance ()
 Access method to the tolerance. More...
 
int & max_itns ()
 Access method to the maximum number of iterations. More...
 
std::pair< unsigned, unsigned > adapt (const double &adapt_tol)
 
std::pair< unsigned, unsigned > adapt (const double &adapt_tol)
 
void adapt_until (const double &adapt_tol)
 
void adapt_until (const double &adapt_tol)
 
- 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, typename _Xtype = double>
class CppNoddy::ODE_BVP< _Type, _Xtype >

A templated object for real/complex vector system of first-order ordinary differential equations.

The class is double templated, with the first type associated with real/complex data, and second (real/complex) type associated with a problem on the real line or line in the complex plane.

Definition at line 37 of file ODE_BVP.h.

Constructor & Destructor Documentation

◆ ODE_BVP()

template<typename _Type , typename _Xtype >
CppNoddy::ODE_BVP< _Type, _Xtype >::ODE_BVP ( Equation_1matrix< _Type, _Xtype > *  ptr_to_equation,
const DenseVector< _Xtype > &  nodes,
Residual< _Type > *  ptr_to_left_residual,
Residual< _Type > *  ptr_to_right_residual 
)

The class is defined by a vector function for the system.

Parameters
ptr_to_equationA pointer to an Equation_1matrix object.
nodesA vector that defines the nodal positions.
ptr_to_left_residualA pointer to a residual object that defines the LHS boundary conditions.
ptr_to_right_residualA pointer to a residual object that defines the RHS boundary conditions.

Definition at line 31 of file ODE_BVP.cpp.

34 :
35 ArcLength_base<_Type> (),
36 MAX_ITERATIONS(12),
37 TOL(1.e-8),
38 LAST_DET_SIGN(0),
39 p_EQUATION(ptr_to_equation),
40 p_LEFT_RESIDUAL(ptr_to_left_residual),
41 p_RIGHT_RESIDUAL(ptr_to_right_residual),
42 MONITOR_DET(true) {
43 // set up the solution mesh using these nodes
44 SOLUTION = OneD_Node_Mesh<_Type, _Xtype>(nodes, p_EQUATION -> get_order());
45 if((p_LEFT_RESIDUAL -> get_number_of_vars() != p_EQUATION -> get_order()) ||
46 (p_RIGHT_RESIDUAL -> get_number_of_vars() != p_EQUATION -> get_order()) ||
47 (p_LEFT_RESIDUAL -> get_order() + p_RIGHT_RESIDUAL -> get_order() != p_EQUATION -> get_order())) {
48 std::cout << "order " << p_EQUATION -> get_order() << "\n";
49 std::cout << "left nvars " << p_LEFT_RESIDUAL -> get_number_of_vars() << "\n";
50 std::cout << "right nvars " << p_RIGHT_RESIDUAL -> get_number_of_vars() << "\n";
51 std::cout << "left order " << p_LEFT_RESIDUAL -> get_order() << "\n";
52 std::cout << "right order " << p_RIGHT_RESIDUAL -> get_order() << "\n";
53 std::string problem;
54 problem = "It looks like the ODE_BVP equation and boundary conditions are\n";
55 problem += "not well posed. The number of variables for each boundary condition\n";
56 problem += "has to be the same as the order of the equation. Also the order of\n";
57 problem += "both boundary conditions has to sum to the order of the equation.\n";
58 throw ExceptionRuntime(problem);
59 }
60#ifdef TIME
61 // timers
62 T_ASSEMBLE = Timer("ODE_BVP: Assembling of the matrix (incl. equation updates):");
63 T_SOLVE = Timer("ODE_BVP: Solving of the matrix:");
64 T_REFINE = Timer("ODE_BVP: Refining the mesh:");
65#endif
66 }

◆ ~ODE_BVP()

template<typename _Type , typename _Xtype >
CppNoddy::ODE_BVP< _Type, _Xtype >::~ODE_BVP
virtual

Destructor.

Definition at line 69 of file ODE_BVP.cpp.

69 {
70#ifdef TIME
71 std::cout << "\n";
72 //T_ASSEMBLE.stop();
73 T_ASSEMBLE.print();
74 //T_SOLVE.stop();
75 T_SOLVE.print();
76 //T_REFINE.stop();
77 T_REFINE.print();
78#endif
79 }

Member Function Documentation

◆ actions_before_linear_solve()

template<typename _Type , typename _Xtype = double>
virtual void CppNoddy::ODE_BVP< _Type, _Xtype >::actions_before_linear_solve ( BandedMatrix< _Type > &  a,
DenseVector< _Type > &  b 
)
inlinevirtual

A virtual method that is called prior to the linear solve stage of the solve2() method.

This is called prior to any linear solve to allow the user to manually tune the matrix problem directly.

Parameters
aThe Jacbian matrix to be passed to the linear solver
bThe residual vector to be passed to the linear solver

Definition at line 63 of file ODE_BVP.h.

64 {}

◆ adapt() [1/3]

template<typename _Type , typename _Xtype >
std::pair< unsigned, unsigned > CppNoddy::ODE_BVP< _Type, _Xtype >::adapt ( const double &  adapt_tol)

Adapt the computational mesh ONCE.

We step through each interior node and evaluate the residual at that node. If the residual is less than the convergence tolerance, the node is removed. If the residual is greater than the adapt_tol parameter, then the mesh is adapted with an addition node place either side of the evaluation node.

Parameters
adapt_tolThe residual tolerance at a nodal point that will lead to the mesh adaptation.
Returns
A pair of values indicating the number of refinements and unrefinements.

Definition at line 481 of file ODE_BVP.cpp.

481 {
482#ifdef TIME
483 T_REFINE.start();
484#endif
485 // the order of the problem
486 unsigned order(p_EQUATION -> get_order());
487 // get the number of nodes in the mesh
488 // -- this may have been refined by the user since the
489 // last call.
490 unsigned N(SOLUTION.get_nnodes());
491 // row counter
492 //std::size_t row( 0 );
493 // local state variable and functions
494 DenseVector<_Type> F_node(order, 0.0);
495 DenseVector<_Type> R_node(order, 0.0);
496 // make sure (un)refine flags vector is sized
497 std::vector< bool > refine(N, false);
498 std::vector< bool > unrefine(N, false);
499 // Residual vector at interior nodes
500 DenseVector<double> Res2(N, 0.0);
501 // reset row counter
502 //row = 0;
503 // inner nodes of the mesh, node = 1,2,...,N-2
504 for(std::size_t node = 1; node <= N - 2; node += 2) {
505 // set the current solution at this node
506 for(unsigned var = 0; var < order; ++var) {
507 //F_node[ var ] = SOLUTION[ var ][ node ];
508 F_node[ var ] = SOLUTION(node, var);
509 }
510 // set the y-pos in the eqn
511 p_EQUATION -> coord(0) = SOLUTION.coord(node);
512 // Update the equation to the nodal position
513 p_EQUATION -> update(F_node);
514 //// evaluate the RHS at the node
515 //p_EQUATION -> get_residual( R_node );
516 // step size centred at the node
517 _Xtype invh = 1. / (SOLUTION.coord(node + 1) - SOLUTION.coord(node - 1));
518 // loop over all the variables
519 DenseVector<_Type> temp(order, 0.0);
520 for(unsigned var = 0; var < order; ++var) {
521 // residual
522 //temp[ var ] = p_EQUATION -> residual()[ var ] - ( SOLUTION[ var ][ node + 1 ] - SOLUTION[ var ][ node - 1 ] ) * invh;
523 temp[ var ] = p_EQUATION -> residual()[ var ] - (SOLUTION(node + 1, var) - SOLUTION(node - 1, var)) * invh;
524 }
525 Res2[ node ] = temp.inf_norm();
526 if(Res2[ node ] > adapt_tol) {
527 refine[ node ] = true;
528 } else if(Res2[ node ] < TOL / 10.) {
529 unrefine[ node ] = true;
530 }
531 }
532
533 std::size_t no_refined(0), no_unrefined(0);
534 for(std::size_t i = 0; i < refine.size(); ++i) {
535 if(refine[ i ] == true) {
536 no_refined += 1;
537 }
538 if(unrefine[ i ] == true) {
539 no_unrefined += 1;
540 }
541 }
542#ifdef DEBUG
543 std::cout << "[ DEBUG ] Refinements = " << no_refined << "\n";
544 std::cout << "[ DEBUG ] Unrefinements = " << no_unrefined << "\n";
545#endif
546
547 // make a new refined/unrefined mesh
548 DenseVector<_Xtype> X(SOLUTION.nodes());
549 DenseVector<_Xtype> newX;
550 newX.push_back(X[ 0 ]);
551 for(std::size_t i = 1; i < N - 1; ++i) {
552 if(refine[ i ]) {
553 if(!refine[ i - 1 ]) {
554 // have not already refined to the left
555 // so refine left AND right with new nodes
556 _Xtype left(X[ i - 1 ]);
557 _Xtype right(X[ i + 1 ]);
558 _Xtype here(X[ i ]);
559 newX.push_back((left + here) / 2.);
560 newX.push_back(here);
561 newX.push_back((right + here) / 2.);
562 } else {
563 // already left refined, so just refine right
564 _Xtype right(X[ i + 1 ]);
565 _Xtype here(X[ i ]);
566 newX.push_back(here);
567 newX.push_back((right + here) / 2.);
568 }
569 } else if(!unrefine[ i ]) {
570 newX.push_back(X[ i ]);
571 }
572 }
573 newX.push_back(X[ N - 1 ]);
574
575 // remesh the current solution to this (un)refined mesh
576 SOLUTION.remesh1(newX);
577#ifdef TIME
578 T_REFINE.stop();
579#endif
580 // adding nodes will screw up the sign of the determinant of the Jacobian
581 // so here we'll just make it zero
582 LAST_DET_SIGN = 0;
583
584 std::pair< unsigned, unsigned > feedback;
585 feedback.first = no_refined;
586 feedback.second = no_unrefined;
587 return feedback;
588 }
void update(const DenseVector< _Type > &x)
A method called by arclength_solve and init_arc which stores the current converged state and paramete...

References CppNoddy::DenseVector< _Type >::inf_norm(), and CppNoddy::DenseVector< _Type >::push_back().

Referenced by main().

◆ adapt() [2/3]

std::pair< unsigned, unsigned > CppNoddy::ODE_BVP< std::complex< double >, std::complex< double > >::adapt ( const double &  adapt_tol)

Definition at line 432 of file ODE_BVP.cpp.

432 {
433 std::string problem;
434 problem = " The ODE_BVP.adapt method has been called for a \n";
435 problem += " problem in the complex plane. This doesn't make sense \n";
436 problem += " as the path is not geometrically defined. \n";
437 throw ExceptionRuntime(problem);
438 }

◆ adapt() [3/3]

std::pair< unsigned, unsigned > CppNoddy::ODE_BVP< double, std::complex< double > >::adapt ( const double &  adapt_tol)

Definition at line 442 of file ODE_BVP.cpp.

442 {
443 std::string problem;
444 problem = " The ODE_BVP.adapt method has been called for a \n";
445 problem += " problem in the complex plane. This doesn't make sense \n";
446 problem += " as the path is not geometrically defined. \n";
447 throw ExceptionRuntime(problem);
448 }

◆ adapt_until() [1/3]

template<typename _Type , typename _Xtype >
void CppNoddy::ODE_BVP< _Type, _Xtype >::adapt_until ( const double &  adapt_tol)

Adaptively solve the system until no refinements or unrefinements are applied.

Parameters
adapt_tolThe residual tolerance at a nodal point that will lead to the mesh adaptation.

Definition at line 471 of file ODE_BVP.cpp.

471 {
472 std::pair< unsigned, unsigned > changes;
473 do {
474 changes = adapt(adapt_tol);
475 solve2();
476 std::cout << "[INFO] Adapting: " << changes.first << " " << changes.second << "\n";
477 } while(changes.first + changes.second != 0);
478 }
std::pair< unsigned, unsigned > adapt(const double &adapt_tol)
Adapt the computational mesh ONCE.
Definition: ODE_BVP.cpp:481
void solve2()
Formulate and solve the ODE using Newton iteration and a second-order finite difference scheme.
Definition: ODE_BVP.cpp:83

◆ adapt_until() [2/3]

void CppNoddy::ODE_BVP< std::complex< double >, std::complex< double > >::adapt_until ( const double &  adapt_tol)

Definition at line 452 of file ODE_BVP.cpp.

452 {
453 std::string problem;
454 problem = " The ODE_BVP.adapt method has been called for a \n";
455 problem += " problem in the complex plane. This doesn't make sense \n";
456 problem += " as the path is not geometrically defined. \n";
457 throw ExceptionRuntime(problem);
458 }

◆ adapt_until() [3/3]

void CppNoddy::ODE_BVP< double, std::complex< double > >::adapt_until ( const double &  adapt_tol)

Definition at line 462 of file ODE_BVP.cpp.

462 {
463 std::string problem;
464 problem = " The ODE_BVP.adapt method has been called for a \n";
465 problem += " problem in the complex plane. This doesn't make sense \n";
466 problem += " as the path is not geometrically defined. \n";
467 throw ExceptionRuntime(problem);
468 }

◆ arclength_solve()

template<typename _Type , typename _Xtype >
double CppNoddy::ODE_BVP< _Type, _Xtype >::arclength_solve ( const double &  step)

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.

Todo:
y & z should be solved for simultaneously - but to do this we'd have to extend the LAPACK interface and/or provide the same feature for the native solver.

Definition at line 164 of file ODE_BVP.cpp.

164 {
165 this -> ds() = step;
166 // order of the equation
167 unsigned order(p_EQUATION -> get_order());
168 // the number of nodes in the BVP
169 unsigned n(SOLUTION.get_nnodes());
170 // Banded Jacobian
171 BandedMatrix<_Type> Jac(n * order, 2 * order - 1, 0.0);
172 // residuals over all nodes vectors
173 DenseVector<_Type> Res1(n * order, 0.0);
174 DenseVector<_Type> Res2(n * order, 0.0);
175 // RHS vectors for the linear solver(s)
176 DenseVector<_Type> y(n * order, 0.0);
177 DenseVector<_Type> z(n * order, 0.0);
178#ifdef LAPACK
179 BandedLinearSystem<_Type> system1(&Jac, &y, "lapack");
180 BandedLinearSystem<_Type> system2(&Jac, &z, "lapack");
181#else
182 BandedLinearSystem<_Type> system1(&Jac, &y, "native");
183 BandedLinearSystem<_Type> system2(&Jac, &z, "native");
184#endif
185 // we use the member data 'monitor_det' to set the linear system determinant monitor
186 system1.set_monitor_det(MONITOR_DET);
187 // make backups in case we can't find a converged solution
188 DenseVector<_Type> backup_state(SOLUTION.vars_as_vector());
189 _Type backup_parameter(*(this -> p_PARAM));
190 // we can generate a 1st-order guess for the next state and parameter
191 DenseVector<_Type> x(this -> LAST_X + this -> X_DERIV_S * this -> DS);
192 *(this -> p_PARAM) = this -> LAST_PARAM + this -> PARAM_DERIV_S * this -> DS;
193 // the class keeps the solution in a OneD_mesh object, so we update it here
194 SOLUTION.set_vars_from_vector(x);
195 // determinant monitor
196 int det_sign(0);
197 // a flag to indicate if we have made a successful step
198 bool step_succeeded(false);
199 // iteration counter
200 int counter = 0;
201 // loop until converged or too many iterations
202 do {
203 /// \todo y & z should be solved for simultaneously - but to do this
204 /// we'd have to extend the LAPACK interface and/or provide the
205 /// same feature for the native solver.
206 ++counter;
207 // extra constraint corresponding to the new unknow parameter (arclength)
208 double E1 = this -> arclength_residual(x);
209 // construct the Jacobian/residual matrix problem
210 assemble_matrix_problem(Jac, Res1);
212 //BandedMatrix<_Type> Jac_copy( Jac );
213 y = Res1;
214#ifdef DEBUG
215 //std::cout << " [ DEBUG ] : max_residual = " << Res1.inf_norm() << "\n";
216#endif
217 if(Res1.inf_norm() < TOL && counter > 1) {
218 step_succeeded = true;
219 break;
220 }
221 try {
222 system1.solve();
223 det_sign = system1.get_det_sign();
224 } catch(const ExceptionExternal &error) {
225 step_succeeded = false;
226 break;
227 }
228 // derivs w.r.t parameter
229 const double delta(1.e-8);
230 *(this -> p_PARAM) += delta;
231 // we actually just want the Res2 & e2 vectors, so we still
232 // use the original Jacobian j ... but it was overwritten by the
233 // previous solve.
234 assemble_matrix_problem(Jac, Res2);
235 //Jac = Jac_copy;
236 double E2 = this -> arclength_residual(x);
238 *(this -> p_PARAM) -= delta;
239 DenseVector<_Type> dRes_dp((Res2 - Res1) / delta);
240 double dE_dp = (E2 - E1) / delta;
241 z = dRes_dp;
242 try {
243 system2.solve();
244 } catch(const ExceptionExternal& error) {
245 step_succeeded = false;
246 break;
247 }
248 // this is the extra (full) row in the augmented matrix problem
249 // bottom row formed from dE/dx_j
250 DenseVector<_Type> Jac_E(this -> Jac_arclength_residual(x));
251 // given the solutions y & z, the bordering algo provides the
252 // solution to the full sparse system via
253 _Type delta_p = - (E1 + Utility::dot(Jac_E, y)) /
254 (dE_dp + Utility::dot(Jac_E, z));
255 DenseVector<_Type> delta_x = y + z * delta_p;
256#ifdef DEBUG
257 std::cout << " [ DEBUG ] : Arclength_solve, dp = " << delta_p
258 << " dx.inf_norm() = " << delta_x.inf_norm()
259 << " theta = " << this -> THETA << "\n";
260#endif
261 // update the state variables and the parameter with corrections
262 x += delta_x;
263 *(this -> p_PARAM) += delta_p;
264 // the corrections must be put back into the mesh container
265 SOLUTION.set_vars_from_vector(x);
266 // converged?
267 if(delta_x.inf_norm() < TOL) {
268 step_succeeded = true;
269 break;
270 }
271 // too many iterations?
272 if ((counter > MAX_ITERATIONS) || (delta_x.inf_norm() > 100 )) {
273 step_succeeded = false;
274 break;
275 }
276 } while(true);
277 //
278 if(!step_succeeded) {
279 // if not a successful step then restore things
280 SOLUTION.set_vars_from_vector(backup_state);
281 *(this -> p_PARAM) = backup_parameter;
282 // reduce our step length
283 this -> DS /= this -> ARCSTEP_MULTIPLIER;
284#ifdef DEBUG
285 std::cout << "[ DEBUG ] : REJECTING STEP \n";
286 std::cout << "[ DEBUG ] : I decreased DS to " << this -> DS << "\n";
287#endif
288 } else {
289 // update the variables needed for arc-length continuation
290 this -> update(SOLUTION.vars_as_vector());
291 if(LAST_DET_SIGN * det_sign < 0) {
292 // a change in the sign of the determinant of the Jacobian
293 // has been found
294 LAST_DET_SIGN = det_sign;
295 std::string problem;
296 problem = "[ INFO ] : Determinant monitor has changed signs in the Newton class.\n";
297 problem += "[ INFO ] : Bifurcation detected.\n";
298 throw ExceptionBifurcation(problem);
299 }
300
301#ifdef DEBUG
302 std::cout << " [ DEBUG ] : Number of iterations = " << counter << "\n";
303 std::cout << " [ DEBUG ] : Parameter p = " << *(this -> p_PARAM)
304 << "; arclength DS = " << this -> DS << "\n";
305 std::cout << " [ DEBUG ] : Arclength THETA = " << this -> THETA << "\n";
306#endif
307 if(counter > 8 || std::abs(this -> DS) > this -> MAX_DS) {
308 // converging too slowly, so decrease DS
309 this -> DS /= this -> ARCSTEP_MULTIPLIER;
310#ifdef DEBUG
311 std::cout << " [ DEBUG ] : I decreased DS to " << this -> DS << "\n";
312#endif
313 }
314 if(counter < 4) {
315 if(std::abs(this -> DS * this -> ARCSTEP_MULTIPLIER) < this -> MAX_DS) {
316 // converging too quickly, so increase DS
317 this -> DS *= this -> ARCSTEP_MULTIPLIER;
318#ifdef DEBUG
319 std::cout << " [ DEBUG ] : I increased DS to " << this -> DS << "\n";
320#endif
321 }
322 }
323 }
324 return this -> DS;
325 }
_Type * p_PARAM
pointer to the parameter in arclength solves
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
DenseVector< _Type > X_DERIV_S
derivative of the state variable w.r.t. arc length
double & ds()
Return a handle to the arclength step.
double DS
size of the arc length step
double ARCSTEP_MULTIPLIER
step change multiplier
double THETA
the arclength theta
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
virtual void actions_before_linear_solve(BandedMatrix< _Type > &a, DenseVector< _Type > &b)
A virtual method that is called prior to the linear solve stage of the solve2() method.
Definition: ODE_BVP.h:63
const double delta(0.5)
_Type dot(const DenseVector< _Type > &X, const DenseVector< _Type > &Y)
Templated dot product.
Definition: Utility.h:314

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

Referenced by main().

◆ init_arc()

template<typename _Type , typename _Xtype >
void CppNoddy::ODE_BVP< _Type, _Xtype >::init_arc ( _Type *  p,
const double &  length,
const double &  max_length 
)

Initialise the class ready for arc length continuation.

The base class requires a vector, so we wrap the base class method here so that the vector can be extracted from the mesh member data.

Parameters
pThe pointer to the parameter
lengthThe initial arc length step to be taken (all in the parameter.
max_lengthThe maximum arc length step to be allowed.

Definition at line 179 of file ODE_BVP.h.

181 {
182 DenseVector<_Type> state(SOLUTION.vars_as_vector());
183 this -> init_arc(state, p, length, max_length);
184 }
void init_arc(_Type *p, const double &length, const double &max_length)
Initialise the class ready for arc length continuation.
Definition: ODE_BVP.h:179

References p.

Referenced by main().

◆ max_itns()

template<typename _Type , typename _Xtype = double>
int & CppNoddy::ODE_BVP< _Type, _Xtype >::max_itns ( )
inline

Access method to the maximum number of iterations.

Returns
A handle to the private member data MAX_ITERATIONS

Definition at line 120 of file ODE_BVP.h.

120 {
121 return MAX_ITERATIONS;
122 }

◆ set_monitor_det()

template<typename _Type , typename _Xtype >
void CppNoddy::ODE_BVP< _Type, _Xtype >::set_monitor_det ( bool  flag)

Set the flag that determines if the determinant will be monitored The default is to monitor.

Parameters
flagThe boolean value that the flag will be set to

Definition at line 174 of file ODE_BVP.h.

174 {
175 MONITOR_DET = flag;
176 }

Referenced by main().

◆ solution()

template<typename _Type , typename _Xtype >
OneD_Node_Mesh< _Type, _Xtype > & CppNoddy::ODE_BVP< _Type, _Xtype >::solution
inline
Returns
A handle to the solution mesh

Definition at line 187 of file ODE_BVP.h.

187 {
188 return SOLUTION;
189 }

Referenced by main().

◆ solve2()

template<typename _Type , typename _Xtype >
void CppNoddy::ODE_BVP< _Type, _Xtype >::solve2

Formulate and solve the ODE using Newton iteration and a second-order finite difference scheme.

The solution is stored in the publicly accessible 'solution' member data.

Definition at line 83 of file ODE_BVP.cpp.

83 {
84 // the order of the problem
85 unsigned order(p_EQUATION -> get_order());
86 // get the number of nodes in the mesh
87 // -- this may have been refined by the user since the
88 // last call.
89 unsigned n(SOLUTION.get_nnodes());
90 // measure of maximum residual
91 double max_residual(1.0);
92 // iteration counter
93 int counter = 0;
94 // determinant monitor
95 int det_sign(LAST_DET_SIGN);
96
97 // ANY LARGE STORAGE USED IN THE MAIN LOOP IS
98 // DEFINED HERE TO AVOID REPEATED CONSTRUCTION.
99 // Note we blank the A matrix after every iteration.
100 //
101 // Banded LHS matrix - max obove diagonal band width is
102 // from first variable at node i to last variable at node i+1
103 BandedMatrix<_Type> a(n * order, 2 * order - 1, 0.0);
104 // RHS
105 DenseVector<_Type> b(n * order, 0.0);
106 // linear solver definition
107#ifdef LAPACK
108 BandedLinearSystem<_Type> system(&a, &b, "lapack");
109#else
110 BandedLinearSystem<_Type> system(&a, &b, "native");
111#endif
112 // pass the local monitor_det flag to the linear system
113 system.set_monitor_det(MONITOR_DET);
114
115 // loop until converged or too many iterations
116 do {
117 // iteration counter
118 ++counter;
119#ifdef TIME
120 T_ASSEMBLE.start();
121#endif
122 assemble_matrix_problem(a, b);
124 max_residual = b.inf_norm();
125#ifdef DEBUG
126 std::cout << " ODE_BVP.solve : Residual_max = " << max_residual << " tol = " << TOL << "\n";
127#endif
128#ifdef TIME
129 T_ASSEMBLE.stop();
130 T_SOLVE.start();
131#endif
132 // linear solver
133 system.solve();
134 // keep the solution in a OneD_Node_Mesh object
135 for(std::size_t var = 0; var < order; ++var) {
136 for(std::size_t i = 0; i < n; ++i) {
137 SOLUTION(i, var) += b[ i * order + var ];
138 }
139 }
140#ifdef TIME
141 T_SOLVE.stop();
142#endif
143 } while((max_residual > TOL) && (counter < MAX_ITERATIONS));
144 if(counter >= MAX_ITERATIONS) {
145 std::string problem("\n The ODE_BVP.solve2 method took too many iterations. \n");
146 throw ExceptionItn(problem, counter, max_residual);
147 }
148
149 // last_det_sign is set to be 0 in ctor, it must be +/-1 when calculated
150 if(MONITOR_DET) {
151 det_sign = system.get_det_sign();
152 if(det_sign * LAST_DET_SIGN < 0) {
153 LAST_DET_SIGN = det_sign;
154 std::string problem;
155 problem = "[ INFO ] : Determinant monitor has changed signs in ODE_BVP.\n";
156 problem += "[ INFO ] : Bifurcation detected.\n";
157 throw ExceptionBifurcation(problem);
158 }
159 LAST_DET_SIGN = det_sign;
160 }
161 }

Referenced by main().

◆ tolerance()

template<typename _Type , typename _Xtype = double>
double & CppNoddy::ODE_BVP< _Type, _Xtype >::tolerance ( )
inline

Access method to the tolerance.

Returns
A handle to the private member data TOLERANCE

Definition at line 114 of file ODE_BVP.h.

114 {
115 return TOL;
116 }

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

© 2012

R.E. Hewitt