rl_DielectricData.cc

00001 // File:   rl_DielectricData.cc
00002 // Author: Terry Gaetz
00003 //
00004 // --8<--8<--8<--8<--
00005 //
00006 // Copyright (C) 2006, 2007 Smithsonian Astrophysical Observatory
00007 //
00008 // This file is part of rl_raylib
00009 //
00010 // rl_raylib is free software; you can redistribute it and/or
00011 // modify it under the terms of the GNU General Public License
00012 // as published by the Free Software Foundation; either version 2
00013 // of the License, or (at your option) any later version.
00014 //
00015 // rl_raylib is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU General Public License
00021 // along with this program; if not, write to the 
00022 //       Free Software Foundation, Inc. 
00023 //       51 Franklin Street, Fifth Floor
00024 //       Boston, MA  02110-1301, USA
00025 //
00026 // -->8-->8-->8-->8--
00027 
00028 // Description: organize dielectric constant information 
00029 //              into a bsearchable array
00030 //
00031 // History
00032 //--------
00033 // 0.2.0  tjg  1998-Jun-23 convert to C++
00034 // 0.1.0  tjg  1998-Jun-17 rename to dielectricdata.c; extensive revisions.
00035 // 0.0.1  tjg  1995-May-18 original
00036 
00037 #include "rl_DielectricData.h"
00038 
00039 #include <cstdlib>     // system includes
00040 #include <cstring>
00041 #include <cmath>
00042 #include <cfloat>      // DBL_MAX
00043 
00044 using namespace std;
00045 
00046 #define EFFECTIVELY_ZERO 1.0e-30
00047 
00048 //=========================================================================
00049 // dtor, ctors...
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   // read reflectance data into rl_DielectricBinPOD array
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   // Set up for more efficient lin-log, log-lin, log-log interpolation; 
00125   // take logs now rather than for each ray interpolation.
00126   // (Assumes that number of rays is much larger than number of table
00127   //  entries.)
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 // accessors...
00168 
00169 /* forward declarations */
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_ )            // not a vacuum...
00180   {
00181     double               w, en;
00182 
00183     switch ( interp_mode_ )
00184     {
00185     case rl_Traits::ELinLin:   // intentional fall-through
00186     case rl_Traits::ELogLin:   en = energy;
00187                                break;
00188   
00189     case rl_Traits::ELinLog:   // intentional fall-through
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,                              // key
00204                            decrement_,                       // array base
00205                            nelts_,                           // num elts
00206                            sizeof(rl_DielectricDataBinPOD),  // sizeof elt
00207                            diel_compare                      // cmp func
00208                          );
00209       if (! diel )
00210       { rc = 1; }   // didn't find requested energy...
00211     }
00212     else
00213     {
00214       diel = &decrement_[nelts_-1];
00215     }
00216   
00217     // log interpolation in energy
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:   // intentional fall-through
00238     case rl_Traits::ELinLog:   break;
00239 
00240     case rl_Traits::ELogLin:   // intentional fall-through
00241     case rl_Traits::ELogLog:   alpha = exp(alpha);
00242                                gamma = exp(gamma);
00243                                break;
00244     }
00245   }
00246   else
00247   {
00248     alpha = 0.0;       // vacuum case...
00249     gamma = 0.0;
00250   }
00251 
00252   return rc;
00253 }
00254 
00255 //-------------------------------------------------------------------------
00256 //
00257 // compare two nodes based on a numeric ordering of the energy field
00258 
00259 int diel_compare( void const* ck,   // search key
00260                   void const* ce    // array element
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 }

Generated on Mon Nov 3 18:15:05 2008 for rl_raylib by  doxygen 1.5.6