Program Listing for File wkbsolver.hpp¶
↰ Return to documentation for file (/home/docs/checkouts/readthedocs.org/user_builds/oscode/checkouts/stable/include/wkbsolver.hpp
)
#pragma once
#include <iomanip>
#include "system.hpp"
class WKBSolver
{
protected:
// Derivative terms
void d1w1();
void d1w2();
void d1w3();
void d1w4();
void d1w5();
void d1w6();
void d2w1();
void d2w2();
void d2w3();
void d2w4();
void d2w5();
void d2w6();
void d3w1();
void d3w2();
void d3w3();
void d3w4();
void d3w5();
void d3w6();
void d4w1();
void d1g1();
void d1g2();
void d1g3();
void d1g4();
void d1g5();
void d1g6();
void d2g1();
void d2g2();
void d2g3();
void d2g4();
void d2g5();
void d2g6();
void d3g1();
void d1w2_5();
void d1w3_5();
void d1w4_5();
// WKB series and derivatives (order dependent)
virtual void dds();
virtual void dsi();
virtual void dsf();
virtual void s();
// WKB solutions and derivatives
void fp();
void fm();
void dfpi();
void dfmi();
void dfpf();
void dfmf();
void ddfp();
void ddfm();
void ap();
void am();
void bp();
void bm();
// Gauss-Lobatto integration
Eigen::Matrix<std::complex<double>,2,1> integrate(const
Eigen::Matrix<std::complex<double>,6,1> &integrand6, const
Eigen::Matrix<std::complex<double>,5,1> &integrand5);
// Gauss-Lobatto n=6, 5 weights
Eigen::Matrix<double,6,1> glws6;
Eigen::Matrix<double,5,1> glws5;
// weights for derivatives
Eigen::Matrix<double,7,1> d4w1_w;
Eigen::Matrix<double,6,1> d1w1_w, d1w2_w, d1w3_w, d1w4_w, d1w5_w, d1w6_w,
d2w1_w, d2w2_w, d2w3_w, d2w4_w, d2w5_w, d2w6_w, d3w1_w, d3w2_w, d3w3_w, d3w4_w, d3w5_w, d3w6_w, d1g1_w, d1g6_w, d2g1_w, d2g6_w, d3g1_w;
Eigen::Matrix<double,5,1> d1w2_5_w, d1w3_5_w, d1w4_5_w;
// grid of ws, gs
Eigen::Matrix<std::complex<double>,7,1> ws7_;
Eigen::Matrix<std::complex<double>,6,1> ws_, gs_;
Eigen::Matrix<std::complex<double>,5,1> ws5_, gs5_;
// derivatives
std::complex<double> d1w1_, d1w2_, d1w3_, d1w4_, d1w5_, d1w6_, d2w1_, d2w2_, d2w3_, d2w4_, d2w5_, d2w6_,
d3w1_, d3w2_, d3w3_, d3w4_, d3w5_, d3w6_, d4w1_, d1g1_, d1g2_, d1g3_, d1g4_, d1g5_, d1g6_, d2g1_, d2g2_, d2g3_, d2g4_, d2g5_, d2g6_, d3g1_;
std::complex<double> d1w2_5_, d1w3_5_, d1w4_5_;
Eigen::Matrix<std::complex<double>,6,1> dws_, dgs_, d2ws_, d2gs_, d3ws_;
Eigen::Matrix<std::complex<double>,5,1> dws5_;
// WKB series and their derivatives
Eigen::Matrix<std::complex<double>,1,4> dds_, dsi_, dsf_, s_;
// Error in WKB series
Eigen::Matrix<std::complex<double>,1,4> s_error;
// WKB solutions and their derivatives
std::complex<double> fp_, fm_, dfpi_, dfmi_, dfpf_, dfmf_, ddfp_, ddfm_, ap_, am_, bp_, bm_;
// step and stepsize
double h;
std::complex<double> x, dx, ddx;
// order
int order_;
// error estimate on step
std::complex<double> err_fp, err_fm, err_dfp, err_dfm;
// dense output
std::list<std::complex<double>> doxs, dodxs, dows;
Eigen::Matrix<std::complex<double>,1,4> dense_s_, dense_ds_, dense_ds_i;
std::complex<double> dense_ap_, dense_am_, dense_bp_, dense_bm_;
// experimental dense output + quadrature
Eigen::Matrix<double,6,6> integ_vandermonde, interp_vandermonde;
public:
// constructor
WKBSolver();
WKBSolver(de_system &de_sys, int order);
Eigen::Matrix<std::complex<double>,3,2> step(std::complex<double> x0,
std::complex<double> dx0, double t0, double h0, const
Eigen::Matrix<std::complex<double>,6,1> &ws, const
Eigen::Matrix<std::complex<double>,6,1> &gs, const
Eigen::Matrix<std::complex<double>,5,1> &ws5, const
Eigen::Matrix<std::complex<double>,5,1> &gs5);
// dense output
void dense_step(double t0, const std::list<double> &dots, std::list<std::complex<double>> &doxs, std::list<std::complex<double>> &dodxs);
Eigen::Matrix<double,6,1> dense_weights_6(double t);
Eigen::Matrix<double,6,1> dense_weights_derivs_6(double t);
std::complex<double> dense_integrate(const Eigen::Matrix<double,6,1>
&denseweights6, const Eigen::Matrix<std::complex<double>,6,1> &integrand6);
std::complex<double> dense_interpolate(const Eigen::Matrix<double,6,1>
&denseweights6, const Eigen::Matrix<std::complex<double>,6,1> &integrand6);
// Experimental continuous representation of solution
Eigen::Matrix<std::complex<double>,7,1> x_vdm;
};
WKBSolver::WKBSolver(){
};
WKBSolver::WKBSolver(de_system &de_sys, int order){
// Set order
order_ = order;
// Set Gauss-Lobatto weights
glws6 << 1.0/15.0,0.3784749562978469803166,0.5548583770354863530167,
0.5548583770354863530167,0.3784749562978469803166,1.0/15.0;
glws5 << 1.0/10.0,49.0/90.0,32.0/45.0,49.0/90.0,1.0/10.0;
// Set finite difference weights
d1w1_w << -15.0000000048537, 20.2828318761850,
-8.07237453994912, 4.48936929577350, -2.69982662677053, 0.999999999614819;
d1w2_w << -3.57272991033049, 0.298532922755350e-7 ,
5.04685352597795, -2.30565629452303, 1.30709499910514, -0.475562350082855;
d1w3_w << 0.969902096162109, -3.44251390568294,
-0.781532641131861e-10, 3.50592393061265, -1.57271334190619, 0.539401220892526 ;
d1w4_w << -0.539401220892533, 1.57271334190621,
-3.50592393061268, 0.782075077478921e-10, 3.44251390568290, -0.969902096162095;
d1w5_w << 0.475562350082834, -1.30709499910509,
2.30565629452296, -5.04685352597787, -0.298533681980831e-7, 3.57272991033053;
d1w6_w << -0.999999999614890, 2.69982662677075,
-4.48936929577383, 8.07237453994954, -20.2828318761854, 15.0000000048538;
d2w1_w << 140.000000016641, -263.163968874741,
196.996471291466, -120.708905753218, 74.8764032980854, -27.9999999782328;
d2w2_w << 60.8267436465252, -96.4575130414144, 42.0725563562029,
-8.78105375967028, 3.41699471496020, -1.07772791660362;
d2w3_w << -5.42778322782674, 28.6981500482483, -43.5424868874619,
24.5830052399403, -5.98965265951073, 1.67876748661075;
d2w4_w << 1.67876748661071, -5.98965265951067, 24.5830052399402,
-43.5424868874617, 28.6981500482481, -5.42778322782664;
d2w5_w << -1.07772791660381, 3.41699471496078, -8.78105375967105,
42.0725563562040, -96.4575130414154, 60.8267436465256;
d2w6_w << -27.9999999782335, 74.8764032980873, -120.708905753221,
196.996471291469, -263.163968874744, 140.000000016642;
d3w1_w << -840.000000234078, 1798.12714381468, -1736.74461287884,
1322.01528240287, -879.397812956524, 335.999999851893;
d3w2_w << -519.5390172614027, 1067.7171515309801, -934.3207515371753,
617.0298708048756, -364.83838902593686, 133.95113548865842;
d3w3_w << -81.13326349151461, 90.82824880172825, 81.1176254157912,
-199.41150112141258, 171.22231114098616, -62.62342074557803;
d3w4_w << 62.62342074557783, -171.2223111409866, 199.41150112141344,
-81.11762541579242, -90.82824880172696, 81.13326349151436;
d3w5_w << -133.95113548865962, 364.8383890259409, -617.0298708048813,
934.3207515371842, -1067.717151530989, 519.5390172614059;
d3w6_w << -335.999999851897, 879.397812956534,
-1322.01528240289, 1736.74461287886, -1798.12714381470, 840.000000234086;
d4w1_w << //9744.00062637928, -27851.6858893579, 75653.4044616243,
//-107520.008443354, 61113.3089030151, -15843.0200709916, 4704.00041268436;
3024.00000383582, -6923.06197480357, 7684.77676018742, 0.0, -6855.31809730784, 5085.60330881706, -2016.00000072890;
d1g1_w << -15.0000000048537, 20.2828318761850,
-8.07237453994912, 4.48936929577350, -2.69982662677053, 0.999999999614819 ;
d1g6_w << -0.999999999614890, 2.69982662677075,
-4.48936929577383, 8.07237453994954, -20.2828318761854, 15.0000000048538;
d2g1_w << 140.000000016641, -263.163968874741,
196.996471291466, -120.708905753218, 74.8764032980854, -27.9999999782328;
d2g6_w << -27.9999999782335, 74.8764032980873,
-120.708905753221, 196.996471291469, -263.163968874744, 140.000000016642;
d3g1_w << -840.000000234078, 1798.12714381468,
-1736.74461287884, 1322.01528240287, -879.397812956524, 335.999999851893;
d1w2_5_w << -2.48198050935042, 0.560400997591235e-8,
3.49148624058567, -1.52752523062733, 0.518019493788063;
d1w3_5_w << 0.750000000213852, -2.67316915534181,
0.360673032443906e-10, 2.67316915534181, -0.750000000213853;
d1w4_5_w << -0.518019493788065, 1.52752523062733,
-3.49148624058568, -0.560400043118500e-8, 2.48198050935041;
// Set polynomial Gauss--Lobatto coefficients for dense output + quadrature
double a = std::sqrt(147+42*std::sqrt(7.));
double b = std::sqrt(147-42*std::sqrt(7.));
interp_vandermonde << 0.06250000000, -0.1946486424, 0.6321486424, 0.6321486424, -0.1946486424, 0.06250000000,
-0.06250000000, 0.2544242701, -2.216265054, 2.216265054, -0.2544242701, 0.06250000000,
-0.8750000000, 2.587172940, -1.712172940, -1.712172940, 2.587172940, -0.8750000000,
0.8750000000, -3.381680853, 6.002748088, -6.002748088, 3.381680853, -0.8750000000,
1.312500000, -2.392524298, 1.080024298, 1.080024298, -2.392524298, 1.312500000,
-1.312500000, 3.127256583, -3.786483034, 3.786483034, -3.127256583, 1.312500000;
integ_vandermonde << 0.06250000000, -0.1946486424, 0.6321486424, 0.6321486424, -0.1946486424, 0.06250000000,
-0.03125000000, 0.1272121350, -1.108132527, 1.108132527, -0.1272121350, 0.03125000000,
-0.2916666667, 0.8623909801, -0.5707243134, -0.5707243134, 0.8623909801, -0.2916666667,
0.2187500000, -0.8454202132, 1.500687022, -1.500687022, 0.8454202132, -0.2187500000,
0.2625000000, -0.4785048596, 0.2160048596, 0.2160048596, -0.4785048596, 0.2625000000,
-0.2187500000, 0.5212094304, -0.6310805056, 0.6310805056, -0.5212094304, 0.2187500000;
};
Eigen::Matrix<std::complex<double>,3,2> WKBSolver::step(std::complex<double> x0,
std::complex<double> dx0, double t0, double h0, const
Eigen::Matrix<std::complex<double>,6,1> &ws, const
Eigen::Matrix<std::complex<double>,6,1> &gs, const
Eigen::Matrix<std::complex<double>,5,1> &ws5, const
Eigen::Matrix<std::complex<double>,5,1> &gs5){
// Vandermonde dense output
Eigen::Matrix<std::complex<double>,6,1> s0_vdm_vec,s1_vdm_vec,s2_vdm_vec,s3_vdm_vec;
std::complex<double> s0_vdm,s1_vdm,s2_vdm,s3_vdm;
Eigen::Matrix<std::complex<double>,7,1> s_vdm_vec;
Eigen::Matrix<double,6,1> dows6, dodws6; // weights for dense integration/interpolation
Eigen::Matrix<std::complex<double>,6,1> integrand6, s3_interp, s2_interp, s1_interp;
Eigen::Matrix<std::complex<double>,6,1> ds1_interp, ds2_interp, ds3_interp;
double t_trans;
std::complex<double> s0,s1,s2,s3,dense_fp,dense_fm,dense_x;
std::complex<double> ds0,ds1,ds2,ds3,dense_dfpf,dense_dfmf,dense_dx;
Eigen::Matrix<std::complex<double>,3,2> result;
result << 0.0, 0.0, 0.0, 0.0, 0.0, 0.0;
// Set grid of ws, gs:
ws_ = ws;
gs_ = gs;
ws5_ = ws5;
gs5_ = gs5;
ws7_ << ws_(0), ws_(1), ws_(2), ws5_(2), ws_(3), ws_(4), ws_(5);
// Set i.c.
x = x0;
dx = dx0;
ddx = -std::pow(ws_(0),2)*x - 2.0*gs_(0)*dx;
// Set derivatives:
h = h0;
d1w1(); d1w2(); d1w3(); d1w4(); d1w5(); d1w6(); d2w1(); d2w6(); d3w1();
d3w6(); d4w1(); d1g1(); d1g6(); d2g1(); d2g6(); d3g1(); d1w2_5(); d1w3_5(); d1w4_5();
dws_ << d1w1_, d1w2_, d1w3_, d1w4_, d1w5_, d1w6_;
dws5_ << d1w1_, d1w2_5_, d1w3_5_, d1w4_5_, d1w6_;
// Higher order step
// Calculate A, B
fm_ = 1.0;
fp_ = 1.0;
s_ << 0.0, 0.0, 0.0, 0.0; dsi(); dds();
dfpi(); dfmi();
ddfp(); ddfm();
ap(); am(); bp(); bm();
dense_ap_ = ap_; dense_am_ = am_;
dense_bp_ = bp_; dense_bm_ = bm_;
dense_ds_i = dsi_;
// Calculate step
s();
dsf();
fp(); fm();
dfpf(); dfmf();
result(0,0) = ap_*fp_ + am_*fm_;
result(0,1) = bp_*dfpf_ +bm_*dfmf_;
// Error estimate on this
err_fp = s_error.cwiseAbs().sum()*fp_;
err_fm = std::conj(err_fp);
err_dfp = dfpf_/fp_*err_fp;
err_dfm = std::conj(err_dfp);
result(2,0) = ap_*err_fp + am_*err_fm;
result(2,1) = bp_*err_dfp + bm_*err_dfm;
// Experimental continuous representation
// Compute some derivatives only necessary for dense output
d1g2(); d1g3(); d1g4(); d1g5(); d2w2(); d2w3(); d2w4(); d2w5();
dgs_ << d1g1_, d1g2_, d1g3_, d1g4_, d1g5_, d1g6_;
d2ws_ << d2w1_, d2w2_, d2w3_, d2w4_, d2w5_, d2w6_;
integrand6 = 4.0*gs_.cwiseProduct(gs_).cwiseQuotient(ws_) +
4.0*dws_.cwiseProduct(gs_).cwiseQuotient(ws_.cwiseProduct(ws_)) +
dws_.cwiseProduct(dws_).cwiseQuotient(ws_.cwiseProduct(ws_.cwiseProduct(ws_)));
for(int i=0; i<=5; i++)
s1_interp(i) = -1./2*std::log(ws_(i));
s2_interp = -1/4.0*(dws_.cwiseQuotient(ws_.cwiseProduct(ws_)) + 2.0*gs_.cwiseQuotient(ws_));
s3_interp =
1/4.0*(gs_.cwiseProduct(gs_).cwiseQuotient((ws_.cwiseProduct(ws_)))) +
1/4.0*(dgs_.cwiseQuotient(ws_.cwiseProduct(ws_))) -
3/16.0*(dws_.cwiseProduct(dws_).cwiseQuotient(ws_.cwiseProduct(ws_).cwiseProduct(ws_.cwiseProduct(ws_))))
+ 1/8.0*(d2ws_.cwiseQuotient(ws_.cwiseProduct(ws_).cwiseProduct(ws_)));
// S0
s0_vdm_vec = h/2.0*std::complex<double>(0,1)*integ_vandermonde*ws_;
// S1
s1_vdm_vec = -h/2.0*integ_vandermonde*gs_;
s1_vdm_vec.head(5) += (interp_vandermonde*s1_interp).tail(5);
// S2
s2_vdm_vec = -h/2.0*1/8.0*integ_vandermonde*integrand6;
s2_vdm_vec.head(5) += (interp_vandermonde*s2_interp).tail(5);
// S3
s3_vdm_vec = Eigen::Matrix<std::complex<double>,6,1>::Zero();
s3_vdm_vec.head(5) += (interp_vandermonde*s3_interp).tail(5);
x_vdm.tail(6) = s0_vdm_vec + s1_vdm_vec + std::complex<double>(0,1)*s2_vdm_vec + s3_vdm_vec;
x_vdm(0) = ap_;
// Lower order step for correction
// A, B
dsi_(order_) = 0.0; dds_(order_) = 0.0;
dfpi(); dfmi();
ddfp(); ddfm();
ap(); am(); bp(); bm();
// Calculate step
s_(order_) = 0.0;
dsf_(order_) = 0.0;
fp(); fm();
dfpf(); dfmf();
result(1,0) = result(0,0) - ap_*fp_ - am_*fm_;
result(1,1) = result(0,1) - bp_*dfpf_ - bm_*dfmf_;
return result;
};
void WKBSolver::dense_step(double t0, const std::list<double> &dots, std::list<std::complex<double>> &doxs, std::list<std::complex<double>> &dodxs){
// We have: ws_, gs_, ws5_, gs5_, ws7_, x, dx, ddx, h, dws_, dws5_, d2wx,
// d3wx, etc.,
int docount = dots.size();
doxs.resize(docount);
dodxs.resize(docount);
Eigen::Matrix<double,6,1> dows6, dodws6; // weights for dense integration/interpolation
Eigen::Matrix<std::complex<double>,6,1> integrand6, s3_interp, s2_interp, s1_interp;
Eigen::Matrix<std::complex<double>,6,1> ds1_interp, ds2_interp, ds3_interp;
double t_trans;
std::complex<double> s0,s1,s2,s3,dense_fp,dense_fm,dense_x;
std::complex<double> ds0,ds1,ds2,ds3,dense_dfpf,dense_dfmf,dense_dx;
// Vandermonde dense output
Eigen::Matrix<std::complex<double>,6,1> s0_vdm_vec,s1_vdm_vec,s2_vdm_vec,s3_vdm_vec;
Eigen::Matrix<double,6,1> t_trans_vec,t_trans_vec_interp;
std::complex<double> s0_vdm,s1_vdm,s2_vdm,s3_vdm;
Eigen::Matrix<std::complex<double>,7,1> s_vdm_vec;
double tt1,tt2,tt3,tt4,tt5,tt6;
// Compute some derivatives only necessary for dense output
d1g2(); d1g3(); d1g4(); d1g5(); d2w2(); d2w3(); d2w4(); d2w5();
d2g2(); d2g3(); d2g4(); d2g5(); d3w2(); d3w3(); d3w4(); d3w5();
dgs_ << d1g1_, d1g2_, d1g3_, d1g4_, d1g5_, d1g6_;
d2ws_ << d2w1_, d2w2_, d2w3_, d2w4_, d2w5_, d2w6_;
d2gs_ << d2g1_, d2g2_, d2g3_, d2g4_, d2g5_, d2g6_;
d3ws_ << d3w1_, d3w2_, d3w3_, d3w4_, d3w5_, d3w6_;
// Loop over dense output points
auto doxit = doxs.begin();
auto dodxit = dodxs.begin();
for(auto it=dots.begin(); it!=dots.end(); it++){
// Transform intermediate points to be in (-1,1):
t_trans = 2*(*it - t0)/h - 1;
dows6 = dense_weights_6(t_trans);
dodws6 = dense_weights_derivs_6(t_trans);
// Dense output x
integrand6 = 4.0*gs_.cwiseProduct(gs_).cwiseQuotient(ws_) +
4.0*dws_.cwiseProduct(gs_).cwiseQuotient(ws_.cwiseProduct(ws_)) +
dws_.cwiseProduct(dws_).cwiseQuotient(ws_.cwiseProduct(ws_.cwiseProduct(ws_)));
s0 = std::complex<double>(0,1)*dense_integrate(dows6,ws_);
s1 = dense_integrate(dows6,gs_);
for(int i=0; i<=5; i++)
s1_interp(i) = -1./2*std::log(ws_(i));
s1 = dense_interpolate(dodws6, s1_interp) - s1;
s2 = dense_integrate(dows6, integrand6);
s2_interp = -1/4.0*(dws_.cwiseQuotient(ws_.cwiseProduct(ws_)) + 2.0*gs_.cwiseQuotient(ws_));
s2 = dense_interpolate(dodws6, s2_interp) - 1/8.0*s2;
s3_interp =
1/4.0*(gs_.cwiseProduct(gs_).cwiseQuotient((ws_.cwiseProduct(ws_)))) +
1/4.0*(dgs_.cwiseQuotient(ws_.cwiseProduct(ws_))) -
3/16.0*(dws_.cwiseProduct(dws_).cwiseQuotient(ws_.cwiseProduct(ws_).cwiseProduct(ws_.cwiseProduct(ws_))))
+ 1/8.0*(d2ws_.cwiseQuotient(ws_.cwiseProduct(ws_).cwiseProduct(ws_)));
s3 = dense_interpolate(dodws6, s3_interp);
dense_s_ << s0, s1, std::complex<double>(0,1)*s2, s3;
dense_fp = std::exp(dense_s_.sum());
dense_fm = std::conj(dense_fp);
dense_x = dense_ap_*dense_fp + dense_am_*dense_fm;
*doxit = dense_x;
doxit++;
// Same, but with Vandermonde matrix:
tt1 = t_trans;
tt2 = tt1*t_trans;
tt3 = tt2*t_trans;
tt4 = tt3*t_trans;
tt5 = tt4*t_trans;
tt6 = tt5*t_trans;
t_trans_vec << tt1+1, tt2-1, tt3+1, tt4-1, tt5+1, tt6-1;
t_trans_vec_interp << 0, tt1+1, tt2-1, tt3+1, tt4-1, tt5+1;
// S0
s0_vdm_vec = h/2.0*std::complex<double>(0,1)*integ_vandermonde*ws_;
s0_vdm = t_trans_vec.dot(s0_vdm_vec);
// S1
s1_vdm = -h/2.0*t_trans_vec.dot(integ_vandermonde*gs_) + t_trans_vec_interp.dot(interp_vandermonde*s1_interp);
s1_vdm_vec = -h/2.0*integ_vandermonde*gs_;
s1_vdm_vec.head(5) += (interp_vandermonde*s1_interp).tail(5);
s1_vdm = t_trans_vec.dot(s1_vdm_vec);
// S2
s2_vdm_vec = -h/2.0*1/8.0*integ_vandermonde*integrand6;
s2_vdm_vec.head(5) += (interp_vandermonde*s2_interp).tail(5);
s2_vdm = t_trans_vec.dot(s2_vdm_vec);
// S3
s3_vdm_vec = Eigen::Matrix<std::complex<double>,6,1>::Zero();
s3_vdm_vec.head(5) += (interp_vandermonde*s3_interp).tail(5);
s3_vdm = t_trans_vec.dot(s3_vdm_vec) ;
//x_vdm = dense_ap_*(s0_vdm_vec + s1_vdm_vec + s2_vdm_vec + s3_vdm_vec);
//std::cout << std::setprecision(15) << "dense S0 with Vandermonde matrix: " << s0_vdm << std::endl;
//std::cout << "dense S0 with classical theory: " << s0 << std::endl;
//std::cout << std::setprecision(15) << "dense S1 with Vandermonde matrix: " << s1_vdm << std::endl;
//std::cout << "dense S1 with classical theory: " << s1 << std::endl;
//std::cout << std::setprecision(15) << "dense S2 with Vandermonde matrix: " << s2_vdm << std::endl;
//std::cout << "dense S1 with classical theory: " << s2 << std::endl;
//std::cout << std::setprecision(15) << "dense S3 with Vandermonde matrix: " << s3_vdm << std::endl;
//std::cout << "dense S3 with classical theory: " << s3 << std::endl;
//std::cout << "Representation of S0: " << s0_vdm_vec << std::endl;
//std::cout << "Representation of S1: " << s1_vdm_vec << std::endl;
//std::cout << "Ap: " << dense_ap_ << ", Am: " << dense_am_ << std::endl;
// Dense output dx
ds0 = std::complex<double>(0,1)*dense_interpolate(dodws6,ws_);
ds1 = dense_interpolate(dodws6,gs_);
ds1_interp = -1./2*dws_.cwiseQuotient(ws_);
ds1 = dense_interpolate(dodws6,ds1_interp) - ds1;
ds2_interp = -1./2*gs_.cwiseProduct(gs_.cwiseQuotient(ws_)) - 1./2*dgs_.cwiseQuotient(ws_) + 3./8*(dws_.cwiseProduct(dws_)).cwiseQuotient((ws_.cwiseProduct(ws_)).cwiseProduct(ws_)) - 1./4*d2ws_.cwiseQuotient(ws_.cwiseProduct(ws_));
ds2 = dense_interpolate(dodws6,ds2_interp);
ds3_interp = 1./8.0*(d3ws_.cwiseQuotient(ws_.cwiseProduct(ws_.cwiseProduct(ws_))) + 2*d2gs_.cwiseQuotient(ws_.cwiseProduct(ws_)) - 6*(dws_.cwiseProduct(d2ws_)).cwiseQuotient(ws_.cwiseProduct(ws_.cwiseProduct(ws_.cwiseProduct(ws_)))) + 6*(dws_.cwiseProduct(dws_.cwiseProduct(dws_))).cwiseQuotient(ws_.cwiseProduct(ws_.cwiseProduct(ws_.cwiseProduct(ws_.cwiseProduct(ws_))))) - 4*(gs_.cwiseProduct(gs_)+dgs_).cwiseProduct(dws_).cwiseQuotient(ws_.cwiseProduct(ws_.cwiseProduct(ws_)))+ 4*dgs_.cwiseProduct(gs_).cwiseQuotient(ws_.cwiseProduct(ws_.cwiseProduct(ws_.cwiseProduct(ws_)))));
ds3 = dense_interpolate(dodws6,ds3_interp);
dense_ds_ << ds0, ds1, std::complex<double>(0,1)*ds2, ds3;
dense_ds_ += dense_ds_i;
dense_dfpf = dense_ds_.sum()*dense_fp;
dense_dfmf = std::conj(dense_dfpf);
dense_dx = dense_bp_*dense_dfpf + dense_bm_*dense_dfmf;
*dodxit = dense_dx;
dodxit++;
}
return;
};
// Compute integration weights at a given point
Eigen::Matrix<double,6,1> WKBSolver::dense_weights_6(double t){
double a = std::sqrt(147+42*std::sqrt(7.));
double b = std::sqrt(147-42*std::sqrt(7.));
double c = (-2./35*t*t*t + 4./35*t*t - 2./45*t - 8./315)*std::sqrt(7.);
double w1 = 31./480 - 7./32*t*t*t*t*t*t + 21./80*t*t*t*t*t + 7./32*t*t*t*t -7./24*t*t*t - 1./32*t*t + 1./16*t;
double w2 = -2205*((c - 4./63*t + 8./63)*a + (t-1)*(t-1)*(t*t*std::sqrt(7.) + 1))*(t+1)*(t+1)/(a*(-1120 + 160*std::sqrt(7.)));
double w3 = -2205*((c + 4./63*t - 8./63)*b + (t-1)*(t-1)*(t*t*std::sqrt(7.) - 1))*(t+1)*(t+1)/(b*(1120 + 160*std::sqrt(7.)));
double w4 = 2205*((-c - 4./63*t + 8./63)*b + (t-1)*(t-1)*(t*t*std::sqrt(7.) - 1))*(t+1)*(t+1)/(b*(1120 + 160*std::sqrt(7.)));
double w5 = 2205*((-c + 4./63*t - 8./63)*a + (t-1)*(t-1)*(t*t*std::sqrt(7.) + 1))*(t+1)*(t+1)/(a*(-1120 + 160*std::sqrt(7.)));
double w6 = 1./480 + 7./32*t*t*t*t*t*t + 21./80*t*t*t*t*t - 7./32*t*t*t*t -7./24*t*t*t + 1./32*t*t + 1./16*t;
Eigen::Matrix<double,6,1> result;
result << w1,w2,w3,w4,w5,w6;
return result;
}
// Compute weights of the interpolating polynomial
Eigen::Matrix<double,6,1> WKBSolver::dense_weights_derivs_6(double t){
double a = std::sqrt(147+42*std::sqrt(7.));
double b = std::sqrt(147-42*std::sqrt(7.));
double c = (27783*t*t*t*t*t*t - 46305*t*t*t*t + 19845*t*t - 1323)*sqrt(7.)/16.;
double w1 = -(21*t*t*t*t-14*t*t+1)*(t-1)/16.;
double w2 = -c/(a*(-7+sqrt(7.))*(21*t + a));
double w3 = -c/(b*(7+sqrt(7.))*(21*t + b));
double w4 = c/(b*(7+sqrt(7.))*(21*t - b));
double w5 = c/(a*(-7+sqrt(7.))*(21*t - a));
double w6 = (21*t*t*t*t-14*t*t+1)*(t+1)/16.;
Eigen::Matrix<double,6,1> result;
result << w1,w2,w3,w4,w5,w6;
return result;
};
// Dense output integration
std::complex<double> WKBSolver::dense_integrate(const
Eigen::Matrix<double,6,1> &denseweights6, const
Eigen::Matrix<std::complex<double>,6,1> &integrand6){
return h/2.0*denseweights6.dot(integrand6);
}
// Dense output interpolation using Gauss-Lobatto
std::complex<double> WKBSolver::dense_interpolate(const
Eigen::Matrix<double,6,1> &denseweights6, const
Eigen::Matrix<std::complex<double>,6,1> &integrand6){
Eigen::Matrix<double,6,1> mod_weights = denseweights6;
mod_weights(0) -= 1.0;
return mod_weights.dot(integrand6);
}
Eigen::Matrix<std::complex<double>,2,1> WKBSolver::integrate(const
Eigen::Matrix<std::complex<double>,6,1> &integrand6, const
Eigen::Matrix<std::complex<double>,5,1> &integrand5){
std::complex<double> x6 = h/2.0*glws6.dot(integrand6);
std::complex<double> x5 = h/2.0*glws5.dot(integrand5);
Eigen::Matrix<std::complex<double>,2,1> result;
result << x6, x6-x5;
return result;
};
void WKBSolver::fp(){
fp_ = std::exp(s_.sum());
};
void WKBSolver::fm(){
fm_ = std::conj(fp_);
};
void WKBSolver::dfpi(){
dfpi_ = dsi_.sum();
};
void WKBSolver::dfmi(){
dfmi_ = std::conj(dfpi_);
};
void WKBSolver::dfpf(){
dfpf_ = dsf_.sum()*fp_;
};
void WKBSolver::dfmf(){
dfmf_ = std::conj(dfpf_);
};
void WKBSolver::ddfp(){
ddfp_ = dds_.sum() + std::pow(dsi_.sum(),2);
};
void WKBSolver::ddfm(){
ddfm_ = std::conj(ddfp_);
};
void WKBSolver::ap(){
ap_ = (dx - x*dfmi_)/(dfpi_ - dfmi_);
};
void WKBSolver::am(){
am_ = (dx - x*dfpi_)/(dfmi_ - dfpi_);
};
void WKBSolver::bp(){
bp_ = (ddx*dfmi_ - dx*ddfm_)/(ddfp_*dfmi_ - ddfm_*dfpi_);
};
void WKBSolver::bm(){
bm_ = (ddx*dfpi_ - dx*ddfp_)/(ddfm_*dfpi_ - ddfp_*dfmi_);
};
void WKBSolver::dds(){
dds_ << std::complex<double>(0.0, 1.0)*d1w1_, 0.0, 0.0, 0.0;
};
void WKBSolver::dsi(){
dsi_ << std::complex<double>(0.0, 1.0)*ws_(0), 0.0, 0.0, 0.0;
};
void WKBSolver::dsf(){
dsf_ << std::complex<double>(0.0, 1.0)*ws_(5), 0.0, 0.0, 0.0;
};
void WKBSolver::s(){
Eigen::Matrix<std::complex<double>,2,1> s0;
s0 << std::complex<double>(0,1)*integrate(ws_, ws5_);
s_ << s0(0), 0.0, 0.0, 0.0;
s_error << s0(1), 0.0, 0.0, 0.0;
};
void WKBSolver::d1w1(){
d1w1_ = d1w1_w.dot(ws_)/h;
};
void WKBSolver::d1w2(){
d1w2_ = d1w2_w.dot(ws_)/h;
};
void WKBSolver::d1w3(){
d1w3_ = d1w3_w.dot(ws_)/h;
};
void WKBSolver::d1w4(){
d1w4_ = d1w4_w.dot(ws_)/h;
};
void WKBSolver::d1w5(){
d1w5_ = d1w5_w.dot(ws_)/h;
};
void WKBSolver::d1w6(){
d1w6_ = d1w6_w.dot(ws_)/h;
};
void WKBSolver::d2w1(){
d2w1_ = d2w1_w.dot(ws_)/(h*h);
};
void WKBSolver::d2w2(){
d2w2_ = d2w2_w.dot(ws_)/(h*h);
};
void WKBSolver::d2w3(){
d2w3_ = d2w3_w.dot(ws_)/(h*h);
};
void WKBSolver::d2w4(){
d2w4_ = d2w4_w.dot(ws_)/(h*h);
};
void WKBSolver::d2w5(){
d2w5_ = d2w5_w.dot(ws_)/(h*h);
};
void WKBSolver::d2w6(){
d2w6_ = d2w6_w.dot(ws_)/(h*h);
};
void WKBSolver::d3w1(){
d3w1_ = d3w1_w.dot(ws_)/(h*h*h);
};
void WKBSolver::d3w2(){
d3w2_ = d3w2_w.dot(ws_)/(h*h*h);
};
void WKBSolver::d3w3(){
d3w3_ = d3w3_w.dot(ws_)/(h*h*h);
};
void WKBSolver::d3w4(){
d3w4_ = d3w4_w.dot(ws_)/(h*h*h);
};
void WKBSolver::d3w5(){
d3w5_ = d3w5_w.dot(ws_)/(h*h*h);
};
void WKBSolver::d3w6(){
d3w6_ = d3w6_w.dot(ws_)/(h*h*h);
};
void WKBSolver::d4w1(){
d4w1_ = d4w1_w.dot(ws7_)/(h*h*h*h);
};
void WKBSolver::d1g1(){
d1g1_ = d1g1_w.dot(gs_)/h;
};
void WKBSolver::d1g2(){
d1g2_ = d1w2_w.dot(gs_)/h;
};
void WKBSolver::d1g3(){
d1g3_ = d1w3_w.dot(gs_)/h;
};
void WKBSolver::d1g4(){
d1g4_ = d1w4_w.dot(gs_)/h;
};
void WKBSolver::d1g5(){
d1g5_ = d1w5_w.dot(gs_)/h;
};
void WKBSolver::d1g6(){
d1g6_ = d1g6_w.dot(gs_)/h;
};
void WKBSolver::d2g1(){
d2g1_ = d2g1_w.dot(gs_)/(h*h);
};
void WKBSolver::d2g2(){
d2g2_ = d2w2_w.dot(gs_)/(h*h);
};
void WKBSolver::d2g3(){
d2g3_ = d2w3_w.dot(gs_)/(h*h);
};
void WKBSolver::d2g4(){
d2g4_ = d2w4_w.dot(gs_)/(h*h);
};
void WKBSolver::d2g5(){
d2g5_ = d2w5_w.dot(gs_)/(h*h);
};
void WKBSolver::d2g6(){
d2g6_ = d2g6_w.dot(gs_)/(h*h);
};
void WKBSolver::d3g1(){
d3g1_ = d3g1_w.dot(gs_)/(h*h*h);
};
void WKBSolver::d1w2_5(){
d1w2_5_ = d1w2_5_w.dot(ws5_)/h;
};
void WKBSolver::d1w3_5(){
d1w3_5_ = d1w3_5_w.dot(ws5_)/h;
};
void WKBSolver::d1w4_5(){
d1w4_5_ = d1w4_5_w.dot(ws5_)/h;
};
class WKBSolver1 : public WKBSolver
{
private:
void dds();
void dsi();
void dsf();
void s();
public:
WKBSolver1();
WKBSolver1(de_system &de_sys, int order);
};
WKBSolver1::WKBSolver1(){
};
WKBSolver1::WKBSolver1(de_system &de_sys, int order) : WKBSolver(de_sys, order){
};
void WKBSolver1::dds(){
dds_ << std::complex<double>(0,1)*d1w1_,
1.0/std::pow(ws_(0),2)*std::pow(d1w1_,2)/2.0-1.0/ws_(0)*d2w1_/2.0-d1g1_, 0.0, 0.0;
};
void WKBSolver1::dsi(){
dsi_ << std::complex<double>(0.0, 1.0)*ws_(0), -0.5*d1w1_/ws_(0)-gs_(0), 0.0, 0.0;
};
void WKBSolver1::dsf(){
dsf_ << std::complex<double>(0.0, 1.0)*ws_(5), -0.5*d1w6_/ws_(5)-gs_(5), 0.0, 0.0;
};
void WKBSolver1::s(){
Eigen::Matrix<std::complex<double>,2,1> s0, s1;
s0 << std::complex<double>(0,1)*integrate(ws_, ws5_);
s1 << integrate(gs_, gs5_);
s1(0) = std::log(std::sqrt(ws_(0)/ws_(5))) - s1(0);
s_ << s0(0), s1(0), 0.0, 0.0;
s_error << s0(1), s1(1), 0.0, 0.0;
};
class WKBSolver2 : public WKBSolver
{
private:
void dds();
void dsi();
void dsf();
void s();
public:
WKBSolver2();
WKBSolver2(de_system &de_sys, int order);
};
WKBSolver2::WKBSolver2(){
};
WKBSolver2::WKBSolver2(de_system &de_sys, int order) : WKBSolver(de_sys, order){
};
void WKBSolver2::dds(){
dds_ << std::complex<double>(0,1)*d1w1_,
1.0/std::pow(ws_(0),2)*std::pow(d1w1_,2)/2.0-1.0/ws_(0)*d2w1_/2.0-d1g1_,
-std::complex<double>(0,1/8)*(8.0*d1g1_*gs_(0)*std::pow(ws_(0),3)-4.0*d1w1_*std::pow(gs_(0),2)*std::pow(ws_(0),2)+4.0*d2g1_*std::pow(ws_(0),3)-4.0*d1w1_*d1g1_*std::pow(ws_(0),2)+2.0*d3w1_*std::pow(ws_(0),2)-10.0*d1w1_*d2w1_*ws_(0)+9.0*std::pow(d1w1_,3))/std::pow(ws_(0),4), 0.0;
};
void WKBSolver2::dsi(){
dsi_ << std::complex<double>(0,1)*ws_(0),-1.0/ws_(0)*d1w1_/2.0-gs_(0),
std::complex<double>(0,1/8)*(-4.0*std::pow(gs_(0),2)*std::pow(ws_(0),2)-4.0*d1g1_*std::pow(ws_(0),2)-2.0*d2w1_
*ws_(0)+3.0*std::pow(d1w1_,2))/std::pow(ws_(0),3), 0.0;
};
void WKBSolver2::dsf(){
dsf_ << std::complex<double>(0,1)*ws_(5),-1.0/ws_(5)*d1w6_/2.0-gs_(5),
std::complex<double>(0,1/8)*(-4.0*std::pow(gs_(5),2)*std::pow(ws_(5),2)-4.0*d1g6_*std::pow(ws_(5),2)-2.0*d2w6_
*ws_(5)+3.0*std::pow(d1w6_,2))/std::pow(ws_(5),3), 0.0;
};
void WKBSolver2::s(){
Eigen::Matrix<std::complex<double>,2,1> s0, s1, s2;
Eigen::Matrix<std::complex<double>,6,1> integrand6;
Eigen::Matrix<std::complex<double>,5,1> integrand5;
integrand6 = 4*gs_.cwiseProduct(gs_).cwiseQuotient(ws_) +
4*dws_.cwiseProduct(gs_).cwiseQuotient(ws_.cwiseProduct(ws_)) +
dws_.cwiseProduct(dws_).cwiseQuotient(ws_.cwiseProduct(ws_.cwiseProduct(ws_)));
integrand5 = 4*gs5_.cwiseProduct(gs5_).cwiseQuotient(ws5_) +
4*dws5_.cwiseProduct(gs5_).cwiseQuotient(ws5_.cwiseProduct(ws5_)) +
dws5_.cwiseProduct(dws5_).cwiseQuotient(ws5_.cwiseProduct(ws5_.cwiseProduct(ws5_)));
s0 << std::complex<double>(0,1)*integrate(ws_, ws5_);
s1 << integrate(gs_, gs5_);
s1(0) = std::log(std::sqrt(ws_(0)/ws_(5))) - s1(0);
s2 << integrate(integrand6, integrand5);
s2(0) = -1/4.0*(dws_(5)/std::pow(ws_(5),2)+2.0*gs_(5)/ws_(5)-
dws_(0)/std::pow(ws_(0),2)-2.0*gs_(0)/ws_(0))-1/8.0*s2(0);
s_ << s0(0), s1(0), std::complex<double>(0,1)*s2(0), 0.0;
s_error << s0(1), s1(1), std::complex<double>(0,-1/8)*s2(1), 0.0;
};
class WKBSolver3 : public WKBSolver
{
private:
void dds();
void dsi();
void dsf();
void s();
public:
WKBSolver3();
WKBSolver3(de_system &de_sys, int);
};
WKBSolver3::WKBSolver3(){
};
WKBSolver3::WKBSolver3(de_system &de_sys, int order) : WKBSolver(de_sys, order){
};
void WKBSolver3::dds(){
dds_ << std::complex<double>(0,1)*d1w1_,
1.0/(ws_(0)*ws_(0))*(d1w1_*d1w1_)/2.0-1.0/ws_(0)*d2w1_/2.0-d1g1_,
-std::complex<double>(0,1.0/8.0)*(8.0*d1g1_*gs_(0)*(ws_(0)*ws_(0)*ws_(0))-4.0*d1w1_*(gs_(0)*gs_(0))*ws_(0)*ws_(0)+4.0*d2g1_*(ws_(0)*ws_(0)*ws_(0))-4.0*d1w1_*d1g1_*ws_(0)*ws_(0)+2.0*d3w1_*ws_(0)*ws_(0)-10.0*d1w1_*d2w1_*ws_(0)+9.0*(d1w1_*d1w1_*d1w1_))/(ws_(0)*ws_(0)*ws_(0)*ws_(0)),
(d4w1_*(ws_(0)*ws_(0)*ws_(0))+2.0*d3g1_*(ws_(0)*ws_(0)*ws_(0)*ws_(0))-9.0*d1w1_*d3w1_*ws_(0)*ws_(0)-6.0*(d2w1_*d2w1_)*ws_(0)*ws_(0) + (42.0*ws_(0)*(d1w1_*d1w1_)-4.0*(ws_(0)*ws_(0)*ws_(0))*((gs_(0)*gs_(0))+d1g1_))*d2w1_+(4.0*gs_(0)*(ws_(0)*ws_(0)*ws_(0)*ws_(0))-8.0*(ws_(0)*ws_(0)*ws_(0))*d1w1_)*d2g1_-30.0*(d1w1_*d1w1_*d1w1_*d1w1_)+12.0*ws_(0)*ws_(0)*((gs_(0)*gs_(0))+d1g1_)*(d1w1_*d1w1_)-16.0*d1w1_*d1g1_*gs_(0)*(ws_(0)*ws_(0)*ws_(0))+4.0*(d1g1_*d1g1_)*(ws_(0)*ws_(0)*ws_(0)*ws_(0)))/(ws_(0)*ws_(0)*ws_(0)*ws_(0)*ws_(0)*ws_(0))/8.0;
};
void WKBSolver3::dsi(){
dsi_ << std::complex<double>(0,1)*ws_(0),-1.0/ws_(0)*d1w1_/2.0-gs_(0),
std::complex<double>(0,1.0/8.0)*(-4.0*(gs_(0)*gs_(0))*ws_(0)*ws_(0)-4.0*d1g1_*ws_(0)*ws_(0)-2.0*d2w1_
*ws_(0)+3.0*(d1w1_*d1w1_))/(ws_(0)*ws_(0)*ws_(0)) ,
(d3w1_*ws_(0)*ws_(0)+2.0*d2g1_*(ws_(0)*ws_(0)*ws_(0))-6.0*d1w1_*d2w1_*ws_(0)+
6.0*(d1w1_*d1w1_*d1w1_)-4.0*((gs_(0)*gs_(0))+d1g1_)*ws_(0)*ws_(0)*d1w1_+4.0*d1g1_
*gs_(0)*(ws_(0)*ws_(0)*ws_(0)))/(ws_(0)*ws_(0)*ws_(0)*ws_(0)*ws_(0))/8.0;
};
void WKBSolver3::dsf(){
dsf_ << std::complex<double>(0,1)*ws_(5),-1.0/ws_(5)*d1w6_/2.0-gs_(5),
std::complex<double>(0,1.0/8.0)*(-4.0*(gs_(5)*gs_(5))*(ws_(5)*ws_(5))-4.0*d1g6_*(ws_(5)*ws_(5))-2.0*d2w6_
*ws_(5)+3.0*(d1w6_*d1w6_))/(ws_(5)*ws_(5)*ws_(5)) ,
(d3w6_*(ws_(5)*ws_(5))+2.0*d2g6_*(ws_(5)*ws_(5)*ws_(5))-6.0*d1w6_*d2w6_*ws_(5)+
6.0*(d1w6_*d1w6_*d1w6_)-4.0*((gs_(5)*gs_(5))+d1g6_)*(ws_(5)*ws_(5))*d1w6_+4.0*d1g6_
*gs_(5)*(ws_(5)*ws_(5)*ws_(5)))/(ws_(5)*ws_(5)*ws_(5)*ws_(5)*ws_(5))/8.0;
};
void WKBSolver3::s(){
Eigen::Matrix<std::complex<double>,2,1> s0, s1, s2;
Eigen::Matrix<std::complex<double>,6,1> integrand6;
Eigen::Matrix<std::complex<double>,5,1> integrand5;
integrand6 = 4.0*gs_.cwiseProduct(gs_).cwiseQuotient(ws_) +
4.0*dws_.cwiseProduct(gs_).cwiseQuotient(ws_.cwiseProduct(ws_)) +
dws_.cwiseProduct(dws_).cwiseQuotient(ws_.cwiseProduct(ws_.cwiseProduct(ws_)));
integrand5 = 4.0*gs5_.cwiseProduct(gs5_).cwiseQuotient(ws5_) +
4.0*dws5_.cwiseProduct(gs5_).cwiseQuotient(ws5_.cwiseProduct(ws5_)) +
dws5_.cwiseProduct(dws5_).cwiseQuotient(ws5_.cwiseProduct(ws5_.cwiseProduct(ws5_)));
s0 << std::complex<double>(0,1)*integrate(ws_, ws5_);
s1 << integrate(gs_, gs5_);
s1(0) = std::log(std::sqrt(ws_(0)/ws_(5))) - s1(0);
s2 << integrate(integrand6, integrand5);
s2(0) = -1/4.0*(dws_(5)/(ws_(5)*ws_(5))+2.0*gs_(5)/ws_(5)-
dws_(0)/(ws_(0)*ws_(0))-2.0*gs_(0)/ws_(0))-1/8.0*s2(0);
std::complex<double> s3 = (1/4.0*(gs_(5)*gs_(5)/(ws_(5)*ws_(5)) -
gs_(0)*gs_(0)/(ws_(0)*ws_(0))) + 1/4.0*(d1g6_/(ws_(5)*ws_(5)) -
d1g1_/(ws_(0)*ws_(0)))-3/16.0*(dws_(5)*dws_(5)/(ws_(5)*ws_(5)*ws_(5)*ws_(5)) -
dws_(0)*dws_(0)/(ws_(0)*ws_(0)*ws_(0)*ws_(0))) + 1/8.0*(d2w6_/(ws_(5)*ws_(5)*ws_(5)) -
d2w1_/(ws_(0)*ws_(0)*ws_(0))));
s_ << s0(0), s1(0), std::complex<double>(0,1)*s2(0), s3;
s_error << s0(1), s1(1), std::complex<double>(0,-1.0/8.0)*s2(1), 0.0;
};