# ifndef WAVEPACKET_H # define WAVEPACKET_H # ifndef _USE_MATH_DEFINES # define _USE_MATH_DEFINES # endif # include # include # include # include "cvector_3.h" using namespace std; /** @file wpmd.h @brief Classes to handle Gaussian Wave Packets. */ // Constants const double MIN_EXP_ARG = -15.; // Minimum noticeable argument for exp function class WavePacket; ///\en Template for v=der operation in \ref Wavepacket::int2phys_der() template struct eq_second : public binary_function { Type operator()(const Type& _Left, const Type& _Right) const{ return _Right; } }; ///\en Template for v=-der operation in \ref Wavepacket::int2phys_der() template struct eq_minus_second : public binary_function { Type operator()(const Type& _Left, const Type& _Right) const{ return -_Right; } }; ///\en Compares complex numbers on a per component basis. /// \return \retval 0 if all component differences are 0 within tolerance \a tol (EQUAL), /// \retval -1 for LESS /// \retval 2 for GREATER template< class CT > int compare_compl(const CT &a, const CT& b, double tol=0.){ double dd=real(a)-real(b); if(dd<-tol) return -1; if(dd>tol) return 1; dd=imag(a)-imag(b); if(dd<-tol) return -1; if(dd>tol) return 1; return 0; } ///\en Compares vectors on a per component basis. /// \return \retval 0 if all component differences are 0 within tolerance \a tol (EQUAL), /// \retval -1 for LESS /// \retval 2 for GREATER inline int compare_vec(const Vector_3 &a, const Vector_3& b, double tol=0.){ for(int i=0;i<3;i++){ double dd=a[i]-b[i]; if(dd<-tol) return -1; if(dd>tol) return 1; } return 0; } /// wavepacket is w(x)=exp(-a*x^2+b*x+lz) class WavePacket{ /// constructs a conjugate packet friend WavePacket conj(const WavePacket &wp); public: cdouble a; cVector_3 b; cdouble lz; WavePacket(const cdouble &sa=cdouble(1.,0.),const cVector_3 &sb=cVector_3(0.,0.), const cdouble &slz=0.): a(sa), b(sb), lz(slz){ } WavePacket operator*(const WavePacket& other) const { return WavePacket(a+other.a,b+other.b,lz+other.lz); } /// returns the integral of w(x) over 3D space cdouble integral() const { cdouble z = lz + b.norm2()/(4.*a); if(real(z) < MIN_EXP_ARG) return 0.; return pow(M_PI/a,3./2.)*exp(z); } /// init normalized packet with physical parameters: r0, p0, width, pw /// w(x)=(3/2pi width^(3/4)exp[-(3/(4 width^2)-i pw/(2*width) )(x-r)^2+i p (x-r)] void init(const double width=1., const Vector_3 &r=0., const Vector_3 &p=0., const double pw=0.){ a = (3./(2.*width) - cdouble(0.,1.)*pw)/(2.*width); b = (2.*a)*r + cdouble(0.,1.)*p; lz = log(3./(2.*M_PI*width*width))*(3./4.) + (-a*r.norm2() - cdouble(0.,1.)*(p*r)); } /// init normalized packet with complex parameters a and b /// w(x)=(3/2pi width^(3/4)exp[-(3/(4 width^2)-i pw/(2*width) )(x-r)^2+i p (x-r)] void init(const cdouble &a_, const cVector_3 &b_){ a = a_; b = b_; Vector_3 r = get_r(); double r2 = r.norm2(); lz = cdouble( log( real(a)*(2./M_PI) )*(3./4.) - r2*real(a), r2*imag(a) - r*imag(b) ); } cdouble operator()(const Vector_3 &x) const { return exp(lz - a*x.norm2() + b*x); } /// ajusts lz so that Integral[w*(conj(w))] is 1 after this operation WavePacket& normalize(){ //lz=0.; //lz=overlap(conj(*this)); //lz=(-1./2)*log(lz); Vector_3 r = get_r(); double r2 = r.norm2(); lz = cdouble( log( real(a)*(2./M_PI) )*(3./4.) - r2*real(a), r2*imag(a) - r*imag(b) ); return *this; } /// computes 3D overlap of wavepackets Inegral[w*other] cdouble overlap(const WavePacket &other) const{ WavePacket wp=(*this)*other; return wp.integral(); } /// returns translated packet to the position of r'=r+dr WavePacket translate(const Vector_3 &dr) const { WavePacket wp(a,b,lz); wp.b+=2*dr*a; Vector_3 r=get_r(); double dr2=(r+dr).norm2()-r.norm2(); wp.lz+=-a*dr2-cdouble(0.,(get_p()*dr)); return wp; } /// width double get_width() const{ return sqrt(3./4./real(a)); } /// width momentum double get_pwidth() const{ return -imag(a)*sqrt(3./real(a)); } /// both width and width momentum pair get_width_pars() const{ double c=sqrt(3./2./real(a)); return make_pair(c/2,-imag(a)*c); } /// position Vector_3 get_r() const { return real(b)/(2*real(a)); } /// momentum Vector_3 get_p() const { return imag(b) - real(b)*(imag(a)/real(a)); } ///\en Transforms derivatives of a function whith respect to WP parameters /// from internal into physical representation, i. e.:\n /// from df/d{are,aim,b0re,b0im,b1re,b1im,b2re,b2im} (8 values accessed by input iterator d_it in the given order)\n /// to df/d{x0,x1,x2}, df/d{p0,p1,p2}, df/dw, df/dpw /// The supplied inputs (val) are modified by op: val=op(val,phys_der). /// Use operation=eq_second for the supplied inputs to be replaced by new physical derivative values. /// The inpput and output locations may coinside, an internal buffer is used for transformation. template class operation, class d_it, class dfdx_it, class dfdp_it, class dfdw_it, class dfdpw_it> void int2phys_der(d_it dfdi_,dfdx_it dfdx, dfdp_it dfdp, dfdw_it dfdw, dfdpw_it dfdpw, double h_p=h_plank) const { operation op; double dfdi[8], dfn[8];// internal buffer for(int i=0;i<8;i++) dfdi[i]=*dfdi_++; double w=get_width(); Vector_3 r=get_r(); double t=3/(2*w*w*w); dfn[6]= -t*dfdi[0]-imag(a)*dfdi[1]/w; //dw dfn[7]=-dfdi[1]/(2*w*h_p); // dpw for(int i=0;i<3;i++){ dfn[i]= 2*real(a)*dfdi[2+2*i]+2*imag(a)*dfdi[2+2*i+1]; dfn[3+i]= dfdi[2+2*i+1]*(/*m_electron*/1./h_p) ; //*(h_plank/m_electron); dfn[7]+=-(r[i]*dfdi[2+2*i+1]/w)/h_p; dfn[6]+=-2*r[i]*(t*dfdi[2+2*i]+imag(a)*dfdi[2+2*i+1]/w); } int i=0; for(int k=0;k<3;k++) *dfdx++=op(*dfdx,dfn[i++]); for(int k=0;k<3;k++) *dfdp++=op(*dfdp,dfn[i++]); *dfdw=op(*dfdw,dfn[i++]); *dfdpw=op(*dfdpw,dfn[i++]); } ///\en Compares the wave packet to another on a per component basis. /// \return \retval 0 if all component differences are 0 within tolerance \a tol (EQUAL), /// \retval -1 for LESS /// \retval 2 for GREATER int compare(const WavePacket &other, double tol=0.) const { int res=compare_compl(a,other.a, tol); if(res) return res; for(int i=0;i<3;i++){ res=compare_compl(b[i],other.b[i]); if(res) return res; } return 0; } }; #if 0 double w=wk.get_width(); Vector_3 r=wk.get_r(); double t=3/(2*w*w*w); fe_w[ic1+k1]+= t*E_der[s1][indw1+8*k1]+imag(wk.a)*E_der[s1][indw1+8*k1+1]/w; fe_pw[ic1+k1]+=E_der[s1][indw1+8*k1+1]/(2*w*h_plank); for(int i=0;i<3;i++){ fe_x[ic1+k1][i]+= -2*real(wk.a)*E_der[s1][indw1+8*k1+2+2*i]-2*imag(wk.a)*E_der[s1][indw1+8*k1+2+2*i+1]; fe_p[ic1+k1][i]+= (-E_der[s1][indw1+8*k1+2+2*i+1])*(m_electron/h_plank); //*(h_plank/m_electron); fe_pw[ic1+k1]+=(r[i]*E_der[s1][indw1+8*k1+2+2*i+1]/w)/h_plank; fe_w[ic1+k1]+=2*r[i]*(t*E_der[s1][indw1+8*k1+2+2*i]+imag(wk.a)*E_der[s1][indw1+8*k1+2+2*i+1]/w); } #endif /// constructs a conjugate packet inline WavePacket conj(const WavePacket &wp){ return WavePacket(conj(wp.a),conj(wp.b),conj(wp.lz)); } # endif // WAVEPACKET_H