CppNoddy  0.92
Loading...
Searching...
No Matches
EVPHarmonicComplex_lapack.cpp
Go to the documentation of this file.
1/// \file EVPHarmonicComplex_lapack.cpp
2/// \ingroup Tests
3/// \ingroup EVP
4/// Solves the harmonic equation
5/// \f[ f''(z) + \lambda f(z) = 0 \f]
6/// as an eigenvalue problem for \f$ \lambda \f$ over a path in the
7/// complex plane with homogeneous boundary conditions for \f$ f(z) \f$, returning
8/// any eigenvalue(s) with absolute value less than 10. The resulting
9/// eigenvalues should approach \f$ m^2 \pi^2 \f$ as \f$n \to \infty \f$ with
10/// \f$ O(\Delta^2)\f$ corrections where \f$ \Delta = 1/(n-1) \f$ and \f$ n \f$ is the number
11/// of nodal points in the FD representation.
12/// The complex path is parametrised by a real parameter "x" and a 2nd order
13/// central difference representation is used.
14/// The matrix problem is solved for all eigenvalues within a specified distance
15/// of the origin of the comlplex plane by calling the LAPACK generalised eigenvalue routine.
16
17#include <Utility.h>
18#include <EVP_bundle.h>
19
20namespace CppNoddy
21{
22 namespace Example
23 {
24 const D_complex eye(0.,1.0);
25 // how far to deform the path into the complex plane
26 const double delta(0.5);
27
28 // functions that define the complex path z=z(x)
29 D_complex z( double x ) {
30 return x + eye*delta*x*(1-x);
31 }
32 // derivative of the path w.r.t. parameter x
33 D_complex zx( double x ) {
34 return 1.0 + eye*delta*(1-2.*x);
35 }
36 // 2nd derivative of the path w.r.t. parameter x
37 D_complex zxx( double x ) {
38 return -eye*2.*delta;
39 }
40 }
41}
42
43using namespace CppNoddy;
44using namespace std;
45
46int main()
47{
48 cout << "\n";
49 cout << "=== EVP: Harmonic equation solved using LAPACK =====\n";
50 cout << "=== with a manually assembled matrix problem.\n";
51 cout << "=== The problem is solved along a path in the complex\n";
52 cout << "=== plane, deformed away from the real axis.\n";
53 cout << "\n";
54
55 cout.precision( 12 );
56 cout << " Number of nodal points : Leading eigenvalue error : Total CPU time taken (ms) \n";
57 bool failed = false;
58 size_t N = 4;
59 // a vector for the eigenvalues
61 DenseMatrix<D_complex> eigenvectors;
62
63 Timer timer;
64 for ( int i = 2; i < 11; ++i )
65 {
66 N = ( size_t ) ( std::pow( 2., i ) );
67 const double delta = 1. / ( N - 1 );
68 const double delta2 = delta * delta;
69 // matrix problem
70 DenseMatrix<D_complex> a( N, N, 0.0 );
71 DenseMatrix<D_complex> b( N, N, 0.0 );
72 // boundary conditions at f(0) = 0
73 a( 0, 0 ) = 1.0;
74 a( 0, 1 ) = 0.0;
75 for ( unsigned j = 1; j < N-1; ++j ) {
76 // Finite difference representation of f''(x)
77 double x = j*delta;
78 a( j, j-1 ) = (1.0/pow(Example::zx(x),2.0))/delta2 + (Example::zxx(x)/pow(Example::zx(x),3.0))/(2*delta);
79 a( j, j) = -(2.0/pow(Example::zx(x),2.0))/delta2;
80 a( j, j+1 ) = (1.0/pow(Example::zx(x),2.0))/delta2 - (Example::zxx(x)/pow(Example::zx(x),3.0))/(2*delta);
81
82 // not a generalised problem - but we'll apply that routine anyway
83 b( j, j ) = -1.0;
84 }
85 // boundary conditions at f(1) = 0
86 a( N - 1, N - 1 ) = 1.0;
87 a( N - 1, N - 2 ) = 0.0;
88 // a vector for the eigenvectors - although we won't use them
89 DenseLinearEigenSystem<D_complex> system( &a, &b );
90 system.set_calc_eigenvectors( true );
91
92 timer.start();
93 try
94 {
95 system.eigensolve();
96 } catch (const std::runtime_error &error ) {
97 cout << " \033[1;31;48m * FAILED THROUGH EXCEPTION BEING RAISED \033[0m\n";
98 return 1;
99 }
100
101 system.tag_eigenvalues_disc( + 1, 10. );
102 lambdas = system.get_tagged_eigenvalues();
103
104 eigenvectors = system.get_tagged_eigenvectors();
105
106 cout << " " << N << " : " << lambdas[ 0 ].real() - M_PI * M_PI << " +i " << lambdas[0].imag()
107 << " : " << timer.get_time() << "\n";
108 timer.stop();
109 }
110
111 // real parameterisation of complex path
112 DenseVector<double> xNodes( Utility::uniform_node_vector( 0.0, 1.0, N ) );
113 // complex path
114 DenseVector<D_complex> zNodes( N, D_complex(0.0,0.0) );
115 // mesh of complex data along a complex path
116 OneD_Node_Mesh<D_complex, D_complex> mesh( zNodes, 1 );
117 int index(0); // first and only eigenvalue returned
118 for ( unsigned j = 0; j < N; ++j ) {
119 // store the nodes in the complex plane
120 mesh.coord(j) = Example::z(xNodes[j]);
121 mesh(j,0) = eigenvectors(index,j+0); //f_j
122 }
123 // write the complex solution on the complex path
124 mesh.dump_gnu("/DATA/complexMesh.dat");
125 const double tol = 1.e-4;
126 if ( abs( lambdas[ 0 ].real() - M_PI * M_PI ) > tol )
127 failed = true;
128
129 if ( failed )
130 {
131 cout << "\033[1;31;48m * FAILED \033[0m\n";
132 cout << " Final error = " << abs( lambdas[ 0 ].real() - M_PI * M_PI ) << "\n";
133 return 1;
134 }
135
136 cout << "\033[1;32;48m * PASSED \033[0m\n";
137 return 0;
138}
139
A shorter bundled include file for ODE_EVP and general eigenvalue problems.
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.
Definition: DenseMatrix.h:25
An DenseVector class – a dense vector object.
Definition: DenseVector.h:34
void set_calc_eigenvectors(bool flag)
Compute the eigenvectors in any eigenvalue computation.
A one dimensional mesh utility object.
const _Xtype & coord(const std::size_t &node) const
Access a nodal position.
void dump_gnu(std::string filename, int precision=10) const
A simple method for dumping data to a file for gnuplot.
A simple CPU-clock-tick timer for timing metods.
Definition: Timer.h:19
double get_time() const
Return the time.
Definition: Timer.cpp:34
void start()
Start the timer & reset stored time to zero.
Definition: Timer.cpp:12
void stop()
Stop the clock & add the current time interval to the previously stored values ready for printing.
Definition: Timer.cpp:17
const double delta(0.5)
const D_complex eye(0., 1.0)
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