17 template <
typename _Type>
27 p_EQUATION(ptr_to_equation),
28 p_BOTTOM_RESIDUAL(ptr_to_bottom_residual),
29 p_TOP_RESIDUAL(ptr_to_top_residual),
37 p_EQUATION -> coord(2) = xnodes[0];
40 T_ASSEMBLE =
Timer(
"Assembling of the matrix (incl. equation updates):");
41 T_SOLVE =
Timer(
"Solving of the matrix:");
45 template <
typename _Type>
56 template <
typename _Type>
61 problem =
" You have called the PDE_double_IBVP::step2 method without calling\n";
62 problem +=
" the PDE_double_IBVP::update_previous_solution method first. This\n";
63 problem +=
" method is required to copy/store the previous time level's solution\n";
64 problem +=
" and then allow you to specify/alter the x-initial condition by\n";
65 problem +=
" for the current time level.";
69 unsigned order(p_EQUATION -> get_order());
72 unsigned nx(SOLN.get_nnodes().first);
73 unsigned ny(SOLN.get_nnodes().second);
75 double max_residual(1.0);
92 for(std::size_t j = 0; j < nx - 1; ++j) {
112 assemble_matrix_problem(a, b, j);
115 std::cout.precision(12);
116 std::cout <<
" PDE_double_IBVP.step2 : x_j = " << SOLN.coord(j,0).first <<
" Residual_max = " << max_residual <<
" tol = " << TOL <<
" counter = " << counter <<
"\n";
125 for(std::size_t i = 0; i < ny; ++i) {
126 for(std::size_t var = 0; var < order; ++var) {
127 SOLN(j + 1, i, var) += b[ i * order + var ];
133 }
while((max_residual > TOL) && (counter < MAX_ITERATIONS));
134 if(counter >= MAX_ITERATIONS) {
135 std::string problem(
"\n The PDE_double_IBVP.step2 method took too many iterations. \n");
142 std::cout <<
"[DEBUG] solved at t = " << T <<
"\n";
148 template <
typename _Type>
152 const std::size_t& j) {
156 const double inv_dt(1. / DT);
158 const double inv_dx(1. / (SOLN.coord(j + 1, 0).first - SOLN.coord(j, 0).first));
160 const double x_midpt = 0.5 * (SOLN.coord(j + 1, 0).first + SOLN.coord(j, 0).first);
162 const unsigned order(p_EQUATION -> get_order());
164 const unsigned ny(SOLN.get_nnodes().second);
180 p_BOTTOM_RESIDUAL -> coord(0) = SOLN.coord(j + 1, 0).first;
181 p_BOTTOM_RESIDUAL -> coord(1) = T + DT;
183 p_BOTTOM_RESIDUAL -> update(SOLN.get_nodes_vars(j + 1, 0));
185 for(
unsigned i = 0; i < p_BOTTOM_RESIDUAL-> get_order(); ++i) {
187 for(
unsigned var = 0; var < order; ++var) {
188 a(row, var) = p_BOTTOM_RESIDUAL -> jacobian()(i, var);
190 b[ row ] = -p_BOTTOM_RESIDUAL -> residual()[ i ];
194 for(std::size_t node = 0; node <= ny - 2; ++node) {
196 const std::size_t b_node = node;
197 const std::size_t t_node = node + 1;
199 const double inv_dy = 1. / (SOLN.coord(j, t_node).second - SOLN.coord(j, b_node).second);
201 for(
unsigned var = 0; var < order; ++var) {
202 const double Fj_midpt = (SOLN(j, b_node, var) + SOLN(j, t_node, var)) / 2;
203 const double Oj_midpt = (PREV_SOLN(j, b_node, var) + PREV_SOLN(j, t_node, var)) / 2;
204 const double Fjp1_midpt = (SOLN(j + 1, b_node, var) + SOLN(j + 1, t_node, var)) / 2;
205 const double Ojp1_midpt = (PREV_SOLN(j + 1, b_node, var) + PREV_SOLN(j + 1, t_node, var)) / 2;
206 state[ var ] = (Fj_midpt + Fjp1_midpt + Oj_midpt + Ojp1_midpt) / 4;
207 state_dx[ var ] = (Fjp1_midpt - Fj_midpt + Ojp1_midpt - Oj_midpt) * inv_dx / 2;
208 state_dt[ var ] = (Fjp1_midpt + Fj_midpt - Ojp1_midpt - Oj_midpt) * inv_dt / 2;
209 state_dy[ var ] = (SOLN(j + 1, t_node, var) - SOLN(j + 1, b_node, var)
210 + SOLN(j, t_node, var) - SOLN(j, b_node, var)
211 + PREV_SOLN(j + 1, t_node, var) - PREV_SOLN(j + 1, b_node, var)
212 + PREV_SOLN(j, t_node, var) - PREV_SOLN(j, b_node, var)) * inv_dy / 4;
215 double y_midpt = 0.5 * (SOLN.coord(j, b_node).second + SOLN.coord(j, t_node).second);
217 p_EQUATION -> coord(0) = y_midpt;
218 p_EQUATION -> coord(1) = T + DT / 2.;
219 p_EQUATION -> coord(2) = x_midpt;
221 p_EQUATION -> update(state);
223 p_EQUATION -> get_jacobian_of_matrix0_mult_vector(state, state_dy, h0);
225 p_EQUATION -> get_jacobian_of_matrix1_mult_vector(state, state_dt, h1);
227 p_EQUATION -> get_jacobian_of_matrix2_mult_vector(state, state_dx, h2);
233 for(
unsigned var = 0; var < order; ++var) {
235 for(
unsigned i = 0; i < order; ++i) {
236 const std::size_t offset(i * a.
noffdiag() * 3 + row);
241 *bottom -= p_EQUATION -> jacobian()(var, i) / 2;
243 *top -= p_EQUATION -> jacobian()(var, i) / 2;
246 *bottom += h0(var, i) * 0.5;
248 *top += h0(var, i) * 0.5;
250 *bottom += h1(var, i) * .5;
252 *top += h1(var, i) * .5;
255 *bottom += h2(var, i) * .5;
257 *top += h2(var, i) * .5;
261 *bottom -= p_EQUATION -> matrix0()(var, i) * inv_dy;
263 *top += p_EQUATION -> matrix0()(var, i) * inv_dy;
266 *bottom += p_EQUATION -> matrix1()(var, i) * inv_dt;
268 *top += p_EQUATION -> matrix1()(var, i) * inv_dt;
270 *bottom += p_EQUATION -> matrix2()(var, i) * inv_dx;
272 *top += p_EQUATION -> matrix2()(var, i) * inv_dx;
275 b[ row ] = p_EQUATION -> residual()[ var ];
276 b[ row ] -=
Utility::dot(p_EQUATION -> matrix0()[ var ], state_dy);
277 b[ row ] -=
Utility::dot(p_EQUATION -> matrix1()[ var ], state_dt);
278 b[ row ] -=
Utility::dot(p_EQUATION -> matrix2()[ var ], state_dx);
285 p_TOP_RESIDUAL -> coord(0) = SOLN.coord(j + 1, ny - 1).first;
286 p_TOP_RESIDUAL -> coord(1) = T + DT;
288 p_TOP_RESIDUAL -> update(SOLN.get_nodes_vars(j + 1, ny - 1));
290 for(
unsigned i = 0; i < p_TOP_RESIDUAL -> get_order(); ++i) {
292 for(
unsigned var = 0; var < order; ++var) {
293 a(row, order * (ny - 1) + var) = p_TOP_RESIDUAL -> jacobian()(i, var);
295 b[ row ] = - p_TOP_RESIDUAL -> residual()[ i ];
299 if(row != ny * order) {
300 std::string problem(
"\n The ODE_BVP has an incorrect number of boundary conditions. \n");
301 throw ExceptionRuntime(problem);
307 template class PDE_double_IBVP<double>
Specification of the linear system class.
A templated class for equations that can be inherited from to allow instantiation of PDE_double_IBVP ...
The collection of CppNoddy exceptions.
A specification of a class for an -order IBVP of the form.
A spec for the CppNoddy Timer object.
A spec for a collection of utility functions.
A linear system class for vector right-hand sides.
void solve()
Solve the banded system.
A matrix class that constructs a BANDED matrix.
std::size_t noffdiag() const
Get the number of off-diagonal elements where the total INPUT band width is 2*noffdiag+1 since the ba...
void assign(_Type elt)
Assign a value the matrix so that it has the same geometry, but zero entries in all locations includi...
DenseVector< _Type >::elt_iter elt_iter
elt_iter get_elt_iter(std::size_t row, std::size_t col)
A matrix class that constructs a DENSE matrix as a row major std::vector of DenseVectors.
An DenseVector class – a dense vector object.
double inf_norm() const
Infinity norm.
An equation object base class used in the PDE_double_IBVP class.
An exception class that is thrown if too many Newton steps are taken in either the scalar or vector N...
A generic runtime exception.
A templated object for real/complex vector system of unsteady equations.
PDE_double_IBVP(Equation_3matrix< _Type > *equation_ptr, const DenseVector< double > &xnodes, const DenseVector< double > &ynodes, Residual_with_coords< _Type > *ptr_to_bottom_residual, Residual_with_coords< _Type > *ptr_to_top_residual)
The class is defined by a vector function for the system.
~PDE_double_IBVP()
Destructor.
void step2(const double &dt)
A Crank-Nicolson 'time' stepper.
A base class to be inherited by objects that define residuals.
A simple CPU-clock-tick timer for timing metods.
A two dimensional mesh utility object.
_Type dot(const DenseVector< _Type > &X, const DenseVector< _Type > &Y)
Templated dot product.
A collection of OO numerical routines aimed at simple (typical) applied problems in continuum mechani...