rl_DielectricData.cc
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "rl_DielectricData.h"
00038
00039 #include <cstdlib>
00040 #include <cstring>
00041 #include <cmath>
00042 #include <cfloat>
00043
00044 using namespace std;
00045
00046 #define EFFECTIVELY_ZERO 1.0e-30
00047
00048
00049
00050
00051
00052 rl_DielectricData::
00053 ~rl_DielectricData()
00054 {
00055 if ( decrement_ ) { delete [] decrement_; }
00056 }
00057
00058
00059 rl_DielectricData::
00060 rl_DielectricData( rl_DielectricData const& other )
00061 throw ( rl_Exception )
00062 : nelts_( other.nelts_ )
00063 , decrement_( new rl_DielectricDataBinPOD[other.nelts_] )
00064 , emin_( other.emin_ )
00065 , emax_( other.emax_ )
00066 , bulkdensity_( other.bulkdensity_ )
00067 , interp_mode_( other.interp_mode_ )
00068 {
00069 memcpy( decrement_, other.decrement_,
00070 nelts_ * sizeof( rl_DielectricDataBinPOD ) );
00071 }
00072
00073
00074 rl_DielectricData::
00075 rl_DielectricData( rl_Traits::rl_DielectricPOD const* diel,
00076 size_t num_pts,
00077 rl_Traits::EInterpMode interp_mode,
00078 double bulk_density )
00079 throw ( rl_Exception )
00080 {
00081 init( diel, num_pts, interp_mode, bulk_density );
00082 }
00083
00084
00085 void rl_DielectricData::
00086 init( rl_Traits::rl_DielectricPOD const* diel,
00087 size_t num_pts,
00088 rl_Traits::EInterpMode interp_mode,
00089 double bulk_density )
00090 throw ( rl_Exception )
00091 {
00092 nelts_ = num_pts - 1;
00093 interp_mode_ = interp_mode;
00094
00095 emin_ = diel[0].energy_;
00096 emax_ = diel[num_pts-1].energy_;
00097
00098 bulkdensity_ = bulk_density;
00099
00100 try {
00101
00102 decrement_ = new rl_DielectricDataBinPOD[nelts_];
00103
00104 } catch ( rl_Exception& e ) {
00105
00106 e.set_rethrow_message( __FILE__, __LINE__ );
00107 throw e;
00108 }
00109
00110
00111
00112 size_t n;
00113 for ( n = 0 ; n < nelts_ ; ++n )
00114 {
00115 decrement_[n].lo_.energy_ = diel[n].energy_;
00116 decrement_[n].lo_.alpha_ = diel[n].alpha_ * bulk_density;;
00117 decrement_[n].lo_.gamma_ = diel[n].gamma_ * bulk_density;;
00118
00119 decrement_[n].hi_.energy_ = diel[n+1].energy_;
00120 decrement_[n].hi_.alpha_ = diel[n+1].alpha_ * bulk_density;;
00121 decrement_[n].hi_.gamma_ = diel[n+1].gamma_ * bulk_density;;
00122 }
00123
00124
00125
00126
00127
00128
00129 switch ( interp_mode_ ) {
00130
00131 case rl_Traits::ELinLin:
00132 break;
00133
00134 case rl_Traits::ELinLog:
00135 for ( n = 0 ; n < nelts_ ; ++n )
00136 {
00137 decrement_[n].lo_.energy_ = log(decrement_[n].lo_.energy_);
00138 decrement_[n].hi_.energy_ = log(decrement_[n].hi_.energy_);
00139 }
00140 break;
00141
00142 case rl_Traits::ELogLin:
00143 for ( n = 0 ; n < nelts_ ; ++n )
00144 {
00145 decrement_[n].lo_.alpha_ = log(decrement_[n].lo_.alpha_);
00146 decrement_[n].hi_.alpha_ = log(decrement_[n].hi_.alpha_);
00147 decrement_[n].lo_.gamma_ = log(decrement_[n].lo_.gamma_);
00148 decrement_[n].hi_.gamma_ = log(decrement_[n].hi_.gamma_);
00149 }
00150 break;
00151
00152 case rl_Traits::ELogLog:
00153 for ( n = 0 ; n < nelts_ ; ++n )
00154 {
00155 decrement_[n].lo_.energy_ = log(decrement_[n].lo_.energy_);
00156 decrement_[n].hi_.energy_ = log(decrement_[n].hi_.energy_);
00157 decrement_[n].lo_.alpha_ = log(decrement_[n].lo_.alpha_);
00158 decrement_[n].hi_.alpha_ = log(decrement_[n].hi_.alpha_);
00159 decrement_[n].lo_.gamma_ = log(decrement_[n].lo_.gamma_);
00160 decrement_[n].hi_.gamma_ = log(decrement_[n].hi_.gamma_);
00161 }
00162 break;
00163 }
00164 }
00165
00166
00167
00168
00169
00170 extern "C" {
00171 static int diel_compare( void const* ck, void const* ce );
00172 }
00173
00174
00175 int rl_DielectricData::
00176 alpha_gamma( double energy, double& alpha, double& gamma )
00177 {
00178 int rc = 0;
00179 if ( decrement_ )
00180 {
00181 double w, en;
00182
00183 switch ( interp_mode_ )
00184 {
00185 case rl_Traits::ELinLin:
00186 case rl_Traits::ELogLin: en = energy;
00187 break;
00188
00189 case rl_Traits::ELinLog:
00190 case rl_Traits::ELogLog: en = log(energy);
00191 break;
00192 }
00193 if ( en < decrement_[0].lo_.energy_ )
00194 { return -1; }
00195
00196 if ( en > decrement_[nelts_-1].hi_.energy_ )
00197 { return +1; }
00198
00199 rl_DielectricDataBinPOD* diel;
00200 if ( en < decrement_[nelts_-1].hi_.energy_ )
00201 {
00202 diel = (rl_DielectricDataBinPOD*)
00203 bsearch( &en,
00204 decrement_,
00205 nelts_,
00206 sizeof(rl_DielectricDataBinPOD),
00207 diel_compare
00208 );
00209 if (! diel )
00210 { rc = 1; }
00211 }
00212 else
00213 {
00214 diel = &decrement_[nelts_-1];
00215 }
00216
00217
00218 w = (en - diel->lo_.energy_) / (diel->hi_.energy_ - diel->lo_.energy_);
00219
00220 alpha = (1.0 - w) * diel->lo_.alpha_ + w * diel->hi_.alpha_;
00221 gamma = (1.0 - w) * diel->lo_.gamma_ + w * diel->hi_.gamma_;
00222
00223 #if defined (TEST_ALPHA_GAMMA)
00224 fprintf( stdout, "___ ALPHA_GAMMA ___\n" );
00225 fprintf( stdout, "E %.15e\n", en );
00226 fprintf( stdout, "E alpha gamma lo %.15e %.15e %.15e\n",
00227 diel->lo_.energy_, diel->lo_.alpha_, diel->lo_.gamma_ );
00228 fprintf( stdout, "E alpha gamma hi %.15e %.15e %.15e\n",
00229 diel->hi_.energy_, diel->hi_.alpha_, diel->hi_.gamma_ );
00230 fprintf( stdout, "w %.15e\n", w );
00231 fprintf( stdout, "alpha gamma %.15e %.15e\n",
00232 alpha, gamma );
00233 #endif
00234
00235 switch ( interp_mode_ )
00236 {
00237 case rl_Traits::ELinLin:
00238 case rl_Traits::ELinLog: break;
00239
00240 case rl_Traits::ELogLin:
00241 case rl_Traits::ELogLog: alpha = exp(alpha);
00242 gamma = exp(gamma);
00243 break;
00244 }
00245 }
00246 else
00247 {
00248 alpha = 0.0;
00249 gamma = 0.0;
00250 }
00251
00252 return rc;
00253 }
00254
00255
00256
00257
00258
00259 int diel_compare( void const* ck,
00260 void const* ce
00261 )
00262 {
00263 double *pk = (double*) ck;
00264
00265 rl_DielectricData::rl_DielectricDataBinPOD *pe
00266 = (rl_DielectricData::rl_DielectricDataBinPOD*)ce;
00267
00268 if ( *pk < pe->lo_.energy_ )
00269 {
00270 return -1;
00271 }
00272 else if ( *pk >= pe->hi_.energy_ )
00273 {
00274 return +1;
00275 }
00276 else
00277 {
00278 return 0;
00279 }
00280 }