CppNoddy  0.92
Loading...
Searching...
No Matches
FT.cpp
Go to the documentation of this file.
1/// \file FT.cpp
2/// An implementation for a collection of Fourier methods
3
4#include <DenseVector.h>
5#include <TwoD_Node_Mesh.h>
6#include <Types.h>
7#include <OneD_Node_Mesh.h>
8#include <TwoD_Node_Mesh.h>
9#include <FT.h>
10
11
12namespace CppNoddy {
13 namespace FT {
14
16 OneD_Node_Mesh<D_complex> ft_shifted( ft );
17 std::size_t N = ft.get_nnodes();
18 for ( std::size_t i = 0; i < N/2; ++i ) {
19 for ( std::size_t var = 0; var < ft.get_nvars(); ++var ) {
20 // first half of shifted output
21 ft_shifted( i, var ) = ft( N/2+i, var );
22 // second half of shifted output
23 ft_shifted( N/2 + i, var ) = ft( i, var );
24 }
25 ft_shifted.coord( i ) = -ft.coord( N/2 - i );
26 ft_shifted.coord( N/2 + i ) = ft.coord( i );
27 }
28 return ft_shifted;
29 }
30
32 OneD_Node_Mesh<D_complex> ft_ishifted( ft );
33 double df = ft.coord(1)-ft.coord(0);
34 std::size_t N = ft.get_nnodes();
35 for ( std::size_t i = 0; i < N/2; ++i ) {
36 for ( std::size_t var = 0; var < ft.get_nvars(); ++var ) {
37 // first half of shifted output
38 ft_ishifted( i, var ) = ft( N/2 + i, var );
39 // second half of shifted output
40 ft_ishifted( N/2 + i, var ) = ft( i, var );
41 }
42 ft_ishifted.coord( i ) = ft.coord( N/2 + i );
43 ft_ishifted.coord( N/2 + i ) = ft.coord(N-1) + i*df;
44 }
45 return ft_ishifted;
46 }
47
49 return shift(dft(f));
50 }
51
53 // assume that we idft each ft(.,node)
54 unsigned ny = f.get_nnodes().second;
55 unsigned nx = f.get_nnodes().first;
56 TwoD_Node_Mesh<D_complex> FTsoln( f.xnodes(), f.ynodes(), f.get_nvars());
57 for ( unsigned jy = 0; jy < ny; ++jy ) {
58 OneD_Node_Mesh<D_complex> mesh = f.get_xsection_at_ynode(jy);
60 for ( unsigned jx = 0; jx < nx; ++jx ) {
61 FTsoln.xcoord(jx)=ftmesh.coord(jx);
62 FTsoln.set_nodes_vars( jx, jy, ftmesh.get_nodes_vars(jx) );
63 }
64 }
65 return FTsoln;
66 }
67
69 return idft(ishift(ft),origin);
70 }
71
73 // assume that we idft each ft(.,node)
74 unsigned ny = ft.get_nnodes().second;
75 unsigned nx = ft.get_nnodes().first;
76 TwoD_Node_Mesh<D_complex> soln( ft.xnodes(), ft.ynodes(), ft.get_nvars());
77 for ( unsigned jy = 0; jy < ny; ++jy ) {
80 for ( unsigned jx = 0; jx < nx; ++jx ) {
81 soln.xcoord(jx)=mesh.coord(jx);
82 soln.set_nodes_vars( jx, jy, mesh.get_nodes_vars(jx) );
83 }
84 }
85 return soln;
86 }
87
89 const D_complex I(0.0,1.0); // imaginary unit
90 // number of samples in the signal
91 std::size_t N = f.get_nnodes();
92 // time step in the signal (has to be constant)
93 double dt = f.coord(1)-f.coord(0);
94 // sample frequency (rad) is related to inverse of "time" step
95 double fs = 2*M_PI/dt;
96 // frequency step between frequency nodes
97 // - largest frequency is (N-1)*df=(N-1)*fs/N
98 double df = fs/N;
99 // container to return the Fourier spectrum
100 OneD_Node_Mesh<D_complex> ft( f.nodes(), f.get_nvars() );
101 //
102 const double Wn = 2*M_PI/N;
103 // slow FT
104 for ( std::size_t k = 0; k < N; ++k ) {
105 // set the frequency
106 ft.coord(k) = k*df; // 0,df,...,(N-1)*df
107 //
108 //
109 // t = n*dt
110 // omega = k*df
111 // df = (2*pi/dt)/N
112 //
113 // variables are all initialised to zero
114 DenseVector<D_complex> vars( f.get_nvars(), 0.0 );
115 for ( std::size_t n = 0; n < N; ++n ) {
116 vars += f.get_nodes_vars(n)*exp(-I*Wn*double(k*n));
117 }
118 // multiply by "dt" to make this correlate with analytical
119 // results from the FT integral
120 ft.set_nodes_vars(k,vars*dt);
121 }
122 return ft;
123 }
124
125
126 // OneD_Node_Mesh<D_complex> idft( const OneD_Node_Mesh<D_complex>& ft, double origin ) {
127 // const D_complex I(0.0,1.0); // imaginary unit
128 // // number of samples in the signal
129 // std::size_t N = ft.get_nnodes();
130 // // time step in the signal (has to be constant)
131 // double df = ft.coord(1)-ft.coord(0);
132 // // sample frequency
133 // double fs = N*df;
134 // // time step in output signal
135 // double dt = 2*M_PI/fs;
136 // // containter to return the "time series" in
137 // OneD_Node_Mesh<D_complex> f( ft );
138 // for ( std::size_t n = 0; n < N; ++n ) {
139 // f.coord(n) = origin + n*dt;
140 // for ( std::size_t var = 0; var < f.get_nvars(); ++var ) {
141 // f(n,var) = 0.0;
142 // for ( std::size_t k = 0; k < N; ++k ) {
143 // double angle = 2*M_PI*k*n/N;
144 // f(n,var) += ft(k,var)*exp(I*angle);
145 // }
146 // // the dt factor is for consistency with continuous FT integral
147 // f(n,var) /= (N*dt);
148 // }
149 // }
150 // return f;
151 // }
152
154 const D_complex I(0.0,1.0); // imaginary unit
155 // number of "frequencies" in the data
156 std::size_t N = ft.get_nnodes();
157 // (uniform) frequency step in the data
158 double df = ft.coord(1)-ft.coord(0);
159 // sample frequency
160 double fs = N*df;
161 // time step in output signal
162 double dt = 2*M_PI/fs;
163 // NOTE: dt*df = 2*pi/N
164 //
165 // containter to return the "time series" in
167 //
168 const double Wn = 2*M_PI/N;
169 // number of variables at each time/frequency
170 const std::size_t nVars( ft.get_nvars() );
171 // slow inverse FT
172 for ( std::size_t n = 0; n < N; ++n ) {
173 // set the coordinate/time using the offset passed to this method
174 f.coord(n) = origin + n*dt;
175 // invert for all variables in the mesh at the same time
176 DenseVector<D_complex> vars( nVars, 0.0 );
177 for ( std::size_t k = 0; k < N; ++k ) {
178 vars += ft.get_nodes_vars(k)*exp(+I*Wn*double(k*n));
179 }
180 // the dt factor is for consistency with continuous FT integral
181 f.set_nodes_vars(n,vars/(N*dt));
182 }
183 return f;
184 }
185
186
187
188
189 } // end FT namespace
190
191} // end CppNoddy namespace
@ f
Definition: BVPBerman.cpp:15
Specification for a templated DenseVector class – a dense, dynamic, vector object.
A spec for a collection of Fourier methods that act on Noddy containers.
A specification for a one dimensional mesh object.
A specification for a two dimensional mesh object.
An DenseVector class – a dense vector object.
Definition: DenseVector.h:34
A one dimensional mesh utility object.
std::size_t get_nvars() const
DenseVector< _Type > get_nodes_vars(const std::size_t &node) const
Get the variables stored at A SPECIFIED node.
const _Xtype & coord(const std::size_t &node) const
Access a nodal position.
void set_nodes_vars(const std::size_t node, const DenseVector< _Type > &u)
Set the variables stored at A SPECIFIED node.
std::size_t get_nnodes() const
A two dimensional mesh utility object.
std::pair< std::size_t, std::size_t > get_nnodes() const
Get the number of nodes in the two directions of the 2D mesh.
const DenseVector< double > & xnodes() const
Access the vector of x-nodal positions.
std::size_t get_nvars() const
Get the number of variables that are stored at each node.
const DenseVector< double > & ynodes() const
Access the vector of y-nodal positions.
double & xcoord(const std::size_t nodex)
Access the x-nodal (first index) position.
OneD_Node_Mesh< _Type > get_xsection_at_ynode(const std::size_t nodey) const
Get a cross section of the 2D mesh at a specified (constant) y node.
void set_nodes_vars(const std::size_t nodex, const std::size_t nodey, const DenseVector< _Type > &U)
Set the variables stored at A SPECIFIED node.
OneD_Node_Mesh< D_complex > dft(const OneD_Node_Mesh< D_complex > &f)
(Slow) DFT of the real data (x_i,f_i), i = 0, ... N-1; N must be EVEN.
Definition: FT.cpp:88
OneD_Node_Mesh< D_complex > dft_with_shift(const OneD_Node_Mesh< D_complex > &f)
A wrapper that calls the 'dft' method above followed by the 'shift' method.
Definition: FT.cpp:48
OneD_Node_Mesh< D_complex > idft_with_ishift(const OneD_Node_Mesh< D_complex > &ft, double origin=0)
A wrapper that calls the 'ishift' method above followed by the 'idft' method.
Definition: FT.cpp:68
OneD_Node_Mesh< D_complex > shift(const OneD_Node_Mesh< D_complex > &ft)
Shift the frequency spectrum obtained from dft to give positive and negative freq.
Definition: FT.cpp:15
OneD_Node_Mesh< D_complex > ishift(const OneD_Node_Mesh< D_complex > &ft)
Invert the shif operation to recover a spectrum in the form that is expected by the idft routine.
Definition: FT.cpp:31
OneD_Node_Mesh< D_complex > idft(const OneD_Node_Mesh< D_complex > &ft, double origin=0)
(Slow) Inverse DFT of the complex data (omega_i,F_i), i = 0,...,N-1; N must be EVEN.
Definition: FT.cpp:153
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