45#elif defined(V_EVEN_Y)
62 template <
typename _Type>
66 My_Mesh(
double left,
double right,
double bottom,
double top, std::size_t nz, std::size_t ny, std::size_t nv ) :
TwoD_Mapped_Node_Mesh<_Type>( left, right, bottom, top, nz, ny, nv )
105 double FnComp_X(
const double& x )
const
107 return BX + x - BX*exp(-(x -
this ->
m_left)/CX );
109 double FnComp_Xd(
const double& x )
const
111 return 1 + BX*exp(-(x -
this ->
m_left)/CX )/CX;
115 return - BX*exp(-(x -
this ->
m_left)/CX )/(CX*CX);
118 double FnComp_Y(
const double& y )
const
120 return BY + y - BY*exp(-(y -
this ->
m_bottom)/CY );
122 double FnComp_Yd(
const double& y )
const
124 return 1 + BY*exp(-(y -
this ->
m_bottom)/CY )/CY;
128 return - BY*exp(-(y -
this ->
m_bottom)/CY )/(CY*CY);
139int main(
int argc,
char *argv[] )
141 SlepcSession::getInstance(argc,argv);
144 cout <<
"=== EVP: Temporal spectra of the 2D Orr-Sommerfeld eqn =\n";
145 cout <<
"=== with a matrix problem assembled by hand using =\n";
146 cout <<
"=== the formulation of Tatsumi and Yoshimura (1990). =\n";
154 const double alpha ( 0.94 );
155 double Re ( 8200.0 );
159 const std::size_t NZ( 301 );
160 const std::size_t NY( 301 );
165 for ( std::size_t i = 0; i < NZ; ++i )
167 for ( std::size_t j = 0; j < NY; ++j )
169 double Z = base.
coord(i,j).first;
170 double Y = base.
coord(i,j).second;
171 double sum = 1.0 - Y*Y;
172 for ( std::size_t n = 0; n < 1000; ++n )
174 double C = (2*n+1)*M_PI/2.0;
175 double term = cos(C*Y)*(exp(C*(Z-A))+exp(-C*(Z+A)))/(1+exp(-2*C*A));
176 sum -= 4*std::pow(2./M_PI,3)*std::pow(-1.0,n)*term/std::pow(2*n+1,3);
185 const std::size_t N( 4*NZ*NY );
187 cout <<
"There are " << N <<
" degrees of freedom in this problem.\n";
203 std::size_t dof_per_i( 4*NY );
205 for ( std::size_t j = 0; j < NY; ++j )
207 const std::size_t i(0);
209 const std::size_t O( i*4*NY );
210 std::size_t k( j*4 );
212 double Z( base.
coord(i,j).first );
216 a( O+k+0, O+k + v ) = 1.0;
218 a( O+k+1, O+k + w ) = 1.0;
220 a( O+k+2, O+k + dof_per_i + v ) = -5.0*(eye/(alpha*Re))*KZd*KZd/(DZ*DZ)
221 + 4.0*(eye/(alpha*Re))*KZdd/(2.0*DZ);
222 a( O+k+2, O+k + 2*dof_per_i + v ) = 4.0*(eye/(alpha*Re))*KZd*KZd/(DZ*DZ)
223 - 1.0*(eye/(alpha*Re))*KZdd/(2.0*DZ);
224 a( O+k+2, O+k + 3*dof_per_i + v ) = -1.0*(eye/(alpha*Re))*KZd*KZd/(DZ*DZ);
225 a( O+k+2, O+k + F ) = -1.0;
227 a( O+k+3, O+k + dof_per_i + w ) = 10.0*(eye/(alpha*Re))*KZd*KZd/(3*DZ*DZ);
228 a( O+k+3, O+k + 2*dof_per_i + w ) = -1.0*(eye/(alpha*Re))*KZd*KZd/(3*DZ*DZ);
229 a( O+k+3, O+k + G ) = -1.0;
232 for ( std::size_t i = 1; i <= NZ - 2; ++i )
235 const std::size_t j(0);
237 std::size_t O( i*4*NY );
238 std::size_t k( j*4 );
240 double Y( base.
coord(i,j).second );
244 a( O+k+0, O+k + v ) = 1.0;
246 a( O+k+1, O+k + w ) = 1.0;
248 a( O+k+2, O+k + 4 + v ) = 10.0*(eye/(alpha*Re))*KYd*KYd/(3*DY*DY);
249 a( O+k+2, O+k + 8 + v ) = -1.0*(eye/(alpha*Re))*KYd*KYd/(3*DY*DY);
250 a( O+k+2, O+k + F ) = -1.0;
252 a( O+k+3, O+k + 4 + w ) = -5.0*(eye/(alpha*Re))*KYd*KYd/(DY*DY)
253 + 4.0*(eye/(alpha*Re))*KYdd/(2.0*DY);
254 a( O+k+3, O+k + 8 + w ) = 4.0*(eye/(alpha*Re))*KYd*KYd/(DY*DY)
255 - 1.0*(eye/(alpha*Re))*KYdd/(2.0*DY);
256 a( O+k+3, O+k + 12 + w ) = -1.0*(eye/(alpha*Re))*KYd*KYd/(DY*DY);
257 a( O+k+3, O+k + G ) = -1.0;
259 for ( std::size_t j = 1; j < NY-1; ++j )
262 double Z( base.
coord(i,j).first );
265 double Y( base.
coord(i,j).second );
269 double Uy = (base(i,j+1,0)-base(i,j-1,0))*KYd/(2*DY);
270 double Uz = (base(i+1,j,0)-base(i-1,j,0))*KZd/(2*DZ);
271 double Uyy = (base(i,j+1,0)-2*base(i,j,0)+base(i,j-1,0))*KYd*KYd/(DY*DY)
272 + (base(i,j+1,0)-base(i,j-1,0))*KYdd/(2*DY);
273 double Uzz = (base(i+1,j,0)-2*base(i,j,0)+base(i-1,j,0))*KZd*KZd/(DZ*DZ)
274 + (base(i+1,j,0)-base(i-1,j,0))*KZdd/(2*DZ);
275 double Uyz = (base(i+1,j+1,0)-base(i+1,j-1,0)
276 - base(i-1,j+1,0)+base(i-1,j-1,0))*KYd*KZd/(4*DY*DZ);
278 std::size_t O( i*4*NY );
279 std::size_t k( j*4 );
284 a( O+k+0, O+k + v ) = (eye/(alpha*Re))*( - 2.0*KYd*KYd/(DY*DY)
285 - 2.0*KZd*KZd/(DZ*DZ)
286 - alpha*alpha ) + base(i,j,0);
288 a( O+k+0, O+k + dof_per_i + v ) = (eye/(alpha*Re))*KZd*KZd/(DZ*DZ)
289 + (eye/(alpha*Re))*KZdd/(2.0*DZ);
291 a( O+k+0, O+k - dof_per_i + v ) = (eye/(alpha*Re))*KZd*KZd/(DZ*DZ)
292 - (eye/(alpha*Re))*KZdd/(2.0*DZ);
294 a( O+k+0, O+k + 4 + v ) = (eye/(alpha*Re))*KYd*KYd/(DY*DY)
295 + (eye/(alpha*Re))*KYdd/(2.0*DY);
297 a( O+k+0, O+k - 4 + v ) = (eye/(alpha*Re))*KYd*KYd/(DY*DY)
298 - (eye/(alpha*Re))*KYdd/(2.0*DY);
300 a( O+k+0, O+k + F ) = -1.0;
302 b( O+k+0, O+k + v ) = 1.0;
307 a( O+k+1, O+k + w ) = (eye/(alpha*Re))*( - 2.0*KYd*KYd/(DY*DY)
308 - 2.0*KZd*KZd/(DZ*DZ)
309 - alpha*alpha ) + base(i,j,0);
311 a( O+k+1, O+k + dof_per_i + w ) = (eye/(alpha*Re))*KZd*KZd/(DZ*DZ)
312 + (eye/(alpha*Re))*KZdd/(2.0*DZ);
314 a( O+k+1, O+k - dof_per_i + w ) = (eye/(alpha*Re))*KZd*KZd/(DZ*DZ)
315 - (eye/(alpha*Re))*KZdd/(2.0*DZ);
317 a( O+k+1, O+k + 4 + w ) = (eye/(alpha*Re))*KYd*KYd/(DY*DY)
318 + (eye/(alpha*Re))*KYdd/(2.0*DY);
320 a( O+k+1, O+k - 4 + w ) = (eye/(alpha*Re))*KYd*KYd/(DY*DY)
321 - (eye/(alpha*Re))*KYdd/(2.0*DY);
323 a( O+k+1, O+k + G ) = -1.0;
325 b( O+k+1, O+k + w ) = 1.0;
330 a( O+k+2, O+k + F ) = -2.0*KYd*KYd/(DY*DY) - alpha*alpha;
332 a( O+k+2, O+k + 4 + F ) = 1.0*KYd*KYd/(DY*DY) + KYdd/(2.0*DY);
334 a( O+k+2, O+k - 4 + F ) = 1.0*KYd*KYd/(DY*DY) - KYdd/(2.0*DY);
337 a( O+k+2, O+k + dof_per_i + 4 + G ) = 0.25*KYd*KZd/(DY*DZ);
339 a( O+k+2, O+k + dof_per_i - 4 + G ) = -0.25*KYd*KZd/(DY*DZ);
341 a( O+k+2, O+k - dof_per_i - 4 + G ) = 0.25*KYd*KZd/(DY*DZ);
343 a( O+k+2, O+k - dof_per_i + 4 + G ) = -0.25*KYd*KZd/(DY*DZ);
346 a( O+k+2, O+k + v ) = -2.0*Uyy;
348 a( O+k+2, O+k + 4 + v ) = -2.0*Uy*KYd/(2.0*DY);
350 a( O+k+2, O+k - 4 + v ) = +2.0*Uy*KYd/(2.0*DY);
353 a( O+k+2, O+k + w ) = -2.0*Uyz;
355 a( O+k+2, O+k + 4 + w ) = -2.0*Uz*KYd/(2.0*DY);
357 a( O+k+2, O+k - 4 + w ) = +2.0*Uz*KYd/(2.0*DY);
363 a( O+k+3, O+k + G ) = -2.0*KZd*KZd/(DZ*DZ) - alpha*alpha;
365 a( O+k+3, O+k + dof_per_i + G ) = 1.0*KZd*KZd/(DZ*DZ) + KZdd/(2.0*DZ);
367 a( O+k+3, O+k - dof_per_i + G ) = 1.0*KZd*KZd/(DZ*DZ) - KZdd/(2.0*DZ);
370 a( O+k+3, O+k + dof_per_i + 4 + F ) = 0.25*KYd*KZd/(DY*DZ);
372 a( O+k+3, O+k + dof_per_i - 4 + F ) = -0.25*KYd*KZd/(DY*DZ);
374 a( O+k+3, O+k - dof_per_i - 4 + F ) = 0.25*KYd*KZd/(DY*DZ);
376 a( O+k+3, O+k - dof_per_i + 4 + F ) = -0.25*KYd*KZd/(DY*DZ);
379 a( O+k+3, O+k + v ) = -2.0*Uyz;
381 a( O+k+3, O+k + dof_per_i + v ) = -2.0*Uy*KZd/(2.0*DZ);
383 a( O+k+3, O+k - dof_per_i + v ) = +2.0*Uy*KZd/(2.0*DZ);
386 a( O+k+3, O+k + w ) = -2.0*Uzz;
388 a( O+k+3, O+k + dof_per_i + w ) = -2.0*Uz*KZd/(2.0*DZ);
390 a( O+k+3, O+k - dof_per_i + w ) = +2.0*Uz*KZd/(2.0*DZ);
395 const std::size_t j(NY-1);
396 std::size_t O( i*4*NY );
397 const std::size_t k( j*4 );
399 double Y( base.
coord(i,j).second );
405 a( O+k+0, O+k + v ) = 3.0*KYd/(2.0*DY);
406 a( O+k+0, O+k - 4 + v ) = -4.0*KYd/(2.0*DY);
407 a( O+k+0, O+k - 8 + v ) = 1.0*KYd/(2.0*DY);
409 a( O+k+2, O+k + F ) = 3.0*KYd/(2.0*DY);
410 a( O+k+2, O+k - 4 + F ) = -4.0*KYd/(2.0*DY);
411 a( O+k+2, O+k - 8 + F ) = 1.0*KYd/(2.0*DY);
412#elif defined(V_ODD_Y)
414 a( O+k+0, O+k + v ) = 1.0;
416 a( O+k+2, O+k + F ) = 1.0;
421 a( O+k+1, O+k + w ) = 3.0*KYd/(2.0*DY);
422 a( O+k+1, O+k - 4 + w ) = -4.0*KYd/(2.0*DY);
423 a( O+k+1, O+k - 8 + w ) = 1.0*KYd/(2.0*DY);
425 a( O+k+3, O+k + G ) = 3.0*KYd/(2.0*DY);
426 a( O+k+3, O+k - 4 + G ) = -4.0*KYd/(2.0*DY);
427 a( O+k+3, O+k - 8 + G ) = 1.0*KYd/(2.0*DY);
428#elif defined(W_ODD_Y)
430 a( O+k+1, O+k + w ) = 1.0;
432 a( O+k+3, O+k + G ) = 1.0;
437 for ( std::size_t j = 0; j < NY; ++j )
440 const std::size_t i(NZ-1);
442 const std::size_t O( i*4*NY );
443 std::size_t k( j*4 );
445 double Z( base.
coord(i,j).first );
450 a( O+k+0, O+k + v ) = 3.0*KZd/(2.0*DZ);
451 a( O+k+0, O+k - dof_per_i + v ) = -4.0*KZd/(2.0*DZ);
452 a( O+k+0, O+k - 2*dof_per_i + v ) = 1.0*KZd/(2.0*DZ);
454 a( O+k+2, O+k + F ) = 3.0*KZd/(2.0*DZ);
455 a( O+k+2, O+k - dof_per_i + F ) = -4.0*KZd/(2.0*DZ);
456 a( O+k+2, O+k - 2*dof_per_i + F ) = 1.0*KZd/(2.0*DZ);
457#elif defined(V_ODD_Z)
459 a( O+k+0, O+k + v ) = 1.0;
461 a( O+k+2, O+k + F ) = 1.0;
466 a( O+k+1, O+k + w ) = 3.0*KZd/(2.0*DZ);
467 a( O+k+1, O+k - dof_per_i + w ) = -4.0*KZd/(2.0*DZ);
468 a( O+k+1, O+k - 2*dof_per_i + w ) = 1.0*KZd/(2.0*DZ);
470 a( O+k+3, O+k + G ) = 3.0*KZd/(2.0*DZ);
471 a( O+k+3, O+k - dof_per_i + G ) = -4.0*KZd/(2.0*DZ);
472 a( O+k+3, O+k - 2*dof_per_i + G ) = 1.0*KZd/(2.0*DZ);
473#elif defined(W_ODD_Z)
475 a( O+k+1, O+k + w ) = 1.0;
477 a( O+k+3, O+k + G ) = 1.0;
487 SparseLinearEigenSystem<D_complex> system( &a, &b );
489 system.set_region(0.0, 1.0, -1.0, 1.0);
490 system.set_target(
D_complex( 0.244, 0.0 ) );
491 system.set_order(
"EPS_TARGET_IMAGINARY");
498 TrackerFile spectrum(
"./DATA/spectrum_disc_2d.dat" );
506 for ( std::size_t n = 0; n < ev_c.
size(); ++n )
508 for ( std::size_t i = 0; i < NZ; ++i )
510 for ( std::size_t j = 0; j < NY; ++j )
512 eigfn(i,j,v) = vec_mtx(n, i*4*NY + 4*j + v );
513 eigfn(i,j,w) = vec_mtx(n, i*4*NY + 4*j + w );
514 eigfn(i,j,F) = vec_mtx(n, i*4*NY + 4*j + F );
515 eigfn(i,j,G) = vec_mtx(n, i*4*NY + 4*j + G );
521 if ( std::abs( ev_c[0].imag() ) < 1.e-4 )
523 cout <<
"\033[1;32;48m * PASSED \033[0m\n";
527 cout <<
"\033[1;31;48m * FAILED \033[0m\n";
528 cout <<
" Final error = " << ev_c[0].imag() <<
"\n";
Specification of the sparse linear eigensystem class.
A matrix class that constructs a SPARSE matrix as an STL Vector of SparseVectors, inheriting from Mat...
A class that can be passed pointers to scalar/vector/mesh objects, then their contents are written to...
A specification for a two dimensional mapped mesh object.
A specification for a two dimensional mesh object.
A spec for a collection of utility functions.
A linear Nth-order generalised eigensystem class.
void tag_eigenvalues_disc(const int &val, const double &radius)
Tag those eigenvalues that are within a disc centred at a point in the complex plane.
DenseVector< D_complex > get_tagged_eigenvalues() const
Get the the tagged eigenvalues.
void eigensolve()
Solve the matrix linear eigensystem.
DenseMatrix< D_complex > get_tagged_eigenvectors() const
Get the the tagged eigenvectors.
A matrix class that constructs a DENSE matrix as a row major std::vector of DenseVectors.
An DenseVector class – a dense vector object.
void dump() const
Dump to std::cout.
std::size_t size() const
A pass-thru definition to get the size of the vector.
A matrix class that constructs a SPARSE matrix as a row major std::vector of SparseVectors.
void push_ptr(double *scalar, std::string desc="")
A two dimensional (mapped) mesh utility object.
std::pair< double, double > get_comp_step_sizes() const
void init_mapping()
Sometimes a useful mapping is painful to invert analytically.
void dump_gnu(std::string filename) const
A simple method for dumping data to a file for gnuplot surface plotting.
std::pair< double, double > coord(const std::size_t nodex, const std::size_t nodey) const
Access the physical nodal position - as a pair.
double FnComp_Ydd(const double &y) const
Mapping function that provides the second derivative of the computational Y coordinate as a function ...
My_Mesh(double left, double right, double bottom, double top, std::size_t nz, std::size_t ny, std::size_t nv)
double FnComp_Xd(const double &x) const
Mapping function that provides the first derivative of the computational m_X coordinate as a function...
double FnComp_X(const double &x) const
Mapping function that provides a computational X coordinate from a physical coordinate.
double FnComp_Xdd(const double &x) const
Mapping function that provides the second derivative of the computational X coordinate as a function ...
double FnComp_Yd(const double &y) const
Mapping function that provides the first derivative of the computational Y coordinate as a function o...
double FnComp_Y(const double &y) const
Mapping function that provides the computational Y coordinate as a function of the physical coordinat...
std::string stringify(const int &val)
Return an integer value as a string - useful for file naming.
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.