CppNoddy  0.92
Loading...
Searching...
No Matches
EVPOrrSommerfeldEasy_lapack.cpp
Go to the documentation of this file.
1/// \file EVPOrrSommerfeldEasy_lapack.cpp
2/// \ingroup Tests
3/// \ingroup EVP
4/// Solves the following linear eigenvalue problem for values \f$ c \f$
5/// that satisfy :
6/// \f[ \phi''(y) - \alpha^2 \phi(y) - \psi(y) = 0\,, \f]
7/// \f[ \psi''(y) - \alpha^2 \psi(y) - i \alpha Re \left \{ ( U(y) - c ) \psi(y) - U''(y) \phi \right \} = 0\,, \f]
8/// subject to \f$ \phi(\pm 1) = \phi'(\pm 1) = 0 \f$ where
9/// \f$ \alpha = 1.02 \f$, \f$ Re = 5772.2 \f$ and \f$ U(y) = 1 - y^2 \f$.
10/// These values approximately correspond to the first neutral temporal mode
11/// in plane Poiseuille flow, therefore the test to be satisfied is that an eigenvalue
12/// exists with \f$ \Im ( c ) \approx 0 \f$. Here we use the ODE_EVP class with
13/// a very low number of mesh points to get an approximation to the temporal
14/// spectrum of modes. The 'most dangerous' mode is then extracted from this
15/// set, interpolated onto a MUCH finer mesh, and used as the initial guess
16/// in a nonlinear boundary-value problem using the ODE_BVP class. This leads
17/// to a local refinement of the selected mode that could equally be applied
18/// to other eigenvalues very simply.
19
20#include <BVP_bundle.h>
21#include <EVP_bundle.h>
22
23#include "../Utils_Fill.h"
24
25// enumerate the variables in the ODE
26enum { phi, phid, psi, psid, eval };
27
28namespace CppNoddy
29{
30 namespace Example
31 {
32
33 /// Globally define the Reynolds number and wavenumber
34 double Re, alpha;
35 /// Globally define the base flow
36 double U( double y )
37 {
38 return 1.0 - y * y;
39 };
40 /// Globally define the base flow curvature
41 double Udd( double y )
42 {
43 return -2.0;
44 };
45
46 /// Define the OS equation for the global QZ EVP
47 class OS_evp_equation : public Equation_2matrix<D_complex>
48 {
49 public:
50 /// The OS equation is a 4th order complex ODE
52
53 /// The OS equation
55 {
56 // define the equation as 4 1st order equations
57 g[ phi ] = z[ phid ];
58 g[ phid ] = z[ psi ] + alpha * alpha * z[ phi ];
59 g[ psi ] = z[ psid ];
60 g[ psid ] = alpha * alpha * z[ psi ]
61 + D_complex( 0.0, 1.0 ) * alpha * Re * ( U( coord(0) ) * z[ psi ] - Udd( coord(0) ) * z[ phi ] );
62 }
63
64 /// matrix to multiply the BVP coordinate
66 {
68 }
69
70 /// Define the unsteady terms by providing the mass matrix
71 /// Here we define the eigenvalue contribution to the g[ psid ] equation
72 /// - D_complex( 0.0, 1.0 ) * alpha * Re * c * z[ psi ]
74 {
75 // the eigenvalue is in equation 3, and multiplies unknown 2
76 m( 3, 2 ) = D_complex( 0.0, 1.0 ) * alpha * Re;
77 }
78
79 };
80
81
82 /// Define the OSE for the local refinement procedure
83 class OS_bvp_equation : public Equation_1matrix<D_complex>
84 {
85 public:
86 /// The OS *LOCAL* problem is a nonlinear 5th order complex BVP
87 /// because the eigenvalue is added to the 4th order equation
89
90 /// The OS equation
92 {
93 // define the equation as 5 1st order equations
94 g[ phi ] = z[ phid ];
95 g[ phid ] = z[ psi ] + alpha * alpha * z[ phi ];
96 g[ psi ] = z[ psid ];
97 g[ psid ] = alpha * alpha * z[ psi ]
98 + D_complex( 0.0, 1.0 ) * alpha * Re * ( U( coord(0) ) * z[ psi ] - Udd( coord(0) ) * z[ phi ] )
99 - D_complex( 0.0, 1.0 ) * alpha * Re * z[ eval ] * z[ psi ];
100 g[ eval ] = 0.0;
101 }
102
103 /// matrix to multiply the BVP coordinate
105 {
107 }
108
109 };
110
111 // BOUNDARY CONDITIONS FOR THE EVP SOLVER - same at both boundaries
112 class OS_evp_both_BC : public Residual<D_complex>
113 {
114 public:
115 // 2 boundary conditions and 4 unknowns
117
119 {
120 B[ 0 ] = z[ phi ];
121 B[ 1 ] = z[ phid ];
122 }
123 };
124
125
126 // BOUNDARY CONDITIONS FOR THE BVP SOLVER
127 class OS_bvp_left_BC : public Residual<D_complex>
128 {
129 public:
130 // 3 boundary conditions and 5 unknowns
132
134 {
135 B[ 0 ] = z[ phi ];
136 B[ 1 ] = z[ phid ];
137 B[ 2 ] = z[ psi ] - 1.0; // an arbitrary amplitude traded against the eigenvalue
138 }
139 };
140
141 class OS_bvp_right_BC : public Residual<D_complex>
142 {
143 public:
144 // 2 boundary conditions and 5 unknowns
146
148 {
149 B[ 0 ] = z[ phi ];
150 B[ 1 ] = z[ phid ];
151 }
152 };
153
154
155 } // end Example namespace
156} // end CppNoddy namespace
157
158using namespace CppNoddy;
159using namespace std;
160
161int main()
162{
163 cout << "\n";
164 cout << "=== EVP: Temporal OSE via the equation interface ====\n";
165 cout << "=== followed by local refinement of the eigenvalue.\n";
166 cout << "\n";
167
168
169 // instantiate the eigenproblem
171 // instantiate the boundary conditions -- same applies at both boundaries
173 Example::Re = 5772.2;
174 Example::alpha = 1.02;
175 // domain is -1 to 1
176 double left = -1.0;
177 double right = 1.0;
178 // number of nodal points
179 int N = 32;
180 // mesh
181 DenseVector<double> nodes( Utility::uniform_node_vector( left, right, N ) );
182
183 // pass it to the ode
184 ODE_EVP<D_complex> ode_global( &evp, nodes, &BC_both, &BC_both );
185 try
186 {
187 // solve the global eigenvalue problem on ropey mesh
188 ode_global.eigensolve();
189 }
190 catch (const std::runtime_error &error )
191 {
192 cout << " \033[1;31;48m * FAILED THROUGH EXCEPTION BEING RAISED \033[0m\n";
193 return 1;
194 }
195 // get the eigenvalues near the origin
196 ode_global.p_eigensystem() -> tag_eigenvalues_disc( + 1, 0.6 );
197 // make a mesh of each tagged eigenmode in the ODE_EVP class
198 ode_global.add_tagged_to_mesh();
199
200 // instantiate the nonlinear BVP formulation
202 // instantiate the BCs
205 // pass it to the ode BVP solver
206 ODE_BVP<D_complex> ode_local( &bvp, nodes, &BC_left, &BC_right );
207 // use our not-great initial guess from QZ code to start the solver off
208 // here we just use the first (0) tagged eigenvalue
209 ode_local.solution() = ode_global.get_mesh( 0 );
210 // interpolate onto a finer mesh
211 ode_local.solution().remesh1( Utility::uniform_node_vector( left, right, 1024 ) );
212 ode_local.set_monitor_det( false );
213 // solve the nonlinear BVP
214 ode_local.solve2();
215 // check the eigenvalue
216 const double tol = 1.e-4;
217 if ( abs( ode_local.solution()( 0, eval ).imag() ) < tol )
218 {
219 cout << "\033[1;32;48m * PASSED \033[0m\n";
220 return 0;
221 }
222 cout << "\033[1;31;48m * FAILED \033[0m\n";
223 return 1;
224}
@ U
Definition: BVPKarman.cpp:20
A shorter bundled include file for ODE_BVP and PDE_IBVP codes.
A shorter bundled include file for ODE_EVP and general eigenvalue 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 IBVP classes (and others).
An equation object base class used in the PDE_double_IBVP class.
Define the OSE for the local refinement procedure.
OS_bvp_equation()
The OS LOCAL problem is a nonlinear 5th order complex BVP because the eigenvalue is added to the 4th ...
void matrix0(const DenseVector< D_complex > &z, DenseMatrix< D_complex > &m) const
matrix to multiply the BVP coordinate
void residual_fn(const DenseVector< D_complex > &z, DenseVector< D_complex > &g) const
The OS equation.
void residual_fn(const DenseVector< D_complex > &z, DenseVector< D_complex > &B) const
A blank virtual residual function method.
void residual_fn(const DenseVector< D_complex > &z, DenseVector< D_complex > &B) const
A blank virtual residual function method.
void residual_fn(const DenseVector< D_complex > &z, DenseVector< D_complex > &B) const
A blank virtual residual function method.
Define the OS equation for the global QZ EVP.
void matrix1(const DenseVector< D_complex > &z, DenseMatrix< D_complex > &m) const
Define the unsteady terms by providing the mass matrix Here we define the eigenvalue contribution to ...
void residual_fn(const DenseVector< D_complex > &z, DenseVector< D_complex > &g) const
The OS equation.
void matrix0(const DenseVector< D_complex > &z, DenseMatrix< D_complex > &m) const
matrix to multiply the BVP coordinate
OS_evp_equation()
The OS equation is a 4th order complex ODE.
A templated object for real/complex vector system of first-order ordinary differential equations.
Definition: ODE_BVP.h:37
void set_monitor_det(bool flag)
Set the flag that determines if the determinant will be monitored The default is to monitor.
Definition: ODE_BVP.h:174
OneD_Node_Mesh< _Type, _Xtype > & solution()
Definition: ODE_BVP.h:187
void solve2()
Formulate and solve the ODE using Newton iteration and a second-order finite difference scheme.
Definition: ODE_BVP.cpp:83
A templated object for real/complex vector system of first-order ordinary differential equations.
Definition: ODE_EVP.h:35
LinearEigenSystem_base * p_eigensystem()
Allow access to the underlying dense linear eigensystem through a pointer to the private member data.
Definition: ODE_EVP.cpp:53
void add_tagged_to_mesh()
Definition: ODE_EVP.h:60
OneD_Node_Mesh< D_complex > get_mesh(const unsigned &i) const
Definition: ODE_EVP.h:99
void eigensolve()
Formulate and solve the global eigenvalue problem for a linear system.
Definition: ODE_EVP.cpp:58
_Xtype & coord(const unsigned &i)
General handle access to the coordinates.
A base class to be inherited by objects that define residuals.
Definition: Residual.h:15
double Udd(double y)
Globally define the base flow curvature.
double Re
Globally define the Reynolds number and wavenumber.
double g(1.0)
gravitational acceleration
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...
std::complex< double > D_complex
A complex double precision number using std::complex.
Definition: Types.h:98
void fill_identity(CppNoddy::Sequential_Matrix_base< _Type > &A)
Fill diagonal with unit values.
Definition: Utils_Fill.h:22

© 2012

R.E. Hewitt