CppNoddy  0.92
Loading...
Searching...
No Matches
IBVPNonlinearFast.cpp
Go to the documentation of this file.
1/// \file IBVPNonlinearFast.cpp
2/// \ingroup Tests
3/// \ingroup IBVP_double
4/// Solving the nonlinear problem
5/// \f[ -u u_x - u_t + u_{yy} = y^2 t^2 e^{-2x} - y e^{-x}\,, \f]
6/// subject to \f$ u(x=0,y,t) = ty \f$, \f$ u(x,t=0,y) = 0 \f$
7/// and \f$ f(x, y = 0,t ) = 0 \f$, \f$ f(x, y = 1,t ) = t \f$.
8/// The solution is computed over a range of \f$ t \f$ for \f$ (x,y) \in [0,10]\times [0,1] \f$
9/// and the maximum deviation away from the exact solution \f$ u = yte^{-x} \f$ is found.
10/// The test fails if this deviation is larger than a set tolerance \f$ \tau \f$.
11/// The example is solved using the PDE_double_IBVP for problems that are
12/// parabolic in 2 coordinates \f$ (x,t) \f$ with a BVP in \f$ y \f$. This is the
13/// `fast' version in which a number of default finite-differenced methods are overloaded
14/// with their analytic versions.
15
16#include <IBVP_double_bundle.h>
17
18#include "../Utils_Fill.h"
19
20enum { U, Ud };
21
22namespace CppNoddy
23{
24 namespace Example
25 {
26
27 // A source term rigged up to give a nice exact solution
28 double source( const double& x, const double& y, const double& t )
29 {
30 return -y * std::exp( -x ) + std::pow( y * t * std::exp( -x ), 2 );
31 }
32
33 class nonlinear : public Equation_3matrix<double>
34 {
35 public:
36 /// The problem is 2nd order and real
37 nonlinear() : Equation_3matrix<double> ( 2 ) {}
38
39 /// Define a nonlinear advection diffusion problem
41 {
42 // The system
43 f[ U ] = z[ Ud ];
44 // x,y,t
45 f[ Ud ] = source( coord(2), coord(0), coord(1) );
46 }
47
48 /// Define the BVP terms
50 {
52 }
53
54 /// Define the unsteady terms by providing the mass matrix for t evolution
56 {
57 // eqn 1 variable 0
58 m( 1, 0 ) = -1.0;
59 }
60
61 /// Define the unsteady terms by providing the mass matrix for x evolution
63 {
64 // eqn 1 variable 0
65 m( 1, 0 ) = -z[ U ];
66 }
67
68 // METHODS BELOW OVERLOAD THE DEFAULT SLOW FINITE-DIFFERENCE VERSIONS
69
70 /// Provide the exact Jacobian rather than using finite-differences
72 {
73 jac( 0, Ud ) = 1.0;
74 }
76 {
77 // constant matrix
78 }
80 {
81 h( 1, U ) = - vec[ 0 ];
82 }
84 {
85 // constant matrix
86 }
87
88 };
89
90 // BOUNDARY CONDITIONS
91 class BC_lower : public Residual_with_coords<double>
92 {
93 public:
94 // 1 constraint, 2nd order system, 2 coordinates (x & t)
95 BC_lower() : Residual_with_coords<double> ( 1, 2, 2 ) {}
96
98 {
99 b[ 0 ] = z[ U ];
100 }
101 };
102
103 class BC_upper : public Residual_with_coords<double>
104 {
105 public:
106 // 1 constraint, 2nd order system, 2 coordinates (x & t)
107 BC_upper() : Residual_with_coords<double> ( 1, 2, 2 ) {}
108
110 {
111 const double x = coord( 0 );
112 const double t = coord( 1 );
113 b[ 0 ] = z[ U ] - t * std::exp( - x );
114 }
115 };
116
117 } // end Test namespace
118} // end CppNoddy namespace
119
120using namespace CppNoddy;
121using namespace std;
122
123int main()
124{
125 cout << "\n";
126 cout << "=== double_IBVP: non-constant mass matrix example ===\n";
127 cout << "\n";
128
129 // instantiate the problem
130 Example::nonlinear problem;
131 Example::BC_lower BC_bottom;
132 Example::BC_upper BC_top;
133
134 // domain definition
135 double top = 1.0;
136 double bottom = 0.0;
137 double left = 0.0;
138 double right = 10.0;
139 // number of (spatial) nodal points
140 unsigned ny = 11;
141 unsigned nx = 1001;
142 // time and time step
143 double t_end = 1.;
144 double dt = 0.01;
145
146 // construct our IBVP
147 PDE_double_IBVP<double> nlin( &problem,
148 Utility::uniform_node_vector( left, right, nx ),
149 Utility::uniform_node_vector( bottom, top, ny ),
150 &BC_bottom, &BC_top );
151
152 // initial conditions
153 for ( unsigned i = 0; i < nx; ++i )
154 {
155 for ( unsigned j = 0; j < ny; ++j )
156 {
157 nlin.solution()( i, j, U ) = 0.0;
158 nlin.solution()( i, j, Ud ) = 0.0;
159 }
160 }
161
162 double max_error( 0.0 );
163 int counter( 0 );
164 do
165 {
166 // inlet profile is time dependent, so we set it here for the next time level
168 // now we can alter the solution stored in the double_IBVP class to define
169 // the desired x=0 'initial' conditions at the next time step
170 double t_next = nlin.t() + dt;
171 for ( unsigned j = 0; j < ny; ++j )
172 {
173 double y = nlin.solution().coord( 0, j ).second;
174 nlin.solution()( 0, j, U ) = t_next * y;
175 nlin.solution()( 0, j, Ud ) = t_next;
176 }
177 nlin.step2( dt );
178 for ( unsigned i = 0; i < nx; ++i )
179 {
180 for ( unsigned j = 0; j < ny; ++j )
181 {
182 double x = nlin.solution().coord( i, j ).first;
183 double y = nlin.solution().coord( i, j ).second;
184 double exact_u = y * nlin.t() * exp( - x );
185 max_error = max( max_error, abs( exact_u - nlin.solution()( i, j, U ) ) );
186 }
187 }
188 ++counter;
189 }
190 while ( nlin.t() < t_end );
191
192 const double tol( 1.e-4 );
193 // check the error from the exact solution
194 if ( max_error > tol )
195 {
196 cout << "\033[1;31;48m * FAILED \033[0m\n";
197 cout << " Difference = " << max_error << "\n";
198 return 1;
199 }
200 else
201 {
202 cout << "\033[1;32;48m * PASSED \033[0m\n";
203 return 0;
204 }
205
206}
@ f
Definition: BVPBerman.cpp:15
@ U
Definition: BVPKarman.cpp:20
@ Ud
Definition: BVPKarman.cpp:20
int main()
A shorter bundled include file for double initial boundary value problems.
A matrix class that constructs a DENSE matrix as a row major std::vector of DenseVectors.
Definition: DenseMatrix.h:25
An DenseVector class – a dense vector object.
Definition: DenseVector.h:34
An equation object base class used in the PDE_double_IBVP class.
void residual_fn(const DenseVector< double > &z, DenseVector< double > &b) const
void residual_fn(const DenseVector< double > &z, DenseVector< double > &b) const
void residual_fn(const DenseVector< double > &z, DenseVector< double > &f) const
Define a nonlinear advection diffusion problem.
void get_jacobian_of_matrix0_mult_vector(const DenseVector< double > &state, const DenseVector< double > &vec, DenseMatrix< double > &h) const
void matrix2(const DenseVector< double > &z, DenseMatrix< double > &m) const
Define the unsteady terms by providing the mass matrix for x evolution.
void get_jacobian_of_matrix2_mult_vector(const DenseVector< double > &state, const DenseVector< double > &vec, DenseMatrix< double > &h) const
Return the product of the Jacobian-of-the-matrix and a vector 'vec' when the equation has a given 'st...
void matrix1(const DenseVector< double > &z, DenseMatrix< double > &m) const
Define the unsteady terms by providing the mass matrix for t evolution.
nonlinear()
The problem is 2nd order and real.
void jacobian(const DenseVector< double > &z, DenseMatrix< double > &jac) const
Provide the exact Jacobian rather than using finite-differences.
void get_jacobian_of_matrix1_mult_vector(const DenseVector< double > &state, const DenseVector< double > &vec, DenseMatrix< double > &h) const
void matrix0(const DenseVector< double > &z, DenseMatrix< double > &m) const
Define the BVP terms.
A templated object for real/complex vector system of unsteady equations.
void update_previous_solution()
Copy the current solution to the previous solution.
double & t()
Return a reference to the current value of the 'timelike' coordinate.
void step2(const double &dt)
A Crank-Nicolson 'time' stepper.
TwoD_Node_Mesh< _Type > & solution()
A base class to be inherited by objects that define residuals.
_Xtype & coord(const unsigned &i)
General handle access to the coordinates.
double source(const double &x, const double &y, const double &t)
Definition: IBVPLinear.cpp:26
DenseVector< double > uniform_node_vector(const double &lower, const double &upper, const std::size_t &N)
Return a DENSE vector with the nodal points of a uniform mesh distributed between the upper/lower bou...
Definition: Utility.cpp:113
A collection of OO numerical routines aimed at simple (typical) applied problems in continuum mechani...
void fill_identity(CppNoddy::Sequential_Matrix_base< _Type > &A)
Fill diagonal with unit values.
Definition: Utils_Fill.h:22

© 2012

R.E. Hewitt