CppNoddy  0.92
Loading...
Searching...
No Matches
EVPOrrSommerfeldSparse_slepcz.cpp
Go to the documentation of this file.
1/// \file EVPOrrSommerfeldSparse_slepcz.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/// The matrix problem is constructed manually in this case, using second-order
11/// finite differences. A sparse eigenvalue routine is employed, via SLEPc.
12/// These values approximately correspond to the first neutral temporal mode
13/// in plane Poiseuille flow, therefore the test to be satisfied is that an eigenvalue
14/// exists with \f$ \Im ( c ) \approx 0 \f$.
15
16#include <Generic_bundle.h>
18#include <SlepcSession.h>
19
20using namespace CppNoddy;
21using namespace std;
22
23
24int main(int argc, char* argv[])
25{
26 SlepcSession::getInstance(argc,argv);
27
28 cout << "\n";
29 cout << "=== EVP: Temporal spectra of the Orr-Sommerfeld eqn =\n";
30 cout << "=== with a matrix problem assembled by hand and \n";
31 cout << "=== eigenproblem solved with SLEPc sparse solver.\n";
32 cout << "\n";
33
34 // discretise with these many nodal points
35 const std::size_t nodes( 1001 );
36 // we'll solve as TWO second order problems
37 const std::size_t N( 2 * nodes );
38 // domain boundaries
39 const double left = -1.0;
40 const double right = 1.0;
41 // spatial step for a uniform mesh
42 const double d = ( right - left ) / ( nodes - 1 );
43
44 // matrices for the EVP, initialised with zeroes
47
48 // streamwise wavenumber and Reynolds number
49 const double alpha ( 1.02 );
50 const double Re ( 5772.2 );
51 const D_complex I( 0.0, 1.0 );
52
53 // boundary conditions at the left boundary
54 a( 0, 0 ) = 1.0; // phi( left ) = 0
55 a( 1, 0 ) = -1.5 / d; // phi'( left ) = 0
56 a( 1, 2 ) = 2.0 / d;
57 a( 1, 4 ) = -0.5 / d;
58 // fill the interior nodes
59 for ( std::size_t i = 1; i <= nodes - 2; ++i )
60 {
61 // position in the channel
62 const double y = left + i * d;
63 // Poiseuille flow profile
64 const double U = ( 1.0 - y * y );
65 const double Udd = -2.0;
66
67 // the first quation at the i'th nodal point
68 std::size_t row = 2 * i;
69 a( row, row ) = -2.0 / ( d * d ) - alpha * alpha;
70 a( row, row - 2 ) = 1.0 / ( d * d );
71 a( row, row + 2 ) = 1.0 / ( d * d );
72 a( row, row + 1 ) = -1.0;
73
74 row += 1;
75 // the second equation at the i'th nodal point
76 a( row, row ) = -2.0 / ( d * d ) - alpha * alpha - I * alpha * Re * U;
77 a( row, row - 2 ) = 1.0 / ( d * d );
78 a( row, row + 2 ) = 1.0 / ( d * d );
79 a( row, row - 1 ) = I * alpha * Re * Udd;
80
81 b( row, row ) = - I * alpha * Re;
82 }
83 // boundary conditions at right boundary
84 a( N - 2, N - 2 ) = 1.5 / d;
85 a( N - 2, N - 4 ) = -2.0 / d;
86 a( N - 2, N - 6 ) = 0.5 / d; // psi'( right ) = 0
87 a( N - 1, N - 2 ) = 1.0; // psi( right ) = 0
88
89 /* Note: current KSP configuration uses an LU preconditioner and MUMPS
90 which doesn't mind zeros on the diagonal of a. */
91
92
93 // a vector for storing the eigenvalues
95 SparseLinearEigenSystem<D_complex> system( &a, &b );
96 system.set_target(D_complex(0.2,0.0));
97 system.set_nev(4);
98 system.set_order( "EPS_TARGET_MAGNITUDE" );
99
100 try
101 {
102 system.eigensolve();
103 }
104 catch (const std::runtime_error &error )
105 {
106 cout << " \033[1;31;48m * FAILED THROUGH EXCEPTION BEING RAISED \033[0m\n";
107 return 1;
108 }
109 // tag any eigenvalues with imaginary part > -0.1
110 system.set_shift( D_complex( 0.0, -0.1 ) );
111 system.tag_eigenvalues_upper( + 1 );
112 lambdas = system.get_tagged_eigenvalues();
113 lambdas.dump();
114 double min_growth_rate( lambdas[ 0 ].imag() );
115 // make sure we have a near neutral mode
116 const double tol = 1.e-3;
117
118 std::string dirname("./DATA");
119 mkdir( dirname.c_str(), S_IRWXU );
120
121 TrackerFile spectrum( "./DATA/spectrum.dat" );
122 spectrum.push_ptr( &lambdas, "evs" );
123 spectrum.update();
124
125 // eigenfunctions
126 DenseMatrix<D_complex> eigenvectors;
127 eigenvectors = system.get_tagged_eigenvectors();
128 DenseVector<double> ynodes = Utility::uniform_node_vector(left,right,nodes);
129 OneD_Node_Mesh<D_complex> mesh( ynodes, 4 );
130 // non-zero eigenvalue list => dump index 0 mode
131 if ( lambdas.nelts() > 0 ) {
132 int index(0);
133 for ( unsigned i = 0; i < nodes; ++i ) {
134 mesh(i,0) = eigenvectors(index,2*i+0); //phi_i
135 mesh(i,1) = eigenvectors(index,2*i+1); //psi_i
136 }
137 for ( unsigned i = 1; i < nodes-1; ++i ) {
138 mesh(i,2) = (mesh(i+1,0)-mesh(i-1,0))/(2*d); //u_i=phi'
139 mesh(i,3) = -I*alpha*mesh(i,0); //v_i=-i*alpha*phi
140 }
141 }
142 mesh.normalise(0);
143 mesh.dump_gnu("./DATA/eigenmode.dat");
144
145 if ( std::abs( min_growth_rate ) < tol )
146 {
147 cout << "\033[1;32;48m * PASSED \033[0m\n";
148 return 0;
149 }
150
151 cout << "\033[1;31;48m * FAILED \033[0m\n";
152 cout << " Final error = " << min_growth_rate << "\n";
153 return 1;
154
155}
int main()
Definition: ArcCircle.cpp:39
@ U
Definition: BVPKarman.cpp:20
A shorter bundled include file for ODE_BVP and PDE_IBVP codes.
Specification of the sparse linear eigensystem class.
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
std::size_t nelts() const
Get the number of elements in the vector Since the vector is dense, the number of elements is the siz...
Definition: DenseVector.h:335
void dump() const
Dump to std::cout.
Definition: DenseVector.cpp:64
A one dimensional mesh utility object.
void normalise(const std::size_t &var)
Normalise all data in the mesh based on one variable.
void dump_gnu(std::string filename, int precision=10) const
A simple method for dumping data to a file for gnuplot.
A matrix class that constructs a SPARSE matrix as a row major std::vector of SparseVectors.
Definition: SparseMatrix.h:31
void push_ptr(double *scalar, std::string desc="")
Definition: TrackerFile.cpp:27
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

© 2012

R.E. Hewitt