rl_raylib  1.1.10
rl_DielectricData.cc
1 // File: rl_DielectricData.cc
2 // Author: Terry Gaetz
3 //
4 // --8<--8<--8<--8<--
5 //
6 // Copyright (C) 2006, 2007 Smithsonian Astrophysical Observatory
7 //
8 // This file is part of rl_raylib
9 //
10 // rl_raylib is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License
12 // as published by the Free Software Foundation; either version 2
13 // of the License, or (at your option) any later version.
14 //
15 // rl_raylib is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the
22 // Free Software Foundation, Inc.
23 // 51 Franklin Street, Fifth Floor
24 // Boston, MA 02110-1301, USA
25 //
26 // -->8-->8-->8-->8--
27 
28 // Description: organize dielectric constant information
29 // into a bsearchable array
30 //
31 // History
32 //--------
33 // 0.2.0 tjg 1998-Jun-23 convert to C++
34 // 0.1.0 tjg 1998-Jun-17 rename to dielectricdata.c; extensive revisions.
35 // 0.0.1 tjg 1995-May-18 original
36 
37 #include "rl_DielectricData.h"
38 
39 #include <cstdlib> // system includes
40 #include <cstring>
41 #include <cmath>
42 #include <cfloat> // DBL_MAX
43 
44 using namespace std;
45 
46 #define EFFECTIVELY_ZERO 1.0e-30
47 
48 //=========================================================================
49 // dtor, ctors...
50 
51 //-------------------------------------------------------------------------
54 {
55  if ( decrement_ ) { delete [] decrement_; }
56 }
57 
58 //-------------------------------------------------------------------------
61  : nelts_( other.nelts_ )
62  , decrement_( new rl_DielectricDataBinPOD[other.nelts_] )
63  , emin_( other.emin_ )
64  , emax_( other.emax_ )
65  , bulkdensity_( other.bulkdensity_ )
66  , interp_mode_( other.interp_mode_ )
67 {
68  memcpy( decrement_, other.decrement_,
69  nelts_ * sizeof( rl_DielectricDataBinPOD ) );
70 }
71 
72 //-------------------------------------------------------------------------
75  size_t num_pts,
76  rl_Traits::EInterpMode interp_mode,
77  double bulk_density )
78 {
79  init( diel, num_pts, interp_mode, bulk_density );
80 }
81 
82 //-------------------------------------------------------------------------
85  size_t num_pts,
86  rl_Traits::EInterpMode interp_mode,
87  double bulk_density )
88 {
89  nelts_ = num_pts - 1;
90  interp_mode_ = interp_mode;
91 
92  emin_ = diel[0].energy_;
93  emax_ = diel[num_pts-1].energy_;
94 
95  bulkdensity_ = bulk_density;
96 
97  try {
98 
99  decrement_ = new rl_DielectricDataBinPOD[nelts_];
100 
101  } catch ( rl_Exception& e ) {
102 
103  e.set_rethrow_message( __FILE__, __LINE__ );
104  throw e;
105  }
106 
107  // read reflectance data into rl_DielectricBinPOD array
108 
109  size_t n;
110  for ( n = 0 ; n < nelts_ ; ++n )
111  {
112  decrement_[n].lo_.energy_ = diel[n].energy_;
113  decrement_[n].lo_.alpha_ = diel[n].alpha_ * bulk_density;;
114  decrement_[n].lo_.gamma_ = diel[n].gamma_ * bulk_density;;
115 
116  decrement_[n].hi_.energy_ = diel[n+1].energy_;
117  decrement_[n].hi_.alpha_ = diel[n+1].alpha_ * bulk_density;;
118  decrement_[n].hi_.gamma_ = diel[n+1].gamma_ * bulk_density;;
119  }
120 
121  // Set up for more efficient lin-log, log-lin, log-log interpolation;
122  // take logs now rather than for each ray interpolation.
123  // (Assumes that number of rays is much larger than number of table
124  // entries.)
125 
126  switch ( interp_mode_ ) {
127 
128  case rl_Traits::ELinLin:
129  break;
130 
131  case rl_Traits::ELinLog:
132  for ( n = 0 ; n < nelts_ ; ++n )
133  {
134  decrement_[n].lo_.energy_ = log(decrement_[n].lo_.energy_);
135  decrement_[n].hi_.energy_ = log(decrement_[n].hi_.energy_);
136  }
137  break;
138 
139  case rl_Traits::ELogLin:
140  for ( n = 0 ; n < nelts_ ; ++n )
141  {
142  decrement_[n].lo_.alpha_ = log(decrement_[n].lo_.alpha_);
143  decrement_[n].hi_.alpha_ = log(decrement_[n].hi_.alpha_);
144  decrement_[n].lo_.gamma_ = log(decrement_[n].lo_.gamma_);
145  decrement_[n].hi_.gamma_ = log(decrement_[n].hi_.gamma_);
146  }
147  break;
148 
149  case rl_Traits::ELogLog:
150  for ( n = 0 ; n < nelts_ ; ++n )
151  {
152  decrement_[n].lo_.energy_ = log(decrement_[n].lo_.energy_);
153  decrement_[n].hi_.energy_ = log(decrement_[n].hi_.energy_);
154  decrement_[n].lo_.alpha_ = log(decrement_[n].lo_.alpha_);
155  decrement_[n].hi_.alpha_ = log(decrement_[n].hi_.alpha_);
156  decrement_[n].lo_.gamma_ = log(decrement_[n].lo_.gamma_);
157  decrement_[n].hi_.gamma_ = log(decrement_[n].hi_.gamma_);
158  }
159  break;
160  }
161 }
162 
163 //=========================================================================
164 // accessors...
165 
166 /* forward declarations */
167 extern "C" {
168 static int diel_compare( void const* ck, void const* ce );
169 }
170 
171 //-------------------------------------------------------------------------
173 alpha_gamma( double energy, double& alpha, double& gamma )
174 {
175  int rc = 0;
176  if ( decrement_ ) // not a vacuum...
177  {
178  double w, en;
179 
180  switch ( interp_mode_ )
181  {
182  case rl_Traits::ELinLin: // intentional fall-through
183  case rl_Traits::ELogLin: en = energy;
184  break;
185 
186  case rl_Traits::ELinLog: // intentional fall-through
187  case rl_Traits::ELogLog: en = log(energy);
188  break;
189  }
190  if ( en < decrement_[0].lo_.energy_ )
191  { return -1; }
192 
193  if ( en > decrement_[nelts_-1].hi_.energy_ )
194  { return +1; }
195 
197  if ( en < decrement_[nelts_-1].hi_.energy_ )
198  {
199  diel = (rl_DielectricDataBinPOD*)
200  bsearch( &en, // key
201  decrement_, // array base
202  nelts_, // num elts
203  sizeof(rl_DielectricDataBinPOD), // sizeof elt
204  diel_compare // cmp func
205  );
206  if (! diel )
207  { rc = 1; } // didn't find requested energy...
208  }
209  else
210  {
211  diel = &decrement_[nelts_-1];
212  }
213 
214  // log interpolation in energy
215  w = (en - diel->lo_.energy_) / (diel->hi_.energy_ - diel->lo_.energy_);
216 
217  alpha = (1.0 - w) * diel->lo_.alpha_ + w * diel->hi_.alpha_;
218  gamma = (1.0 - w) * diel->lo_.gamma_ + w * diel->hi_.gamma_;
219 
220  #if defined (TEST_ALPHA_GAMMA)
221  fprintf( stdout, "___ ALPHA_GAMMA ___\n" );
222  fprintf( stdout, "E %.15e\n", en );
223  fprintf( stdout, "E alpha gamma lo %.15e %.15e %.15e\n",
224  diel->lo_.energy_, diel->lo_.alpha_, diel->lo_.gamma_ );
225  fprintf( stdout, "E alpha gamma hi %.15e %.15e %.15e\n",
226  diel->hi_.energy_, diel->hi_.alpha_, diel->hi_.gamma_ );
227  fprintf( stdout, "w %.15e\n", w );
228  fprintf( stdout, "alpha gamma %.15e %.15e\n",
229  alpha, gamma );
230  #endif
231 
232  switch ( interp_mode_ )
233  {
234  case rl_Traits::ELinLin: // intentional fall-through
235  case rl_Traits::ELinLog: break;
236 
237  case rl_Traits::ELogLin: // intentional fall-through
238  case rl_Traits::ELogLog: alpha = exp(alpha);
239  gamma = exp(gamma);
240  break;
241  }
242  }
243  else
244  {
245  alpha = 0.0; // vacuum case...
246  gamma = 0.0;
247  }
248 
249  return rc;
250 }
251 
252 //-------------------------------------------------------------------------
253 //
254 // compare two nodes based on a numeric ordering of the energy field
255 
256 int diel_compare( void const* ck, // search key
257  void const* ce // array element
258  )
259 {
260  double *pk = (double*) ck;
261 
264 
265  if ( *pk < pe->lo_.energy_ )
266  {
267  return -1;
268  }
269  else if ( *pk >= pe->hi_.energy_ )
270  {
271  return +1;
272  }
273  else
274  {
275  return 0;
276  }
277 }
rl_Traits::rl_DielectricPOD lo_
lower edge of energy bin
~rl_DielectricData()
Non-virtual detructor.
void init(rl_Traits::rl_DielectricPOD const *diel, size_t num_pts, rl_Traits::EInterpMode interp_mode, double bulk_density=1.0)
Initialization function.
linear in energy, linear in optical constants.
Definition: rl_Traits.h:71
log in energy, log in optical constants.
Definition: rl_Traits.h:74
rl_DielectricData()
Default constructor.
linear in energy, log in optical constants.
Definition: rl_Traits.h:73
double alpha_
dielectric decrement, real part
Definition: rl_Traits.h:98
The exception thrown by the rl_RayLib and rl_RaySupLib libraries.
Definition: rl_Exception.h:36
double gamma_
dielectric decrement, imag part
Definition: rl_Traits.h:100
log in energy, linear in optical constants.
Definition: rl_Traits.h:72
int alpha_gamma(double energy, double &alpha, double &gamma)
Evaluate the dielectric decrements, alpha and gamma, at the given energy.
double energy_
energy (keV)
Definition: rl_Traits.h:96
rl_Traits::rl_DielectricPOD hi_
upper edge of energy bin
A class encapsulating the dielectric data (alpha, gamma) as a function of energy.
EInterpMode
Enumeration specifying the interpolation of the optical constants.
Definition: rl_Traits.h:69
A POD describing the lower and upper edge of an energy bin.