CppNoddy  0.92
Loading...
Searching...
No Matches
IBVPDiffusionNonlinear.cpp
Go to the documentation of this file.
1/// \file IBVPDiffusionNonlinear.cpp
2/// \ingroup Tests
3/// \ingroup IBVP
4/// Solving the unstead diffusion problem:
5/// \f[ U_t - U U_{yy} = -Ae^{-t} sin(\pi y) + ( (1+y) + Ae^{-t} sin(\pi y) )\pi^2 Ae^{-t} sin(\pi y)/\sigma \f]
6/// with boundary conditions \f$ U(y=0)=1, U(y=1)=2 \f$; where \f$ A=10 \f$. The initial condition
7/// is \f$ U(y,t=0)=1+y+A sin(\pi y) \f$.
8/// The class constructs and solves the IBVP using 2nd order finite-differencing
9/// in both space and time over a non-uniform spatial mesh. The output is compared to the exact
10/// solution \f$ U(y,t) = =1+y+A sin(\pi y)e^{-t} \f$.
11
12#include <IBVP_bundle.h>
13
14enum { U, Ud };
15
16namespace CppNoddy
17{
18 namespace Example
19 {
20
21 double A( 10.0 );
22 double sigma( 100.0 );
23
25 {
26 public:
27
28 /// The problem is 2nd order and real
30
31 /// Define the Karman equations
33 {
34 double E( A*exp( -coord(1) ) );
35 double Y( coord(0) );
36 // we will add some source terms to give an exact solution
37 f[ 0 ] = z[ Ud ];
38 f[ 1 ] = -E*sin(M_PI*Y) + ((1+Y)+E*sin(M_PI*Y))*(M_PI*M_PI)*E*sin(M_PI*Y)/sigma;
39 }
40
41 /// Define the domain-derivative terms by providing the mass matrix
43 {
44 // blank definition leads to a identity result
45 m( 0, 0 ) = 1.0;
46 m( 1, 1 ) = -z[ U ]/sigma;
47 }
48
49 /// To speed things up we'll overload this to say the mass matrix is constant
51 {
52 // blank definition leads to a zero result
53 }
54
55 /// Define the unsteady terms by providing the mass matrix
57 {
58 m( 1, 0 ) = 1.0;
59 }
60
61 /// To speed things up we'll overload this to say the mass matrix is constant
63 {
64 // blank definition leads to a zero result
65 }
66
67 };
68
69 /// Define the boundary conditions
71 {
72 public:
73 // 3 BCs for 5 unknowns and one independent coordinate (time)
74 Diffusion_left_BC() : Residual_with_coords<double> ( 1, 2, 1 ) {}
75
77 {
78 b[ 0 ] = z[ U ] - 1.0;
79 }
80 };
81
83 {
84 public:
85 // 2 BCs for 5 unknowns and one independent coordinate (time)
86 Diffusion_right_BC() : Residual_with_coords<double> ( 1, 2, 1 ) {}
87
89 {
90 b[ 0 ] = z[ U ] - 2.0;
91 }
92 };
93
94 } // end Example namespace
95} // end CppNoddy namespace
96
97using namespace CppNoddy;
98using namespace std;
99
100int main()
101{
102 cout << "\n";
103 cout << "=== IBVP: A nonlinear diffusion problem ============\n";
104 cout << "\n";
105
106 // define the system
108 // define the boundary conditions
111
112 // domain definition
113 double left = 0.0;
114 double right = 1.0;
115 // number of (spatial) nodal points
116 unsigned ny = 400;
117 // time step
118 double dt = 0.005;
119 // number of time steps
120 unsigned max_steps = ( unsigned ) ( 2.0 / dt );
121
122 // construct our IBVP with more nodes near the boundary
123 PDE_IBVP<double> diffusion( &problem, Utility::power_node_vector( left, right, ny, 1.0 ), &BC_left, &BC_right );
124 //
125 for ( unsigned i = 0; i < ny; ++i )
126 {
127 double y( diffusion.solution().coord(i) );
128 diffusion.solution()( i, U ) = (1+y) + Example::A*sin(M_PI*y);
129 diffusion.solution()( i, Ud ) = 1 + Example::A*M_PI*cos(M_PI*y);
130 }
131
132 // set up output details
133 std::string dirname("./DATA");
134 mkdir( dirname.c_str(), S_IRWXU );
135 TrackerFile metric( "./DATA/IBVP_diffusion_metric.dat" );
136 metric.push_ptr( &diffusion.coord(), "time" );
137 metric.push_ptr( &diffusion.solution()( 0, Ud ), "y=0 derivative" );
138 metric.header();
139 TrackerFile profs( "./DATA/IBVP_diffusion_profs.dat" );
140 profs.push_ptr( &diffusion.coord(), "time" );
141 profs.push_ptr( &diffusion.solution(), "solution" );
142 profs.header();
143
144 Timer timer;
145 timer.start();
146 //
147 double max_error( 0.0 );
148 // time step
149 for ( unsigned i = 1; i < max_steps; ++i )
150 {
151 // take a time step
152 try
153 {
154 diffusion.step2( dt );
155 }
156 catch (const std::runtime_error &error )
157 {
158 cout << " \033[1;31;48m * FAILED THROUGH EXCEPTION BEING RAISED \033[0m\n";
159 return 1;
160 }
161 if ( i % 20 == 0 )
162 {
163 cout << diffusion.coord() << "\n";
164 profs.update();
165 profs.newline();
166 }
167 timer.counter()++;
168 metric.update();
169 //
170 double yy( 0.5 );
171 double Uexact = 1 + yy + Example::A*exp(-diffusion.coord())*sin(M_PI*yy);
172 double error = diffusion.solution().get_interpolated_vars( 0.5 )[ U ] - Uexact;
173 max_error = std::max( std::abs( error ), max_error );
174 //
175 // std::cout << " ****** " << diffusion.t() << " " << max_error << "\n";
176 }
177 timer.stop();
178 timer.print();
179 //
180 const double tol( 1.e-4 );
181 // check the BL transpiration vs the known solution
182 if ( max_error > tol )
183 {
184 cout << "\033[1;31;48m * FAILED \033[0m\n";
185 cout << " Max difference over time steps = " << max_error << "\n";
186 return 1;
187 }
188 else
189 {
190 cout << "\033[1;32;48m * PASSED \033[0m\n";
191 return 0;
192 }
193
194}
@ f
Definition: BVPBerman.cpp:15
@ U
Definition: BVPKarman.cpp:20
@ Ud
Definition: BVPKarman.cpp:20
A shorter bundled include file for 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 > &f) const
Define the Karman equations.
void get_jacobian_of_matrix1_mult_vector(const DenseVector< double > &state, const DenseVector< double > &vec, DenseMatrix< double > &h) const
To speed things up we'll overload this to say the mass matrix is constant.
Diffusion_equations()
The problem is 2nd order and real.
void matrix1(const DenseVector< double > &z, DenseMatrix< double > &m) const
Define the unsteady terms by providing the mass matrix.
void matrix0(const DenseVector< double > &z, DenseMatrix< double > &m) const
Define the domain-derivative terms by providing the mass matrix.
void get_jacobian_of_matrix0_mult_vector(const DenseVector< double > &state, const DenseVector< double > &vec, DenseMatrix< double > &h) const
To speed things up we'll overload this to say the mass matrix is constant.
void residual_fn(const DenseVector< double > &z, DenseVector< double > &b) const
void residual_fn(const DenseVector< double > &z, DenseVector< double > &b) const
A templated object for real/complex vector system of unsteady equations.
Definition: PDE_IBVP.h:37
void step2(const double &dt)
A Crank-Nicolson 'time' stepper.
Definition: PDE_IBVP.cpp:72
OneD_Node_Mesh< _Type > & solution()
Definition: PDE_IBVP.h:127
double & coord()
Return a reference to the current value of the 'timelike/parabolic' coordinate.
Definition: PDE_IBVP.h:65
A base class to be inherited by objects that define residuals.
_Xtype & coord(const unsigned &i)
General handle access to the coordinates.
A simple CPU-clock-tick timer for timing metods.
Definition: Timer.h:19
void start()
Start the timer & reset stored time to zero.
Definition: Timer.cpp:12
int & counter()
Increment an internal discrete counter.
Definition: Timer.cpp:44
void print() const
Write a string to cout stating the time taken.
Definition: Timer.cpp:59
void stop()
Stop the clock & add the current time interval to the previously stored values ready for printing.
Definition: Timer.cpp:17
void push_ptr(double *scalar, std::string desc="")
Definition: TrackerFile.cpp:27
double A(1.0)
initial hump amplitude
double sigma(100.0)
DenseVector< double > power_node_vector(const double &lower, const double &upper, const std::size_t &N, const double &power)
Return a DENSE vector with the nodal points of a non-uniform mesh distributed between the upper/lower...
Definition: Utility.cpp:123
A collection of OO numerical routines aimed at simple (typical) applied problems in continuum mechani...

© 2012

R.E. Hewitt