00001 #ifndef NEW_YLMEXPANSION_H
00002 #define NEW_YLMEXPANSION_H
00003
00004 #include "objects3d.h"
00005 #include "objects1d.h"
00006 #include "sf.h"
00007 #include "cheezyparser.h"
00008 #include "utils.h"
00009 #include "constants.h"
00010 #include <complex>
00011 #include <map>
00012 #include <sstream>
00013 #include <fstream>
00014
00015 typedef complex<double> double_complex;
00016
00017 #define EXTENSION ".coral"
00018
00019 using namespace std;
00020
00021
00024
00025 class CHarmonicBasisFunction{
00026 public:
00027 int l;
00028 CHarmonicBasisFunction(int _l=0): l(_l){}
00029 CHarmonicBasisFunction(const CHarmonicBasisFunction& other):l(other.l){}
00030 virtual ~CHarmonicBasisFunction(void){}
00031 bool operator==(const CHarmonicBasisFunction& other) const{return other.l==l;}
00032 bool operator<(const CHarmonicBasisFunction& other) const{return l<other.l;}
00033 virtual double getValue(double theta, double phi) const=0;
00034 virtual double getValue(double x, double y, double z) const=0;
00035 string termName(void) const{string s;stringstream ss; ss<<"_"<<l; ss>>s; return s;}
00036 };
00037
00038
00040
00041 class CSphericalHarmonicBasisFunction: public CHarmonicBasisFunction{
00042 public:
00043 int l;
00044 int m;
00045 bool realpart;
00046 CSphericalHarmonicBasisFunction(int _l=0, int _m=0, bool _re=true):
00047 l(_l), m(_m), realpart(_re){}
00048 CSphericalHarmonicBasisFunction(const CSphericalHarmonicBasisFunction& other):
00049 l(other.l),m(other.m),realpart(other.realpart){}
00050 virtual ~CSphericalHarmonicBasisFunction(void){}
00051 bool operator==(const CSphericalHarmonicBasisFunction& other) const
00052 {return (other.l==l)&&(other.m==m)&&(other.realpart==realpart);}
00053 bool operator<(const CSphericalHarmonicBasisFunction& other) const{
00054 if (l<other.l) return true;
00055 else if (m<other.m) return true;
00056 else if (realpart==other.realpart) return false;
00057 else return other.realpart;
00058 }
00059 double getValue(double theta, double phi) const
00060 {if (realpart) return SpherHarmonics::ReYlm(l,m,theta,phi); else return SpherHarmonics::ImYlm(l,m,theta,phi);}
00061 double getValue(double x, double y, double z) const
00062 {if (realpart) return SpherHarmonics::ReYlm(l,m,x,y,z); else return SpherHarmonics::ImYlm(l,m,x,y,z);}
00063 string termName(void) const
00064 {string s;stringstream ss; ss<<"_"<<l<<"_"<<m<<"_"; if (realpart) ss<<"re"; else ss<<"im"; ss>>s; return s;}
00065 };
00066
00067
00069
00070 class CCartesianHarmonicBasisFunction: public CHarmonicBasisFunction{
00071 public:
00072 int lx, ly, lz;
00073 CCHCalc cartHarm;
00074 CCartesianHarmonicBasisFunction(int _lx=0, int _ly=0, int _lz=0):
00075 lx(_lx),ly(_ly),lz(_lz){}
00076 CCartesianHarmonicBasisFunction(const CCartesianHarmonicBasisFunction& other):
00077 lx(other.lx),ly(other.ly),lz(other.lz){}
00078 virtual ~CCartesianHarmonicBasisFunction(void){}
00079 bool operator==(const CCartesianHarmonicBasisFunction& other) const
00080 {return (other.lx==lx)&&(other.ly==ly)&&(other.lz==lz);}
00081 bool operator<(const CCartesianHarmonicBasisFunction& other) const{
00082 int sum1 = lx+ly+lz, sum2=other.lx+other.ly+other.lz;
00083 if (sum1!=sum2) return (sum1<sum2);
00084 if (lx!=other.lx) return (lx<other.lx);
00085 if (ly!=other.ly) return (ly<other.ly);
00086 else return (lz<other.lz);
00087 }
00088 double getValue(double theta, double phi) const{
00089 double nx = sin(theta), ny = nx*sin(phi), nz = cos(theta);
00090 nx*=cos(phi);
00091 return const_cast<CCartesianHarmonicBasisFunction*>(this)->cartHarm.GetAFromE(lx,ly,lz,nx,ny,nz);
00092 }
00093 double getValue(double x, double y, double z) const
00094 {
00095 double r = sqrt( x*x+y*y+z*z );
00096 if ( r < 1e-10 ) return const_cast<CCartesianHarmonicBasisFunction*>(this)->cartHarm.GetAFromE(lx,ly,lz,0.,0.,0.);
00097 return const_cast<CCartesianHarmonicBasisFunction*>(this)->cartHarm.GetAFromE(lx,ly,lz,x/r,y/r,z/r);
00098 }
00099 string termName(void) const
00100 {string s;stringstream ss; ss<<"_"<<lx<<"_"<<ly<<"_"<<lz; ss>>s; return s;}
00101 };
00102
00103
00112
00113 template< class TBas, class TObj >
00114 class CHarmonicExpansion : public CObject3d, public map< TBas, TObj > {
00115
00116 public:
00117
00118 string storage_directory;
00119 string file_prefix;
00120 int lmax;
00121 bool skip_odd_l;
00122 typedef typename CHarmonicExpansion< TBas, TObj >::iterator term_iterator;
00123 typedef typename CHarmonicExpansion< TBas, TObj >::const_iterator const_term_iterator;
00124
00125
00126 CHarmonicExpansion(void): storage_directory("."), file_prefix("term"), lmax(0), skip_odd_l(false) {}
00127 CHarmonicExpansion(int _lmax, bool _skip, string _sd, string _fp = "term" ):
00128 storage_directory(_sd), file_prefix(_fp), lmax(_lmax), skip_odd_l(_skip) {}
00129 virtual ~CHarmonicExpansion(void){}
00130
00131
00133 bool Read(const parameterMap& s){
00134 bool result(CObject3d::Read(s));
00135 lmax = parameter::getI(s,"lmax",0);
00136 if (s.find("skip_odd_l")==s.end())
00137 MESSAGE << "Looking for skip_odd_l flag, make sure you have reset this in any class that inherits from CHarmonicExpansion"<<ENDM_WARN;
00138 skip_odd_l = parameter::getB(s,"skip_odd_l",true);
00139 if ((skip_odd_l)&&(IS_ODD(lmax))) {lmax=lmax-1;}
00140
00141 storage_directory = parameter::getS(s,"storage_directory",storage_directory);
00142 file_prefix = parameter::getS(s,"file_prefix",file_prefix);
00143 return result;
00144 }
00145
00146
00148 bool Write(parameterMap& s){
00149 bool result=CObject3d::Write(s);
00150 parameter::set(s,"lmax",lmax);
00151 parameter::set(s,"skip_odd_l",skip_odd_l);
00152 parameter::set(s,"file_prefix",file_prefix);
00153 parameter::set(s,"storage_directory",storage_directory);
00154 return result;
00155 }
00156
00157
00159 virtual bool writeTerms( void ){
00160 bool result=true;
00161 for ( term_iterator it=CHarmonicExpansion< TBas, TObj >::begin(); it!=CHarmonicExpansion< TBas, TObj >::end(); ++it ){
00162 if (keepTerm(it)) {
00163 parameterMap outParams;
00164 it->second.Write(outParams);
00165 string filename = storage_directory+"/"+file_prefix+(it->first.termName())+EXTENSION;
00166 ofstream oFile( filename.c_str() );
00167 if (!oFile) throw MESSAGE << "Writing term "<<it->first.termName()<<" to "<< filename <<" failed"<<ENDM_SEVERE;
00168 result = result&&(oFile<<outParams);
00169 }
00170 }
00171 return result;
00172 }
00173
00174
00176 virtual bool fillTerms( void )=0;
00177
00178
00180 bool keepTerm( const_term_iterator it ) const
00181 {return (it->first.l<=lmax) && !( IS_ODD(it->first.l)&&(skip_odd_l) );}
00182
00183
00185 double getValueSphr(double r, double theta, double phi) const{
00186 double ans=0.0;
00187 for ( const_term_iterator it=CHarmonicExpansion< TBas, TObj >::begin(); it!=CHarmonicExpansion< TBas, TObj >::end(); ++it ){
00188 if (keepTerm(it))
00189 ans += SQRTFOURPI*(it->second.getValue(r))*(it->first.getValue(r,theta,phi));
00190 }
00191 return ans;
00192 }
00193
00194
00196 double getErrorSphr(double r, double theta, double phi) const{
00197 double ans=0.0;
00198 for ( const_term_iterator it=CHarmonicExpansion< TBas, TObj >::begin(); it!=CHarmonicExpansion< TBas, TObj >::end(); ++it ){
00199 if (keepTerm(it))
00200 ans+=SQRTFOURPI*(it->second.getError(r))*(it->first.getValue(r,theta,phi));
00201 }
00202 return ans;
00203 }
00204
00205
00206
00208 double getValueCart(double rS, double rO, double rL) const{
00209 double r=sqrt(rS*rS+rO*rO+rL*rL),ans=0.0;
00210 for ( const_term_iterator it=CHarmonicExpansion< TBas, TObj >::begin(); it!=CHarmonicExpansion< TBas, TObj >::end(); ++it ){
00211 if (keepTerm(it))
00212 ans+=SQRTFOURPI*(it->second.getValue(r))*(it->first.getValue(rS,rO,rL));
00213 }
00214 return ans;
00215 }
00216
00217
00219 double getErrorCart(double rS, double rO, double rL) const{
00220 double r=sqrt(rS*rS+rO*rO+rL*rL),ans=0.0;
00221 for ( const_term_iterator it=CHarmonicExpansion< TBas, TObj >::begin(); it!=CHarmonicExpansion< TBas, TObj >::end(); ++it){
00222 if (keepTerm(it))
00223 ans+=SQRTFOURPI*(it->second.getError(r))*(it->first.getValue(rS,rO,rL));
00224 }
00225 return ans;
00226 }
00227
00228 };
00229
00230
00231
00234
00235 template< class TObj >
00236 class CSphericalHarmonicExpansion: public CHarmonicExpansion< CSphericalHarmonicBasisFunction, TObj >{
00237
00238 public:
00239
00240 typedef typename CSphericalHarmonicExpansion< TObj >::iterator term_iterator;
00241 typedef typename CSphericalHarmonicExpansion< TObj >::const_iterator const_term_iterator;
00242
00243
00244 CSphericalHarmonicExpansion(void){}
00245 CSphericalHarmonicExpansion(int _lmax, bool _skip, string _sd=".", string _fp="term"):
00246 CHarmonicExpansion< CSphericalHarmonicBasisFunction, TObj >(_lmax,_skip,_sd,_fp){}
00247 ~CSphericalHarmonicExpansion(void){}
00248
00249
00251 virtual bool readTerms( void ){
00252 bool result = false;
00253 int lstep=1; if (this->skip_odd_l) lstep=2;
00254 for (int l=0; l<=this->lmax; l+=lstep){
00255 for (int m=0; m<=l; ++m){
00256 bool reim=false;
00257 for (int im=0; im<2; ++im){
00258 reim=!reim;
00259 if (!(m==0 && !reim)) {
00260 CSphericalHarmonicBasisFunction key(l,m,reim);
00261 cout << " Reading term "<<key.termName()<<flush;
00262 string filename = this->storage_directory+"/"+this->file_prefix+(key.termName())+EXTENSION;
00263 ifstream iFile( filename.c_str() );
00264 parameterMap inParams;
00265 cout <<" .."<<flush;
00266 if (iFile) {
00267 iFile >> inParams;
00268 result = true;
00269 TObj obj;
00270 cout <<".."<<flush;
00271 obj.Read(inParams);
00272 cout <<".."<<flush;
00273 insert(make_pair(key,obj));
00274 cout <<" OK"<<endl;
00275 } else {
00276 MESSAGE << "Could not load term w/ filename "<<filename<<ENDM_WARN;
00277 }
00278 }
00279 }
00280 }
00281 }
00282 return result;
00283 }
00284
00285
00287 bool fillTerms( void ){
00288 bool result = false;
00289 int lstep=1; if (this->skip_odd_l) lstep=2;
00290 for (int l=0; l<=this->lmax; l+=lstep){
00291 for (int m=0; m<=l; ++m){
00292 bool reim=false;
00293 for (int im=0; im<2; ++im){
00294 reim=!reim;
00295 if (!(m==0 && !reim)) {
00296 CSphericalHarmonicBasisFunction key(l,m,reim);
00297 TObj obj;
00298 obj.l=l;
00299 obj.m=m;
00300 obj.realpart=reim;
00301 insert(make_pair(key,obj));
00302 }
00303 }
00304 }
00305 }
00306 return result;
00307 }
00308
00309
00310
00312 double_complex getValueSphr(int l, int m, double r){
00313 const_term_iterator riter=find(l,abs(m),true);
00314 const_term_iterator iiter=find(l,abs(m),false);
00315 double repart(0.), impart(0.);
00316 if (riter!=CHarmonicExpansion< CSphericalHarmonicBasisFunction, TObj >::end()) repart=riter->second.getValue(r);
00317 if (iiter!=CHarmonicExpansion< CSphericalHarmonicBasisFunction, TObj >::end()) impart=iiter->second.getValue(r);
00318 if (m>=0) {
00319 return double_complex(repart, impart);
00320 } else {
00321 return static_cast<double_complex>(NEGONE_TO_THE(abs(m)))*double_complex(repart, -impart);
00322 }
00323 }
00324
00325
00327 double_complex getErrorSphr(int l, int m, double r){
00328 const_term_iterator riter=find(l,abs(m),true);
00329 const_term_iterator iiter=find(l,abs(m),false);
00330 double repart(0.), impart(0.);
00331 if (riter!=CHarmonicExpansion< CSphericalHarmonicBasisFunction, TObj >::end()) repart=riter->second.getError(r);
00332 if (iiter!=CHarmonicExpansion< CSphericalHarmonicBasisFunction, TObj >::end()) impart=iiter->second.getError(r);
00333 if (m>=0) {
00334 return double_complex(repart, impart);
00335 } else {
00336 return static_cast<double_complex>(NEGONE_TO_THE(abs(m)))*double_complex(repart, -impart);
00337 }
00338 }
00339
00340
00342 term_iterator find(int l, int m, bool rpart){
00343 return CHarmonicExpansion< CSphericalHarmonicBasisFunction, TObj >::find(CSphericalHarmonicBasisFunction(l,m,rpart));
00344 }
00345
00346
00350 TObj& getItem(int l, int m, bool rpart)
00351 {return (*this)[CSphericalHarmonicBasisFunction(l,m,rpart)];}
00352 TObj& operator()(int l, int m, bool rpart)
00353 {return (*this)[CSphericalHarmonicBasisFunction(l,m,rpart)];}
00354 TObj getItem(int l, int m, bool rpart) const
00355 {return (*this)[CSphericalHarmonicBasisFunction(l,m,rpart)];}
00356 TObj operator()(int l, int m, bool rpart) const
00357 {return (*this)[CSphericalHarmonicBasisFunction(l,m,rpart)];}
00358 };
00359
00360 #endif