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

A templated object for real/complex vector system of unsteady equations. More...

#include <PDE_IBVP.h>

Inheritance diagram for CppNoddy::PDE_IBVP< _Type >:
CppNoddy::Uncopyable

Public Member Functions

 PDE_IBVP (Equation_2matrix< _Type > *equation_ptr, const DenseVector< double > &nodes, Residual_with_coords< _Type > *ptr_to_left_residual, Residual_with_coords< _Type > *ptr_to_right_residual)
 The class is defined by a vector function for the system. More...
 
 ~PDE_IBVP ()
 Destructor. More...
 
void step2 (const double &dt)
 A Crank-Nicolson 'time' stepper. More...
 
void assemble_matrix_problem (BandedMatrix< _Type > &a, DenseVector< _Type > &b, const double &dt)
 Assembles the matrix problem for a BVP solve at the current time level. More...
 
double & coord ()
 Return a reference to the current value of the 'timelike/parabolic' coordinate. More...
 
OneD_Node_Mesh< _Type > & solution ()
 
OneD_Node_Mesh< _Type > & previous_solution ()
 
double & tolerance ()
 Access method to the tolerance. More...
 
int & max_itns ()
 Access method to the maximum number of iterations. More...
 
Equation_2matrix< _Type > * get_p_equation ()
 
Residual_with_coords< _Type > * get_p_left ()
 
Residual_with_coords< _Type > * get_p_right ()
 

Detailed Description

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

A templated object for real/complex vector system of unsteady equations.

Definition at line 37 of file PDE_IBVP.h.

Constructor & Destructor Documentation

◆ PDE_IBVP()

template<typename _Type >
CppNoddy::PDE_IBVP< _Type >::PDE_IBVP ( Equation_2matrix< _Type > *  equation_ptr,
const DenseVector< double > &  nodes,
Residual_with_coords< _Type > *  ptr_to_left_residual,
Residual_with_coords< _Type > *  ptr_to_right_residual 
)

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

Parameters
equation_ptrA pointer to an inherited Equation 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 34 of file PDE_IBVP.cpp.

37 :
38 TOL(1.e-8),
39 T(0.0),
40 MAX_ITERATIONS(12),
41 p_EQUATION(ptr_to_equation),
42 p_LEFT_RESIDUAL(ptr_to_left_residual),
43 p_RIGHT_RESIDUAL(ptr_to_right_residual) {
44 SOLN = OneD_Node_Mesh<_Type>(nodes, p_EQUATION -> get_order());
45 PREV_SOLN = SOLN;
46 //
47 p_EQUATION -> coord(1) = T;
48 if(p_EQUATION -> get_order() - p_LEFT_RESIDUAL -> get_order() - p_RIGHT_RESIDUAL -> get_order() != 0) {
49 std::string problem("\n The PDE_IBVP class has been constructed, but the order of the \n");
50 problem += "system does not match the number of boundary conditions.\n";
51 throw ExceptionRuntime(problem);
52 }
53#ifdef TIME
54 // timers
55 T_ASSEMBLE = Timer("Assembling of the matrix (incl. equation updates):");
56 T_SOLVE = Timer("Solving of the matrix:");
57#endif
58 }
double & coord()
Return a reference to the current value of the 'timelike/parabolic' coordinate.
Definition: PDE_IBVP.h:65

References CppNoddy::PDE_IBVP< _Type >::coord().

◆ ~PDE_IBVP()

template<typename _Type >
CppNoddy::PDE_IBVP< _Type >::~PDE_IBVP

Destructor.

Definition at line 61 of file PDE_IBVP.cpp.

61 {
62#ifdef TIME
63 std::cout << "\n";
64 T_ASSEMBLE.stop();
65 T_ASSEMBLE.print();
66 T_SOLVE.stop();
67 T_SOLVE.print();
68#endif
69 }

Member Function Documentation

◆ assemble_matrix_problem()

template<typename _Type >
void CppNoddy::PDE_IBVP< _Type >::assemble_matrix_problem ( BandedMatrix< _Type > &  a,
DenseVector< _Type > &  b,
const double &  dt 
)

Assembles the matrix problem for a BVP solve at the current time level.

Parameters
aThe LHS (banded) matrix.
bThe RHS (dense) vector.
dtThe 'time step' to be taken.

Definition at line 143 of file PDE_IBVP.cpp.

143 {
144 // clear the Jacobian matrix
145 a.assign(0.0);
146 // inverse of the time step
147 const double inv_dt(1. / dt);
148 // the order of the problem
149 const unsigned order(p_EQUATION -> get_order());
150 // number of spatial nodes
151 const unsigned ny(SOLN.get_nnodes());
152 // row counter
153 std::size_t row(0);
154 // a matrix that is used in the Jacobian of the mass matrix terms
155 DenseMatrix<_Type> h0(order, order, 0.0);
156 DenseMatrix<_Type> h1(order, order, 0.0);
157 // local state variable and functions
158 DenseVector<_Type> F_midpt(order, 0.0);
159 DenseVector<_Type> O_midpt(order, 0.0);
160 DenseVector<_Type> state(order, 0.0);
161 DenseVector<_Type> state_dt(order, 0.0);
162 DenseVector<_Type> state_dy(order, 0.0);
163 // BCn equation is evaluated at the next time step
164 p_LEFT_RESIDUAL -> coord(0) = T + dt;
165 // update the BC residuals for the current iteration
166 p_LEFT_RESIDUAL -> update(SOLN.get_nodes_vars(0));
167 // add the (linearised) LHS BCs to the matrix problem
168 for(unsigned i = 0; i < p_LEFT_RESIDUAL -> get_order(); ++i) {
169 // loop thru variables at LHS of the domain
170 for(unsigned var = 0; var < order; ++var) {
171 a(row, var) = p_LEFT_RESIDUAL -> jacobian()(i, var);
172 }
173 b[ row ] = - p_LEFT_RESIDUAL -> residual()[ i ];
174 ++row;
175 }
176 // inner nodes of the mesh, node = 0,1,2,...,N-2
177 for(std::size_t node = 0; node <= ny - 2; ++node) {
178 const std::size_t l_node = node;
179 const std::size_t r_node = node + 1;
180 // inverse of step size
181 const double inv_dy = 1. / (SOLN.coord(r_node) - SOLN.coord(l_node));
182 // set the current solution at this node by 2nd order evaluation at mid point
183 for(unsigned var = 0; var < order; ++var) {
184 const _Type F_midpt = (SOLN(l_node, var) + SOLN(r_node, var)) / 2.;
185 const _Type O_midpt = (PREV_SOLN(l_node, var) + PREV_SOLN(r_node, var)) / 2.;
186 state_dy[ var ] = (SOLN(r_node, var) - SOLN(l_node, var)
187 + PREV_SOLN(r_node, var) - PREV_SOLN(l_node, var)) * inv_dy / 2.;
188 state[ var ] = (F_midpt + O_midpt) / 2.;
189 state_dt[ var ] = (F_midpt - O_midpt) * inv_dt;
190 }
191 // set the equation's y & t values to be mid points
192 // y
193 p_EQUATION -> coord(0) = 0.5 * (SOLN.coord(l_node) + SOLN.coord(r_node));
194 // t
195 p_EQUATION -> coord(1) = T + dt / 2;
196 // Update the equation to the mid point position
197 p_EQUATION -> update(state);
198 // evaluate the Jacobian of mass contribution multiplied by state_dy
199 p_EQUATION -> get_jacobian_of_matrix0_mult_vector(state, state_dy, h0);
200 // evaluate the Jacobian of mass contribution multiplied by state_dt
201 p_EQUATION -> get_jacobian_of_matrix1_mult_vector(state, state_dt, h1);
202 // loop over all the variables
203 //
204 // to avoid repeated mapping arithmetic within operator() of the
205 // BandedMatrix class we'll access the matrix with the iterator.
206 //
207 // il = position for (0, lnode*order)
208 typename BandedMatrix<_Type>::elt_iter l_iter(a.get_elt_iter(0, l_node * order));
209 // ir = position for (0, rnode*order)
210 typename BandedMatrix<_Type>::elt_iter r_iter(a.get_elt_iter(0, r_node * order));
211 //
212 for(unsigned var = 0; var < order; ++var) {
213 // add the matrix mult terms to the linearised problem
214 for(unsigned i = 0; i < order; ++i) { // dummy index
215 // add the Jacobian terms
216 // indirect access: a( row, order * l_node + i ) -= jac_midpt( var, i ) * 0.5;
217 const std::size_t offset(i * a.noffdiag() * 3 + row);
218 const typename BandedMatrix<_Type>::elt_iter left(l_iter + offset);
219 const typename BandedMatrix<_Type>::elt_iter right(r_iter + offset);
220 //
221 *left -= p_EQUATION -> jacobian()(var, i) * 0.5;
222 // indirect access: a( row, order * r_node + i ) -= jac_midpt( var, i ) * 0.5;
223 *right -= p_EQUATION -> jacobian()(var, i) * 0.5;
224 // add the Jacobian of mass terms for dt terms
225 // indirect access: a( row, order * l_node + i ) += h1( var, i ) * 0.5;
226 *left += h0(var, i) * 0.5;
227 // indirect access: a( row, order * r_node + i ) += h1( var, i ) * 0.5;
228 *right += h0(var, i) * 0.5;
229 // add the Jacobian of mass terms for dt terms
230 // indirect access: a( row, order * l_node + i ) += h2( var, i ) * 0.5;
231 *left += h1(var, i) * 0.5;
232 // indirect access: a( row, order * r_node + i ) += h2( var, i ) * 0.5;
233 *right += h1(var, i) * 0.5;
234 // add the mass matrix terms
235 // indirect access: a( row, order * l_node + i ) -= mass_midpt( var, i ) * inv_dy;
236 *left -= p_EQUATION -> matrix0()(var, i) * inv_dy;
237 // indirect access: a( row, order * r_node + i ) += mass_midpt( var, i ) * inv_dy;
238 *right += p_EQUATION -> matrix0()(var, i) * inv_dy;
239 // indirect access: a( row, order * l_node + i ) += mass_midpt( var, i ) * inv_dt;
240 *left += p_EQUATION -> matrix1()(var, i) * inv_dt;
241 // indirect access: a( row, order * r_node + i ) += mass_midpt( var, i ) * inv_dt;
242 *right += p_EQUATION -> matrix1()(var, i) * inv_dt;
243 }
244 // RHS
245 b[ row ] = p_EQUATION -> residual()[ var ];
246 b[ row ] -= Utility::dot(p_EQUATION -> matrix0()[ var ], state_dy);
247 b[ row ] -= Utility::dot(p_EQUATION -> matrix1()[ var ], state_dt);
248 b[ row ] *= 2;
249 // increment the row
250 row += 1;
251 }
252 }
253 // BCn equation is evaluated at the next step time point as
254 // they cannot depend on d/dt terms
255 p_RIGHT_RESIDUAL -> coord(0) = T + dt;
256 // update the BC residuals for the current iteration
257 p_RIGHT_RESIDUAL -> update(SOLN.get_nodes_vars(ny - 1));
258 // add the (linearised) RHS BCs to the matrix problem
259 for(unsigned i = 0; i < p_RIGHT_RESIDUAL -> get_order(); ++i) {
260 // loop thru variables at RHS of the domain
261 for(unsigned var = 0; var < order; ++var) {
262 a(row, order * (ny - 1) + var) = p_RIGHT_RESIDUAL -> jacobian()(i, var);
263 }
264 b[ row ] = - p_RIGHT_RESIDUAL -> residual()[ i ];
265 ++row;
266 }
267#ifdef PARANOID
268 if(row != ny * order) {
269 std::string problem("\n The ODE_BVP has an incorrect number of boundary conditions. \n");
270 throw ExceptionRuntime(problem);
271 }
272#endif
273 }
DenseVector< _Type >::elt_iter elt_iter
Definition: BandedMatrix.h:20
_Type dot(const DenseVector< _Type > &X, const DenseVector< _Type > &Y)
Templated dot product.
Definition: Utility.h:314

References CppNoddy::BandedMatrix< _Type >::assign(), CppNoddy::Utility::dot(), CppNoddy::BandedMatrix< _Type >::get_elt_iter(), and CppNoddy::BandedMatrix< _Type >::noffdiag().

◆ coord()

template<typename _Type >
double & CppNoddy::PDE_IBVP< _Type >::coord ( )
inline

Return a reference to the current value of the 'timelike/parabolic' coordinate.

Returns
A handle to the current time stored in the object

Definition at line 65 of file PDE_IBVP.h.

65 {
66 return T;
67 }

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

◆ get_p_equation()

template<typename _Type >
Equation_2matrix< _Type > * CppNoddy::PDE_IBVP< _Type >::get_p_equation ( )
inline

Definition at line 87 of file PDE_IBVP.h.

87 {
88 return p_EQUATION;
89 }

◆ get_p_left()

template<typename _Type >
Residual_with_coords< _Type > * CppNoddy::PDE_IBVP< _Type >::get_p_left ( )
inline

Definition at line 91 of file PDE_IBVP.h.

91 {
92 return p_LEFT_RESIDUAL;
93 }

◆ get_p_right()

template<typename _Type >
Residual_with_coords< _Type > * CppNoddy::PDE_IBVP< _Type >::get_p_right ( )
inline

Definition at line 95 of file PDE_IBVP.h.

95 {
96 return p_RIGHT_RESIDUAL;
97 }

◆ max_itns()

template<typename _Type >
int & CppNoddy::PDE_IBVP< _Type >::max_itns ( )
inline

Access method to the maximum number of iterations.

Returns
A handle to the private member data MAX_ITERATIONS

Definition at line 83 of file PDE_IBVP.h.

83 {
84 return MAX_ITERATIONS;
85 }

◆ previous_solution()

template<typename _Type >
OneD_Node_Mesh< _Type > & CppNoddy::PDE_IBVP< _Type >::previous_solution
inline
Returns
A handle to the previous step's solution mesh

Definition at line 132 of file PDE_IBVP.h.

132 {
133 return PREV_SOLN;
134 }

◆ solution()

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

Definition at line 127 of file PDE_IBVP.h.

127 {
128 return SOLN;
129 }

Referenced by main().

◆ step2()

template<typename _Type >
void CppNoddy::PDE_IBVP< _Type >::step2 ( const double &  dt)

A Crank-Nicolson 'time' stepper.

Definition at line 72 of file PDE_IBVP.cpp.

72 {
73 // the order of the problem
74 unsigned order(p_EQUATION -> get_order());
75 // get the number of nodes in the mesh
76 // -- this may have been refined by the user since the last call.
77 unsigned ny(SOLN.get_nnodes());
78 // measure of maximum residual
79 double max_residual(1.0);
80 // iteration counter
81 int counter = 0;
82 // store this soln as the 'previous SOLUTION'
83 PREV_SOLN = SOLN;
84 // ANY LARGE STORAGE USED IN THE MAIN LOOP IS
85 // DEFINED HERE TO AVOID REPEATED CONSTRUCTION.
86 // Note we blank the A matrix after every iteration.
87 //
88 // Banded LHS matrix - max obove diagonal band width is
89 // from first variable at node i to last variable at node i+1
90 BandedMatrix<_Type> a(ny * order, 2 * order - 1, 0.0);
91 // RHS
92 DenseVector<_Type> b(ny * order, 0.0);
93 // linear solver definition
94#ifdef LAPACK
95 BandedLinearSystem<_Type> system(&a, &b, "lapack");
96#else
97 BandedLinearSystem<_Type> system(&a, &b, "native");
98#endif
99 // loop until converged or too many iterations
100 do {
101 // iteration counter
102 ++counter;
103#ifdef TIME
104 T_ASSEMBLE.start();
105#endif
106 assemble_matrix_problem(a, b, dt);
107 max_residual = b.inf_norm();
108#ifdef DEBUG
109 std::cout << " PDE_IBVP.solve : Residual_max = " << max_residual << " tol = " << TOL << "\n";
110#endif
111#ifdef TIME
112 T_ASSEMBLE.stop();
113 T_SOLVE.start();
114#endif
115 // linear solver
116 system.solve();
117 // keep the solution in a OneD_GenMesh object
118 for(std::size_t var = 0; var < order; ++var) {
119 for(std::size_t i = 0; i < ny; ++i) {
120 SOLN(i, var) += b[ i * order + var ];
121 }
122 }
123#ifdef TIME
124 T_SOLVE.stop();
125#endif
126 } while((max_residual > TOL) && (counter < MAX_ITERATIONS));
127 if(max_residual > TOL) {
128 // restore to previous state because this step failed
129 SOLN = PREV_SOLN;
130 std::string problem("\n The PDE_IBVP.step2 method took too many iterations.\n");
131 problem += "Solution has been restored to the previous accurate state.\n";
132 throw ExceptionItn(problem, counter, max_residual);
133 }
134#ifdef DEBUG
135 std::cout << "[DEBUG] time-like variable = " << T << "\n";
136#endif
137 // set the time to the updated level
138 T += dt;
139 }
void assemble_matrix_problem(BandedMatrix< _Type > &a, DenseVector< _Type > &b, const double &dt)
Assembles the matrix problem for a BVP solve at the current time level.
Definition: PDE_IBVP.cpp:143

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

Referenced by main().

◆ tolerance()

template<typename _Type >
double & CppNoddy::PDE_IBVP< _Type >::tolerance ( )
inline

Access method to the tolerance.

Returns
A handle to the private member data TOL

Definition at line 77 of file PDE_IBVP.h.

77 {
78 return TOL;
79 }

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

© 2012

R.E. Hewitt