NESSi  v1.0.2
The NonEquilibrium Systems Simulation Library
fourier.cpp
Go to the documentation of this file.
1 /*--------------------------------------------------
2  fourier.c
3  Martin Eckstein, Dec. 7, 2006
4 -----------------------------------------------------
5 PURPOSE: fourier transforms of complex functions */
6 #include "./fourier.hpp"
7 #include <cmath>
8 
9 namespace fourier{
10 
11 typedef std::complex<double> cplx;
12 
43 void get_dftcorr_cubic(double th,double *corfac,cplx *endcor)
44 {
45  double ai[4],ar[4],t;
46  double t2,t4,t6;
47  double cth,ctth,spth2,sth,sth4i,stth,th2,th4,tmth2,tth4i;
48  int j;
49 
50  if (fabs(th) < 5.0e-2) {
51  t=th;
52  t2=t*t;
53  t4=t2*t2;
54  t6=t4*t2;
55  *corfac=1.0-(11.0/720.0)*t4+(23.0/15120.0)*t6;
56  ar[0]=(-2.0/3.0)+t2/45.0+(103.0/15120.0)*t4-(169.0/226800.0)*t6;
57  ar[1]=(7.0/24.0)-(7.0/180.0)*t2+(5.0/3456.0)*t4-(7.0/259200.0)*t6;
58  ar[2]=(-1.0/6.0)+t2/45.0-(5.0/6048.0)*t4+t6/64800.0;
59  ar[3]=(1.0/24.0)-t2/180.0+(5.0/24192.0)*t4-t6/259200.0;
60  ai[0]=t*(2.0/45.0+(2.0/105.0)*t2-(8.0/2835.0)*t4+(86.0/467775.0)*t6);
61  ai[1]=t*(7.0/72.0-t2/168.0+(11.0/72576.0)*t4-(13.0/5987520.0)*t6);
62  ai[2]=t*(-7.0/90.0+t2/210.0-(11.0/90720.0)*t4+(13.0/7484400.0)*t6);
63  ai[3]=t*(7.0/360.0-t2/840.0+(11.0/362880.0)*t4-(13.0/29937600.0)*t6);
64  } else {
65  cth=cos(th);
66  sth=sin(th);
67  ctth=cth*cth-sth*sth;
68  stth=2.0e0*sth*cth;
69  th2=th*th;
70  th4=th2*th2;
71  tmth2=3.0e0-th2;
72  spth2=6.0e0+th2;
73  sth4i=1.0/(6.0e0*th4);
74  tth4i=2.0e0*sth4i;
75  *corfac=tth4i*spth2*(3.0e0-4.0e0*cth+ctth);
76  ar[0]=sth4i*(-42.0e0+5.0e0*th2+spth2*(8.0e0*cth-ctth));
77  ai[0]=sth4i*(th*(-12.0e0+6.0e0*th2)+spth2*stth);
78  ar[1]=sth4i*(14.0e0*tmth2-7.0e0*spth2*cth);
79  ai[1]=sth4i*(30.0e0*th-5.0e0*spth2*sth);
80  ar[2]=tth4i*(-4.0e0*tmth2+2.0e0*spth2*cth);
81  ai[2]=tth4i*(-12.0e0*th+2.0e0*spth2*sth);
82  ar[3]=sth4i*(2.0e0*tmth2-spth2*cth);
83  ai[3]=sth4i*(6.0e0*th-spth2*sth);
84  }
85  for(j=0;j<=3;j++) endcor[j]=cplx(ar[j],ai[j]);
86 }
117 void get_dftcorr_linear(double th,double *corfac,cplx *endcor)
118 {
119  double ai,ar;
120  double th2,th4,th6,cth,sth;
121 
122  if (fabs(th) < 5.0e-2) {
123  th2=th*th;
124  th4=th2*th2;
125  th6=th4*th2;
126  *corfac=1.0-(1.0/12.0)*th2+(1.0/360.0)*th4-(1.0/20160.0)*th6;
127  ar=-0.5+th2/24.0-(1.0/720.0)*th4+(1.0/40320.0)*th6;
128  ai=th*(1.0/6.0-(1.0/120.0)*th2+(1.0/5040.0)*th4-(1.0/362880.0)*th6);
129  } else {
130  cth=cos(th);
131  sth=sin(th);
132  th2=th*th;
133  *corfac=2.0*(1.0-cth)/th2;
134  ar=(cth-1.0)/th2;
135  ai=(th-sth)/th2;
136  }
137  endcor[0]=cplx(ar,ai);
138  endcor[1]=0;
139 }
140 
141 
182 void complex_dftcor_cubic(double w, double delta,double a,double b, cplx *endpts,cplx *endcor,double *corfac)
183 {
184  double ai[4],ar[4],arg,t;
185  double t2,t4,t6;
186  double cth,ctth,spth2,sth,sth4i,stth,th,th2,th4,tmth2,tth4i;
187  cplx expfac,cr,cl,cor,al;
188  int j;
189 
190  th=w*delta;
191  if (fabs(th) < 5.0e-2) {
192  t=th;
193  t2=t*t;
194  t4=t2*t2;
195  t6=t4*t2;
196  *corfac=1.0-(11.0/720.0)*t4+(23.0/15120.0)*t6;
197  ar[0]=(-2.0/3.0)+t2/45.0+(103.0/15120.0)*t4-(169.0/226800.0)*t6;
198  ar[1]=(7.0/24.0)-(7.0/180.0)*t2+(5.0/3456.0)*t4-(7.0/259200.0)*t6;
199  ar[2]=(-1.0/6.0)+t2/45.0-(5.0/6048.0)*t4+t6/64800.0;
200  ar[3]=(1.0/24.0)-t2/180.0+(5.0/24192.0)*t4-t6/259200.0;
201  ai[0]=t*(2.0/45.0+(2.0/105.0)*t2-(8.0/2835.0)*t4+(86.0/467775.0)*t6);
202  ai[1]=t*(7.0/72.0-t2/168.0+(11.0/72576.0)*t4-(13.0/5987520.0)*t6);
203  ai[2]=t*(-7.0/90.0+t2/210.0-(11.0/90720.0)*t4+(13.0/7484400.0)*t6);
204  ai[3]=t*(7.0/360.0-t2/840.0+(11.0/362880.0)*t4-(13.0/29937600.0)*t6);
205  } else {
206  cth=cos(th);
207  sth=sin(th);
208  ctth=cth*cth-sth*sth;
209  stth=2.0e0*sth*cth;
210  th2=th*th;
211  th4=th2*th2;
212  tmth2=3.0e0-th2;
213  spth2=6.0e0+th2;
214  sth4i=1.0/(6.0e0*th4);
215  tth4i=2.0e0*sth4i;
216  *corfac=tth4i*spth2*(3.0e0-4.0e0*cth+ctth);
217  ar[0]=sth4i*(-42.0e0+5.0e0*th2+spth2*(8.0e0*cth-ctth));
218  ai[0]=sth4i*(th*(-12.0e0+6.0e0*th2)+spth2*stth);
219  ar[1]=sth4i*(14.0e0*tmth2-7.0e0*spth2*cth);
220  ai[1]=sth4i*(30.0e0*th-5.0e0*spth2*sth);
221  ar[2]=tth4i*(-4.0e0*tmth2+2.0e0*spth2*cth);
222  ai[2]=tth4i*(-12.0e0*th+2.0e0*spth2*sth);
223  ar[3]=sth4i*(2.0e0*tmth2-spth2*cth);
224  ai[3]=sth4i*(6.0e0*th-spth2*sth);
225  }
226  cl=0;
227  for(j=0;j<=3;j++){
228  al=cplx(ar[j],ai[j]);
229  cor=endpts[j]*al;
230  cl+=cor;
231  }
232  cr=0;
233  for(j=0;j<=3;j++){
234  al=cplx(ar[j],-ai[j]);
235  cor=endpts[7-j]*al;
236  cr += cor;
237  }
238  arg=w*(b-a);
239  expfac=cplx(cos(arg),sin(arg));
240  cr *= expfac;
241  *endcor = cl+cr;
242 }
243 
283 void dft_cplx(double w,int n,double a,double b,cplx *f,cplx &res,cplx &err)
284 {
285  /*same as fourier transform complex_ft_cubic, but
286  an approximate error is returned, given the difference between
287  complex_ft_cubic using m and (m+1)/2 points*/
288  double theta,delta,len,corfac,corfac2,arg;
289  cplx endpoints[8],endcor,endcor2,res2,expfac,z;
290  int j;
291 
292  len=b-a;
293  if(n<=16 || (n/2)*2!=n || len<=0.0) std::cerr << "n=" << n << " len= " << len << std::endl;
294  if(n<=16 || (n/2)*2!=n || len<=0.0) {std::cerr << "complex_ft_cubic_err: wrong input" << std::endl;abort();}
295  delta=len/((double) n);
296  theta=w*delta;
297  /*endcorrections using all points*/
298  /*store endpoints*/
299  for(j=0;j<=3;j++){
300  endpoints[j]=f[j];
301  endpoints[7-j]=f[n-j];
302  }
303  /*get corrections*/
304  complex_dftcor_cubic(w,delta,a,b,endpoints,&endcor,&corfac);
305  /*endcorrections using every second points*/
306  /*store endpoints*/
307  for(j=0;j<=3;j++){
308  endpoints[j]=f[2*j];
309  endpoints[7-j]=f[n-2*j];
310  }
311  /*get corrections*/
312  complex_dftcor_cubic(w,2.0*delta,a,b,endpoints,&endcor2,&corfac2);
313  /*compute discrete fourier transform
314  (naive version, without FFT)*/
315  /*first using every second point*/
316  res2=0;
317  for(j=0;j<=n;j+=2){
318  arg=((double) j)*theta;
319  expfac=cplx(cos(arg),sin(arg));
320  res2 += expfac*f[j];
321  }
322  /*using remaining points*/
323  res=res2;
324  for(j=1;j<n;j+=2){
325  arg=((double) j)*theta;
326  expfac=cplx(cos(arg),sin(arg));
327  res += expfac*f[j];
328  }
329  /*apply corrections*/
330  res *= corfac;
331  res += endcor;
332  arg=w*a;
333  expfac=cplx(delta*cos(arg),delta*sin(arg));
334  res *= expfac;
335 
336  res2 *= corfac2;
337  res2 += endcor2;
338  expfac *=2;
339  res2 *= expfac;
340  err=res-res2;
341 }
342 
343 } //namespace
std::complex< double > cplx
Definition: fourier.cpp:11
void get_dftcorr_linear(double th, double *corfac, cplx *endcor)
Returns correction factor and boundary correction term needed for linearly corrected DFT...
Definition: fourier.cpp:117
void dft_cplx(double w, int n, double a, double b, cplx *f, cplx &res, cplx &err)
Computes the Fourier integral using cubically corrected DFT.
Definition: fourier.cpp:283
void complex_dftcor_cubic(double w, double delta, double a, double b, cplx *endpts, cplx *endcor, double *corfac)
Returns correction factor and evaluate boundary correction terms needed for cubically corrected DFT...
Definition: fourier.cpp:182
void get_dftcorr_cubic(double th, double *corfac, cplx *endcor)
Returns correction factor and boundary correction terms needed for cubically corrected DFT...
Definition: fourier.cpp:43