OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
ComplexErrorFun.cpp
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2// $RCSfile: ComplexErrorFun.cpp,v $
3// ------------------------------------------------------------------------
4// $Revision: 1.2 $
5// ------------------------------------------------------------------------
6// Copyright: see Copyright.readme
7// ------------------------------------------------------------------------
8//
9// Function: Werrf(complex<double>)
10// The complex error function.
11//
12// ------------------------------------------------------------------------
13// Class category: Utilities
14// ------------------------------------------------------------------------
15//
16// $Date: 2001/08/24 19:33:44 $
17// $Author: jsberg $
18//
19// ------------------------------------------------------------------------
20
22#include <complex>
23
24
25// Complex error function
26// The algorithms is based on:
27// Walter Gautschi,
28// Efficient Computation of the Complex Error Function,
29// SIAM J. Numer. Anal., Vol 7, No. 1, March 1970, pp. 187-198.
30// ------------------------------------------------------------------------
31
32std::complex<double> Werrf(std::complex<double> z) {
33 const double cc = 1.12837916709551; // 2 / sqrt(pi)
34 const double xlim = 5.33;
35 const double ylim = 4.29;
36
37 const double x = std::abs(std::real(z));
38 const double y = std::abs(std::imag(z));
39 std::complex<double> w;
40
41 if(y < ylim && x < xlim) {
42 // Inside limit rectangle: equation (3.8): q = s(z);
43 const double q = (1.0 - y / ylim) * sqrt(1.0 - (x * x) / (xlim * xlim));
44 // Equations (3.11).
45 const int nc = 6 + int(23.0 * q);
46 const int nu = 9 + int(21.0 * q);
47 const std::complex<double> zz(1.6 * q + y, - x); // h - i*z
48
49 // Equations (3.12) for n = nu, nu - 1, ..., N.
50 std::complex<double> r(0.0); // r_{nu}
51 for(int n = nu; n > nc; n--) { // for n = nu, nu-1, ..., nc+1
52 r = 0.5 / (zz + double(n + 1) * r); // r_{n-1}
53 }
54
55 // Equations (3.12) for n = N, N - 1, ..., 0.
56 double power = pow(3.2 * q, nc); // (2*h)^nc
57 const double div = 0.3125 / q; // 1 / (2*h)
58 std::complex<double> s(0.0); // s_{N}
59 for(int n = nc; n >= 0; n--) { // for n = N, N-1, ..., 0
60 r = 0.5 / (zz + double(n + 1) * r); // r_{n-1}
61 s = r * (power + s); // s_{n-1}
62 power *= div; // (2*h)^(n-1)
63 }
64
65 // Equation (3.13).
66 w = cc * s;
67 } else {
68 // Outside limit rectangle: equations (3.12) for h = 0.
69 const std::complex<double> zz(y, - x); // - i*z
70 std::complex<double> r(0.0); // r_{nu}
71 for(int n = 8; n >= 0; n--) { // for n = nu, nu-1, ..., 0
72 r = 0.5 / (zz + double(n + 1) * r); // r_{n-1}
73 }
74
75 // Equation (3.13).
76 w = cc * r;
77 }
78
79 // Equations (3.1).
80 if(std::imag(z) < 0.0) {
81 std::complex<double> zz(x, y);
82 w = 2.0 * std::exp(- zz * zz) - w;
83 if(std::real(z) > 0.0) w = std::conj(w);
84 } else {
85 if(std::real(z) < 0.0) w = std::conj(w);
86 }
87
88 return w;
89}
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
FLieGenerator< T, N > imag(const FLieGenerator< std::complex< T >, N > &)
Take imaginary part of a complex generator.
std::complex< double > Werrf(std::complex< double > z)
Complex error function.
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
Tps< T > exp(const Tps< T > &x)
Exponential.
Definition: TpsMath.h:165
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
m_complex conj(const m_complex &c)
Definition: MVector.h:105