rl_DielectricLayer.cc

00001 // File:   rl_DielectricLayer.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 // #define DEBUG_DIELECTRICLAYER
00029 #define DIEL_GAMMA_NEGATIVE   1
00030 
00031 #include <rl_DielectricLayer.h>     // rl_DielectricLayer
00032 
00033 #include <cstring>                  // strlen strcpy
00034 #include <cstdio>                   // stdout
00035 // #include <cfloat>                   // DBL_MAX
00036 #include <mathconst/mathconst.h>    // M_PI
00037 
00038 #include <iomanip>
00039 
00040 using namespace std;
00041 
00042 //=========================================================================
00043 // dtor, ctors...
00044 
00045 //-------------------------------------------------------------------------
00046 rl_DielectricLayer::
00047 ~rl_DielectricLayer()
00048 { 
00049   if ( name_ ) { delete [] name_; } 
00050 }
00051 
00052 //-------------------------------------------------------------------------
00053 // default constructor:  initialize as an infinitely thick vacuum layer.
00054 
00055 rl_DielectricLayer::
00056 rl_DielectricLayer( char const layer_name[] )
00057   throw ( rl_Exception )
00058   : diel_info_()
00059   , thickness_(-1.0)
00060   , zcoat_(-1.0)
00061   , alpha_(0.0)
00062   , gamma_(0.0)
00063   , rtype_(rl_Traits::ERoughNone)
00064   , srough_(0.0)
00065   , lambda_(826.5)
00066   , prop_( complex(1.0,0.0) )
00067   , kt_perp_( complex(0.0,0.0) )
00068   , phase_factor_(0.0)
00069   , rflcoef_()
00070   , t_ij_()
00071   , t_ji_()
00072   , is_substrate_(rl_Traits::False)
00073 {
00074   try {
00075 
00076     if ( layer_name )
00077     { 
00078       name_ = new char[strlen(layer_name)+1];
00079     }
00080     else
00081     {
00082       name_ = new char[1];
00083       *name_ = '\0';
00084     }
00085 
00086   } catch ( std::exception& bad_alloc ) {
00087 
00088     char msg[] = "rl_DielectricLayer(layername): "
00089                  "unable to allocate space for the layer name";
00090 
00091     throw rl_Exception( msg );
00092   }
00093 }
00094 
00095 //-------------------------------------------------------------------------
00096 // DEEP Copy Constructor.
00097 
00098 rl_DielectricLayer::
00099 rl_DielectricLayer( rl_DielectricLayer const& other )
00100   throw ( rl_Exception )
00101   : diel_info_()
00102   , thickness_(-1.0)
00103   , zcoat_(-1.0)
00104   , alpha_(0.0)
00105   , gamma_(0.0)
00106   , rtype_(rl_Traits::ERoughNone)
00107   , srough_(0.0)
00108   , lambda_(826.5)
00109   , prop_( complex(1.0,0.0) )
00110   , kt_perp_( complex(0.0,0.0) )
00111   , phase_factor_(0.0)
00112   , rflcoef_()
00113   , t_ij_()
00114   , t_ji_()
00115   , is_substrate_(rl_Traits::False)
00116 {
00117   try {
00118 
00119     if ( other.name_ )
00120     {
00121       name_ = new char[strlen(other.name_)+1];
00122       strcpy( name_, other.name_ );
00123     }
00124     else
00125     {
00126       name_ = new char[1];
00127       *name_ = '\0';
00128     }
00129 
00130   } catch ( std::exception& bad_alloc ) {
00131 
00132     char msg[] = "rl_DielectricLayer copy constructor: "
00133                  "unable to allocate space for the layer name";
00134 
00135     throw rl_Exception( msg );
00136   }
00137 }
00138 
00139 //-------------------------------------------------------------------------
00140 
00141 rl_DielectricLayer::
00142 rl_DielectricLayer( rl_Traits::rl_DielectricPOD const* diel,
00143                     std::size_t                        ndielpts,
00144                     double                             layer_thickness,
00145                     double                             roughness,
00146                     rl_Traits::ERoughType              roughness_type,
00147                     rl_Traits::EInterpMode             interp_mode,
00148                     double                             bulkdensity,
00149                     char const*                        layer_name,
00150                     rl_Traits::Bool                    is_substrate )
00151   throw ( rl_Exception )
00152 { 
00153   init( diel, ndielpts, layer_thickness, roughness, roughness_type, 
00154         interp_mode, bulkdensity, layer_name, is_substrate ); 
00155 }
00156   
00157 //-------------------------------------------------------------------------
00158 
00159 void rl_DielectricLayer::
00160 init( rl_Traits::rl_DielectricPOD const* diel,
00161       std::size_t                        ndielpts,
00162       double                             layer_thickness,
00163       double                             roughness,
00164       rl_Traits::ERoughType              roughness_type,
00165       rl_Traits::EInterpMode             interp_mode,
00166       double                             bulkdensity,
00167       char const*                        layer_name,
00168       rl_Traits::Bool                    is_substrate )
00169   throw ( rl_Exception )
00170 {
00171   diel_info_.init( diel, ndielpts, interp_mode, bulkdensity );
00172 
00173   try {
00174 
00175     if ( layer_name )
00176     {
00177       name_ = new char[strlen(layer_name)+1];
00178       strcpy( name_, layer_name );
00179     }
00180     else
00181     {
00182       name_ = new char[1];
00183       *name_ = '\0';
00184     }
00185 
00186   } catch ( std::exception& bad_alloc ) {
00187 
00188     char msg[256] = "rl_DielectricLayer::init(...): "
00189                     "unable to allocate space for layer name";
00190 
00191     throw rl_Exception( msg );
00192   }
00193 
00194   thickness_    = layer_thickness;  // layer thickness (Angstroms)
00195   rtype_        = roughness_type;   // layer roughness type
00196   srough_       = roughness;        // roughness parameter (Angstroms)
00197   is_substrate_ = is_substrate;     // 0;  1, if this is the substrate,
00198 
00199   switch ( rtype_ )
00200   {
00201   case rl_Traits::ERoughDebyeWaller_RSAO    :           // fall through
00202   case rl_Traits::ERoughDebyeWaller_CSAO    :           // fall through
00203   case rl_Traits::ERoughDebyeWaller_Spiller :           // fall through
00204   case rl_Traits::ERoughNevotCroce          :           // fall through
00205   case rl_Traits::ERoughModifiedDebyeWaller :           // fall through
00206   case rl_Traits::ERoughNone                :  break;     
00207 
00208   default :
00209     { char msg[256];
00210       char const format[] = "rl_DielectricPODArray::init(...): "
00211                             "Invalid roughness type was %d\n";
00212       sprintf( msg, format, rtype_ );
00213       throw rl_Exception( msg );
00214     }
00215   } /* end rl_Traits::ERoughType cases */
00216 
00217 }
00218 
00219 //=========================================================================
00220 // mutators...
00221 
00222 //-------------------------------------------------------------------------
00223 int rl_DielectricLayer::
00224 setup_for( double energy, double sinphi )
00225 {
00226   lambda_ = 12.39854 / energy;       // wavelength (Angstrom)
00227 
00228   if ( rtype_ != rl_Traits::ERoughNone )
00229   {
00230     phase_factor_ = 2.0 * M_PI * srough_ / lambda_;
00231   }
00232   else
00233   {
00234     phase_factor_ = 0.0;
00235   }
00236 
00237   int rc = diel_info_.alpha_gamma( energy, alpha_, gamma_ );
00238 
00239   //-------------------
00240   // kt_perp_
00241   //
00242   // This is the component of the complex wave vector perpendicular
00243   // to the interface divided by k0, the magnitude of the wave vector
00244   // in the vacuum.
00245   //
00246   // The boundary condition at the interface requires that the component
00247   // of the wave vector parallel to the interface is the same for each
00248   // layer.  The perpendicular component is then
00249   //     k_{\perp,j} = \sqrt{ \sin^2 \phi_0 + \Delta \epsilon }
00250   // where \phi_0 is the graze angle in the vacuum and
00251   // \Delta\epsilon is the dielectric decrement, i.e.,
00252   // complex( -alpha, -gamma ).
00253   // Note that in obtaining k_{\perp,j} we take a complex square
00254   // root.  The imaginary part of the principal root is obtained
00255   // by multiplying b by the sign of gamma_.
00256 
00257   double const difab = sinphi * sinphi - alpha_;
00258   double const sumab = sqrt( difab * difab + gamma_ * gamma_ );
00259 
00260   // Force b to be evaluated to avoid sqrt(-tiny) when i86
00261   // extended FP registers in use.  Is there a g++ compiler option
00262   // to force this?  There's supposed to be a way to set the FP mode...
00263 
00264   double const a   = sqrt( (sumab + difab) / 2.0 );
00265   double const tmp =       (sumab - difab) / 2.0;
00266   double const b   = (tmp >= 0.0) ? sqrt( tmp ) : sqrt( -tmp );
00267 
00268   // the following ifdefs allow hardwiring the branch cut for efficiency
00269   #ifdef DIEL_GAMMA_GENERAL
00270     kt_perp_ = complex( a, ((gamma_ > 0.0) ? 1.0 : -1.0) * b );
00271   #else
00272     #ifdef DIEL_GAMMA_NEGATIVE
00273       kt_perp_ = complex( a, -b );
00274     #endif
00275     #ifdef DIEL_GAMMA_POSITIVE
00276       kt_perp_ = complex( a,  b );
00277     #endif
00278   #endif
00279 
00280   #if defined(DEBUG_DIELECTRICLAYER)
00281     fprintf(stdout, "\nDEBUG: ___SETUP_FOR___ %s ---------------------\n",
00282                      name_ );
00283     fprintf(stdout, "kt_perp_          (%.15e  %.15e)\n",
00284                      kt_perp_.real(),
00285                      kt_perp_.imag() );
00286     fprintf(stdout, "alpha_ gamma_     (%.15e  %.15e)\n",
00287                      alpha_, gamma_ );
00288     fprintf(stdout, "energy, sinphi    (%.15e  %.15e)\n",
00289                      energy, sinphi );
00290     fprintf(stdout, "difab sumab  tmp  (%.15e  %.15e  %.15e)\n",
00291                      difab, sumab, tmp );
00292     fprintf(stdout, "a, b              (%.15e  %.15e)\n",
00293                      a, b );
00294   #endif
00295 
00296   //-------------------
00297   // evaluate layer propagator
00298   // the layer propagator is exp( phase_factor )
00299 
00300   if (! rc )
00301   {
00302     if (! is_vacuum() && ! is_substrate() )
00303     {
00304       zcoat_ = 4.0 * M_PI * thickness_ / lambda_;  
00305          // dimensionless thickness of layer
00306 
00307       prop_ = exp( complex( -b * zcoat_, -a * zcoat_ ) );
00308     #if defined(DEBUG_DIELECTRICLAYER)
00309       fprintf(stdout, "zcoat_             %.15e\n",
00310                        zcoat_ );
00311       fprintf(stdout, "prop_ (r,i)       (%.15e  %.15e)\n",
00312                        prop_.real(), prop_.imag() );
00313     #endif
00314     }
00315   }
00316   return rc;  // 0 if successful
00317 }
00318 
00319 //-------------------------------------------------------------------------
00320 // calculate complex reflection coefficients at interface between 
00321 // this layer and layer immediately above it.
00322 
00323 void rl_DielectricLayer::
00324 reflect_amp( rl_DielectricLayer const& upper, double sinphi )
00325 {
00326   double  alpha_jm1 = upper.alpha_;
00327   double  gamma_jm1 = upper.gamma_;
00328   double  alpha_j   =       alpha_;
00329   double  gamma_j   =       gamma_;
00330 
00331   complex upper_delta_eps( -alpha_jm1, -gamma_jm1 );
00332   complex       delta_eps( -alpha_j,   -gamma_j   );
00333 
00334   complex eps_upper( upper_delta_eps + 1.0 );
00335   complex eps(             delta_eps + 1.0 );
00336 
00337   complex num_perp    =  upper.kt_perp_ - kt_perp_;
00338   complex denom_perp  =  upper.kt_perp_ + kt_perp_;
00339 
00340   rflcoef_.perp()     =  num_perp / denom_perp;
00341 
00342   #if defined(DEBUG_DIELECTRICLAYER)
00343     fprintf(stdout, "\nDEBUG: ___REFLECT_AMP___ ___AAA0___ --------\n");
00344     fprintf(stdout, "upper, this layer   (%s  %s)\n", 
00345                      upper.name_, name_);
00346     fprintf(stdout, "alpha, gamma (j-1): (%.15e, %.15e)\n",
00347                      alpha_jm1, gamma_jm1);
00348     fprintf(stdout, "alpha, gamma (j):   (%.15e, %.15e)\n",
00349                      alpha_j, gamma_j);
00350     fprintf(stdout, "rflcoef (perp)      (%.15e  %.15e)\n",
00351                      rflcoef_.perp().real(),
00352                      rflcoef_.perp().imag() );
00353     fprintf(stdout, "num_perp            (%.15e  %.15e)\n",
00354                      num_perp.real(),
00355                      num_perp.imag() );
00356     fprintf(stdout, "denom_perp          (%.15e  %.15e)\n",
00357                      denom_perp.real(),
00358                      denom_perp.imag() );
00359     fprintf(stdout, "upper.kt_perp_      (%.15e  %.15e)\n",
00360                      upper.kt_perp_.real(),
00361                      upper.kt_perp_.imag() );
00362     fprintf(stdout, "kt_perp_             %.15e  %.15e)\n",
00363                      kt_perp_.real(),
00364                      kt_perp_.imag() );
00365   #endif
00366 
00367   complex num_para    =        delta_eps * upper.kt_perp_;
00368           num_para   -=  upper_delta_eps *       kt_perp_;
00369           num_para   +=        num_perp;
00370 
00371   complex denom_para  =        delta_eps * upper.kt_perp_;
00372           denom_para +=  upper_delta_eps *       kt_perp_;
00373           denom_para +=        denom_perp;
00374 
00375   rflcoef_.para()     =  num_para / denom_para;
00376 
00377   double eps_epsupper_r  = alpha_jm1 * alpha_j - gamma_jm1 * gamma_j;
00378          eps_epsupper_r -= alpha_jm1 + alpha_j;
00379          eps_epsupper_r += 1.0;
00380    
00381   double eps_epsupper_i  = alpha_jm1 * gamma_j + gamma_jm1 * alpha_j;
00382          eps_epsupper_i -= gamma_jm1 + gamma_j;
00383 
00384   eps_epsupper_ = complex( eps_epsupper_r, eps_epsupper_i );
00385 
00386   #if defined(DEBUG_DIELECTRICLAYER)
00387     fprintf(stdout, "eps_epsupper (r,i): (%.15e, %.15e)\n",
00388                      eps_epsupper_r, eps_epsupper_i);
00389     fprintf(stdout, "num_para            (%.15e  %.15e)\n",
00390                      num_para.real(),
00391                      num_para.imag() );
00392     fprintf(stdout, "denom_perp          (%.15e  %.15e)\n",
00393                      denom_para.real(),
00394                      denom_para.imag() );
00395     fprintf(stdout, "rflcoef (para)      (%.15e  %.15e)\n",
00396                      rflcoef_.para().real(),
00397                      rflcoef_.para().imag() );
00398   #endif
00399 
00400   if (! is_substrate() )
00401   {
00402     t_ij_.perp() = 2.0 * upper.kt_perp_ / denom_perp;
00403     t_ji_.perp() = 2.0 *       kt_perp_ / denom_perp;
00404 
00405     t_ij_.para() = 2.0 * ( eps       * upper.kt_perp_ ) / denom_para;
00406     t_ji_.para() = 2.0 * ( eps_upper *       kt_perp_ ) / denom_para;
00407 
00408     tij_tji_perp_ = t_ij_.perp() * t_ji_.perp();
00409     tij_tji_para_ = t_ij_.para() * t_ji_.para();
00410 
00411     r_perp_          = rflcoef_.perp();
00412     r_para_          = rflcoef_.para();
00413     r2_perp_         = rflcoef_.perp() * rflcoef_.perp();
00414     r2_para_         = rflcoef_.para() * rflcoef_.para();
00415     r2_tij_tji_perp_ = r2_perp_ + tij_tji_perp_;
00416     r2_tij_tji_para_ = r2_para_ + tij_tji_para_;
00417 
00418     #if defined(DEBUG_DIELECTRICLAYER)
00419       fprintf(stdout, "t_ij_ (para)      (%.15e  %.15e)\n",
00420                        t_ij_.para().real(),
00421                        t_ij_.para().imag() );
00422       fprintf(stdout, "t_ji_ (para)      (%.15e  %.15e)\n",
00423                        t_ji_.para().real(),
00424                        t_ji_.para().imag() );
00425       fprintf(stdout, "t_ij_ (perp)      (%.15e  %.15e)\n",
00426                        t_ij_.perp().real(),
00427                        t_ij_.perp().imag() );
00428       fprintf(stdout, "t_ji_ (perp)      (%.15e  %.15e)\n",
00429                        t_ji_.perp().real(),
00430                        t_ji_.perp().imag() );
00431       fprintf(stdout, "tij_tji_perp_     (%.15e  %.15e)\n",
00432                        tij_tji_perp_.real(),
00433                        tij_tji_perp_.imag() );
00434       fprintf(stdout, "tij_tji_para_     (%.15e  %.15e)\n",
00435                        tij_tji_para_.real(),
00436                        tij_tji_para_.imag() );
00437       fprintf(stdout, "r_perp_           (%.15e  %.15e)\n",
00438                        r_perp_.real(),
00439                        r_perp_.imag() );
00440       fprintf(stdout, "r_para_           (%.15e  %.15e)\n",
00441                        r_para_.real(),
00442                        r_para_.imag() );
00443       fprintf(stdout, "r2_perp_          (%.15e  %.15e)\n",
00444                        r2_perp_.real(),
00445                        r2_perp_.imag() );
00446       fprintf(stdout, "r2_para_          (%.15e  %.15e)\n",
00447                        r2_para_.real(),
00448                        r2_para_.imag() );
00449       fprintf(stdout, "r2_tij_tji_perp_  (%.15e  %.15e)\n",
00450                        r2_tij_tji_perp_.real(),
00451                        r2_tij_tji_perp_.imag() );
00452       fprintf(stdout, "r2_tij_tji_para_  (%.15e  %.15e)\n",
00453                        r2_tij_tji_para_.real(),
00454                        r2_tij_tji_para_.imag() );
00455   #endif
00456 
00457   }
00458 
00459   switch ( rtype_ )
00460   {
00461   case rl_Traits::ERoughDebyeWaller_RSAO :
00462 
00463          apply_DebyeWaller_RSAO_factor( upper, sinphi );
00464          break;
00465 
00466   case rl_Traits::ERoughDebyeWaller_CSAO :
00467 
00468          apply_DebyeWaller_CSAO_factor( upper, sinphi );
00469          break;
00470 
00471   case rl_Traits::ERoughDebyeWaller_Spiller :
00472 
00473          apply_DebyeWaller_Spiller_factor( sinphi );
00474          break;
00475 
00476   case rl_Traits::ERoughNevotCroce :
00477 
00478          apply_NevotCroce_factor( upper, sinphi );
00479          break;
00480 
00481   case rl_Traits::ERoughModifiedDebyeWaller :
00482 
00483          apply_ModifiedDW_factor( upper, sinphi );
00484          break;
00485 
00486   case rl_Traits::ERoughNone :
00487 
00488          /* do nothing */
00489          break;
00490 
00491   default :
00492 
00493          cerr << "Invalid roughness type in rl_DielectricLayer::reflect_amp"
00494               << endl;
00495          cerr << "Roughness type was " << rtype_ << endl;
00496          exit(1);
00497 
00498   } /* end rl_Traits::ERoughType cases */
00499 }
00500 
00501 //-------------------------------------------------------------------------
00502 // c   Calculate n-layer reflectivity using recurrence relation.
00503 // c
00504 //       subroutine reflect_nlayer ( ca, cprop, n, refl )
00505 //       implicit complex (c)
00506 //       dimension ca(15), cprop(14)
00507 // c
00508 //       ceps = ca( n )
00509 //       do m=n-1, 1, -1
00510 //          ceps = (ca(m) + cprop(m)*ceps) / (1.0 + cprop(m)*ca(m)*ceps)
00511 //       end do
00512 // c
00513 //       rmod = abs( ceps )
00514 //       refl = rmod*rmod
00515 // c
00516 //       return
00517 //       end
00518 
00519 void rl_DielectricLayer::
00520 reflect_nlayer( rl_DielectricLayer layer[],
00521                 int                num )
00522 {
00523   complex eps_para( layer[num-1].rflcoef_.para() );
00524   complex eps_perp( layer[num-1].rflcoef_.perp() );
00525   const complex one( 1.0 );
00526   #if defined(DEBUG_DIELECTRICLAYER)
00527     fprintf(stdout, "\nDEBUG: ___REFLECT_NLAYER___ ___AAA0___ -----\n");
00528     fprintf(stdout, "\n==> layer %5d -- ", num-1);
00529     fprintf(stdout, "layer[n-1] (%5d  %.s)\n", 
00530                      num-1, layer[num-1].name_);
00531     fprintf(stdout, "rl_DielectricLayer::reflect_nlayer ");
00532     fprintf(stdout, "======================\n");
00533     fprintf(stdout, "eps (para) %5d (%.15e  %.15e)\n",
00534                      num-1, eps_para.real(), eps_para.imag());
00535     fprintf(stdout, "eps (perp) %5d (%.15e  %.15e)\n",
00536                      num-1, eps_perp.real(), eps_perp.imag());
00537   #endif
00538 
00539   for ( int n = num-2; n >= 0; --n )
00540   {
00541     rl_Traits::complex prop_eps_para( layer[n].propagator() * eps_para );
00542     eps_para = (layer[n].rflcoef_.para() 
00543               + layer[n].r2_tij_tji_para_ * prop_eps_para)
00544              / (one + layer[n].rflcoef_.para() * prop_eps_para);
00545 
00546     rl_Traits::complex prop_eps_perp( layer[n].propagator() * eps_perp );
00547     eps_perp = (layer[n].rflcoef_.perp() 
00548               + layer[n].r2_tij_tji_perp_ * prop_eps_perp)
00549              / (one + layer[n].rflcoef_.perp() * prop_eps_perp);
00550 
00551   #if defined(DEBUG_DIELECTRICLAYER)
00552     fprintf(stdout, "\nDEBUG: ___REFLECT_NLAYER___ ___AAA1___ -----\n");
00553     fprintf(stdout, "\n==> layer %5d -- ", n);
00554     fprintf(stdout, "rl_DielectricLayer::reflect_nlayer ");
00555     fprintf(stdout, "======================\n");
00556     cprint_constraints_on( stdout );
00557     fprintf(stdout, "rflcoef (para) %5d, (%.15e  %.15e)\n",
00558                      n, layer[n].rflcoef_.para().real(),
00559                         layer[n].rflcoef_.para().imag() );
00560 
00561     fprintf(stdout, "rflcoef (perp) %5d, (%.15e  %.15e)\n",
00562                      n, layer[n].rflcoef_.perp().real(),
00563                         layer[n].rflcoef_.perp().imag() );
00564 
00565     fprintf(stdout, "r2_tt   (para) %5d, (%.15e  %.15e)\n",
00566                      n, layer[n].r2_tij_tji_para_.real(), 
00567                         layer[n].r2_tij_tji_para_.imag() );
00568 
00569     fprintf(stdout, "r2_tt   (perp) %5d, (%.15e  %.15e)\n",
00570                      n, layer[n].r2_tij_tji_perp_.real(), 
00571                         layer[n].r2_tij_tji_perp_.imag() );
00572 
00573     fprintf(stdout, "eps     (para) %5d, (%.15e  %.15e)\n",
00574                      n, eps_para.real(), eps_para.imag());
00575     fprintf(stdout, "eps     (perp) %5d, (%.15e  %.15e)\n",
00576                      n, eps_perp.real(), eps_perp.imag());
00577   #endif
00578   }
00579   layer[0].rflcoef_.para() = eps_para;
00580   layer[0].rflcoef_.perp() = eps_perp;
00581 
00582   #if defined(DEBUG_DIELECTRICLAYER)
00583     fprintf(stdout, "\n");
00584   #endif
00585 
00586 #if 0
00587   refl  = abs( eps );
00588   refl *= refl;
00589 #endif
00590 }
00591 
00592 //=========================================================================
00593 
00594 //-------------------------------------------------------------------------
00595 // Routine to evaluate Debye-Waller roughness factor
00596 // <code>phase_factor</code> is <code>2 pi srough / lambda</code>
00597 //
00598 // Implemented in the IDL code as dw_csao: SAO variant on Windt's DW, 
00599 // using complex factor
00600 //      exp(double(-2d*kc*kc*sigma_t(j)*sigma_t(j)*c_t(*,*,j)*c_t(*,*,j)))
00601 
00602 void rl_DielectricLayer::
00603 apply_DebyeWaller_CSAO_factor( rl_DielectricLayer const& upper, // upper layer
00604                                double sinphi             // sin(graze angle)
00605                              )
00606 {
00607   double phase_factor = -2 * phase_factor_ * phase_factor_;
00608   double sinphi_sq    = sinphi * sinphi;
00609 
00610   complex sinterm_0( sinphi_sq - upper.alpha_, -upper.gamma_ );
00611   sinterm_0 /= complex( 1.0 - upper.alpha_, -upper.gamma_ );
00612 
00613   complex ckphase( sinterm_0 );
00614   ckphase *= phase_factor;
00615   ckphase  = exp(ckphase);
00616 
00617   rflcoef_.para() *= ckphase;
00618   rflcoef_.perp() *= ckphase;
00619 }
00620 
00621 //-------------------------------------------------------------------------
00622 // Routine to evaluate Debye-Waller roughness factor
00623 // <code>phase_factor</code> is <code>2 pi srough / lambda</code>
00624 //
00625 // Implemented in the IDL code as dw_csao: SAO variant on Windt's DW,
00626 // taking only the real part of the factor
00627 //      exp(double(-2d*kc*kc*sigma_t(j)*sigma_t(j)*c_t(*,*,j)*c_t(*,*,j)))
00628 
00629 void rl_DielectricLayer::
00630 apply_DebyeWaller_RSAO_factor( rl_DielectricLayer const& upper, // upper layer
00631                                double sinphi             // sin(graze angle)
00632                              )
00633 {
00634   double phase_factor = -2.0 * phase_factor_ * phase_factor_;
00635   double sinphi_sq    = sinphi * sinphi;
00636 
00637   complex sinterm_0( sinphi_sq - upper.alpha_, -upper.gamma_ );
00638   sinterm_0 /= complex( 1.0 - upper.alpha_, -upper.gamma_ );
00639 
00640   complex ckphase( sinterm_0 );
00641   ckphase *= phase_factor;
00642   double real_phase_factor = ckphase.real();
00643   real_phase_factor = exp( real_phase_factor );
00644 
00645   rflcoef_.para() *= real_phase_factor;
00646   rflcoef_.perp() *= real_phase_factor;
00647 }
00648 
00649 //-------------------------------------------------------------------------
00650 // Routine to evaluate Debye-Waller roughness factor
00651 // <code>phase_factor</code> is <code>2 pi srough / lambda</code>
00652 //
00653 // Implemented in the IDL code as dw_spiller: Variant on the DW rising 
00654 // from a paper by Spiller
00655 //      exp(-2d*kc*kc*sigma_t(j)*sigma_t(j)*c_t(*,*,j)*c_t(*,*,j)*
00656 //          n(*,*,j)*n(*,*,j))
00657 
00658 void rl_DielectricLayer::
00659 apply_DebyeWaller_Spiller_factor( double sinphi        // sin(graze angle)
00660                         )
00661 {
00662   double phase_factor = phase_factor_;
00663 
00664   phase_factor *= sinphi;
00665   phase_factor *= phase_factor;
00666   phase_factor *= 2.0;
00667 
00668   complex ckphase( phase_factor * (alpha_ - 1.0),
00669                    phase_factor *  gamma_ );
00670 
00671   complex cexp_factor = exp(ckphase);
00672 
00673   rflcoef_.para() *= cexp_factor;
00674   rflcoef_.perp() *= cexp_factor;
00675 }
00676 
00677 //-------------------------------------------------------------------------
00678 // Routine to evaluate "modified Debye-Waller" roughness factor
00679 // <code>phase_factor</code> is <code>2 pi srough / lambda</code>
00680 
00681 void rl_DielectricLayer::
00682 apply_ModifiedDW_factor( rl_DielectricLayer const& upper,  // upper layer
00683                          double                    sinphi  // sin(graze angle)
00684                        )
00685 {
00686   double phase_factor = phase_factor_;
00687   double sinphi_sq    = sinphi * sinphi;
00688 
00689   #if defined(DEBUG_DIELECTRICLAYER)
00690     fprintf(stdout, "\nDEBUG: ___MDW___ ---------------------------\n");
00691     cerr << "===================================================================" 
00692          << endl;
00693     cerr << "Layer j-1:" << endl;
00694     upper.cdump_on( stdout );
00695     cerr << "-------------------------------------------------------------------" 
00696          << endl;
00697     cerr << "Layer j:" << endl;
00698     cdump_on( stdout );
00699     cerr << "-------------------------------------------------------------------" 
00700          << endl;
00701   #endif
00702 
00703   phase_factor     *= -2.0 * phase_factor;
00704 
00705   #if defined(DEBUG_DIELECTRICLAYER)
00706     cerr << "sinphi:                  " << sinphi << endl;
00707     cerr << "phi:                     " << 60.0 * asin(sinphi) / M_DEG2RAD << endl;
00708     cerr << "-2 (2pi sigma/lambda)^2: " << phase_factor << endl;
00709   #endif
00710 
00711   complex sinterm_0( sinphi_sq - upper.alpha_, -upper.gamma_ );
00712   complex nopt0  = sqrt( complex( 1.0 - upper.alpha_, -upper.gamma_ ));
00713   complex cos2_0 = sqrt( sinterm_0 ) / nopt0;
00714 
00715   #if defined(DEBUG_DIELECTRICLAYER)
00716     cerr << "cos_{j-1}:               " << cos2_0 << endl;
00717   #endif
00718 
00719   complex sinterm_1( sinphi_sq - alpha_, -gamma_ );
00720   complex nopt1  =  sqrt( complex( 1.0 - alpha_, -gamma_ ) );
00721   complex cos2_1 =  sqrt( sinterm_1 ) / nopt1;
00722 
00723   #if defined(DEBUG_DIELECTRICLAYER)
00724     complex cosij = cos2_0 * cos2_1;
00725     complex cosj = cos2_0 * nopt0 / nopt1;
00726     complex sin2_0 = sqrt( complex(1.0) - cos2_0 * cos2_0 );
00727     complex sin2_1 = sqrt( complex(1.0) - cos2_1 * cos2_1 );
00728     cerr << "cos_{j}:                  " << cos2_1 << endl;
00729     cerr << "cos_{j-1} n_{j-1} / n_{j} " << cos2_0 * nopt0 / nopt1 << endl;
00730     cerr << "n_{j-1} sin_{j-1}         " << sin2_0 * nopt0 << endl;
00731     cerr << "n_{j}   sin_{j}           " << sin2_1 * nopt1 << endl;
00732     cerr << "cos_{j} cos_{j-1}         " << cosij << endl;
00733   #endif
00734 
00735   complex cexp_factor( cos2_0 );
00736   cexp_factor *= cos2_1;
00737   cexp_factor *= phase_factor;
00738   cexp_factor  = exp( cexp_factor );
00739 
00740   rflcoef_.para() *= cexp_factor;
00741   rflcoef_.perp() *= cexp_factor;
00742 
00743   #if defined(DEBUG_DIELECTRICLAYER)
00744     cerr << "===================================================================" 
00745          << endl;
00746   #endif
00747 }
00748 
00749 //-------------------------------------------------------------------------
00750 // Routine to evaluate Nevot-Croce factor
00751 // <code>phase_factor</code> is <code>2 pi srough / lambda</code>
00752 //
00753 //<code>
00754 //  \NC_\mathit{j-1,j}
00755 //     =  \exp\left[ -2 \k_0^2
00756 //           \left[ \left( \sin^2 \tilde\alpha_0 + \Delta\eps_{j}   \right)
00757 //                  \left( \sin^2 \tilde\alpha_0 + \Delta\eps_{j-1} \right)
00758 //           \right]^{1\over 2}
00759 //        \sigma_\j^2 \right]
00760 //</code>
00761 
00762 void rl_DielectricLayer::
00763 apply_NevotCroce_factor( rl_DielectricLayer const& upper,  // upper layer
00764                          double                    sinphi  // sin(graze angle)
00765                        )
00766 {
00767   double phase_factor = phase_factor_;
00768   double sinphi_sq    = sinphi * sinphi;
00769 
00770   phase_factor  *=  phase_factor;
00771   phase_factor  *= -2.0;
00772 
00773   complex sinterm_0( sinphi_sq - upper.alpha_, -upper.gamma_ );
00774   complex sinterm_1( sinphi_sq -       alpha_,       -gamma_ );
00775   complex ckphase( sinterm_0 );
00776 
00777   ckphase *= sinterm_1;
00778   ckphase  = sqrt( ckphase );
00779   ckphase *= phase_factor;
00780   ckphase  = exp(ckphase);
00781 
00782   rflcoef_.para() *= ckphase;
00783   rflcoef_.perp() *= ckphase;
00784 }
00785 
00786 //=========================================================================
00787 // i/o
00788 
00789 //-------------------------------------------------------------------------
00790 std::ostream& rl_DielectricLayer::
00791 dump_on( std::ostream& os, char const pre[], char const pst[] ) const
00792 {
00793   if ( strlen(pre) )
00794   { os << pre; }
00795 
00796   os << "Layer:                  " << name_         << endl;
00797   os.setf( ios::scientific, ios::floatfield );
00798   os.precision(12);
00799 
00800   os << "minimum energy (keV):   " << diel_info_.energy_min() << endl;
00801   os << "maximum energy (keV):   " << diel_info_.energy_max() << endl;
00802   os << "bulk density scale:     " << diel_info_.bulk_density_factor() << endl;
00803 
00804   os << "thickness (Angstrom):   " << thickness_    << endl;
00805   if (! is_vacuum() )
00806   {
00807     os << "reflection coefficient: " << rflcoef_      << endl;
00808   }
00809   os << "alpha:                  " << alpha_        << endl;
00810   os << "gamma:                  " << gamma_        << endl;
00811   os << "refractive index:       " 
00812      << sqrt( complex( 1.0 - alpha_, -gamma_ )) << endl;
00813   if (! is_vacuum() )
00814   {
00815     os << "roughness type:         " << rtype_        << endl;
00816     os << "sigma_rough:            " << srough_       << endl;
00817     os << "wavelength:             " << lambda_       << endl;
00818     os << "zcoat:                  " << zcoat_        << endl;
00819     os << "propagator:             " << prop_         << endl;
00820     os << "kt_perp_:               " << kt_perp_      << endl;
00821   }
00822   os << "is_vacuum:              " << is_vacuum()   << endl;
00823   os << "is_substrate:           " << is_substrate_ << endl;
00824 
00825   if ( strlen(pst) )
00826   { os << pst; }
00827 
00828   return os;
00829 }
00830 
00831 //=========================================================================
00832 // i/o
00833 
00834 //-------------------------------------------------------------------------
00835 void rl_DielectricLayer::
00836 cdump_on( std::FILE* of, char const pre[], char const pst[] ) const
00837 {
00838   if ( strlen(pre) )
00839   { fprintf(of, "%s", pre); }
00840 
00841   fprintf(of, "Layer:                  %s\n", name_);
00842 
00843   fprintf(of, "minimum energy (keV):   %.15e\n", diel_info_.energy_min());
00844   fprintf(of, "maximum energy (keV):   %.15e\n", diel_info_.energy_max());
00845   fprintf(of, "bulk density scale:     %.15e\n", 
00846                diel_info_.bulk_density_factor());
00847 
00848   fprintf(of, "thickness (Angstrom):   %.15e\n", thickness_);
00849   if (! is_vacuum() )
00850   {
00851     rflcoef_.cprint_on(of);
00852   }
00853   fprintf( of, "alpha:                  %.15e\n", alpha_);
00854   fprintf( of, "gamma:                  %.15e\n", gamma_);
00855 
00856   complex srt = sqrt( complex( 1.0 - alpha_, -gamma_ ) );
00857   fprintf(of, "refractive index:       (%.15e, %.15e)\n", 
00858                srt.real(), srt.imag());
00859 
00860   if (! is_vacuum() )
00861   {
00862     fprintf(of, "roughness type:         %d\n",    rtype_);
00863     fprintf(of, "sigma_rough:            %.15e\n", srough_);
00864     fprintf(of, "wavelength:             %.15e\n", lambda_);
00865     fprintf(of, "zcoat:                  %.15e\n", zcoat_);
00866     fprintf(of, "propagator:             (%.15e, %.15e)\n",
00867                 prop_.real(), prop_.imag());
00868     fprintf(of, "kt_perp_:               (%.15e, %.15e)\n",
00869                 kt_perp_.real(), kt_perp_.imag());
00870   }
00871   fprintf(of, "is_vacuum:              %d\n", is_vacuum());
00872   fprintf(of, "is_substrate:           %d\n", is_substrate_);
00873 
00874   if ( strlen(pst) )
00875   { fprintf(of, "%s", pst); }
00876 }
00877 
00878 //-------------------------------------------------------------------------
00879 void rl_DielectricLayer::
00880 cprint_constraints_on( std::FILE* of, 
00881                        char const pre[], char const pst[] ) const
00882 {
00883   if ( strlen(pre) )
00884   { fprintf(of, "%s", pre); }
00885 
00886   fprintf(of, "Layer:                  %s\n", name_);
00887 
00888   complex identperp = t_ij_.perp() - rflcoef_.perp();
00889   complex identpara = t_ij_.para() - rflcoef_.para();
00890 
00891   fprintf(of, "minimum energy (keV):   %.14e\n", diel_info_.energy_min());
00892   fprintf(of, "maximum energy (keV):   %.14e\n", diel_info_.energy_max());
00893   fprintf(of, "bulk density scale:     %.14e\n", 
00894                diel_info_.bulk_density_factor());
00895 
00896   fprintf(of, "thickness (Angstrom):   %.14e\n", thickness_);
00897   fprintf( of, "alpha:                  %.14e\n", alpha_);
00898   fprintf( of, "gamma:                  %.14e\n", gamma_);
00899 
00900   complex srt = sqrt( complex( 1.0 - alpha_, -gamma_ ) );
00901   fprintf(of, "refractive index:       (%.14e, %.14e)\n", 
00902                srt.real(), srt.imag());
00903 
00904   if (! is_vacuum() )
00905   {
00906     fprintf(of, "roughness type:         %d\n",    rtype_);
00907     fprintf(of, "sigma_rough:            %.14e\n", srough_);
00908     fprintf(of, "wavelength:             %.14e\n", lambda_);
00909     fprintf(of, "zcoat:                  %.14e\n", zcoat_);
00910     fprintf(of, "propagator:             (%.14e, %.14e)\n",
00911                  prop_.real(), prop_.imag());
00912     fprintf(of, "kt_perp_:               (%.14e, %.14e)\n",
00913                  kt_perp_.real(), kt_perp_.imag());
00914     fprintf(of, "\n");
00915 
00916     fprintf(of, "Tji_perp:               (%.14e, %.14e)\n",
00917                  t_ji_.perp().real(), t_ji_.perp().imag());
00918     fprintf(of, "Tij_perp:               (%.14e, %.14e)\n",
00919                  t_ij_.perp().real(), t_ij_.perp().imag());
00920     fprintf(of, "Rij_perp:               (%.14e, %.14e)\n",
00921                  rflcoef_.perp().real(), rflcoef_.perp().imag());
00922     fprintf(of, "Rij^2 (perp):           (%.14e, %.14e)\n",
00923                  r2_perp_.real(), r2_perp_.imag());
00924     fprintf(of, "Tij Tji (perp):         (%.14e, %.14e)\n",
00925                  tij_tji_perp_.real(), tij_tji_perp_.imag());
00926     double tprpi = (fabs(identperp.imag()) >= 1e-15)
00927                   ? identperp.imag() : 0.0;
00928     fprintf(of, "Tij_perp-Rij_perp:      (%.14e, %.14e)\n",
00929                  identperp.real(), tprpi);
00930     fprintf(of, "Rij^2+Tij Tji (perp):   (%.14e, %.14e)\n",
00931                  r2_tij_tji_perp_.real(), r2_tij_tji_perp_.imag());
00932     fprintf(of, "\n");
00933 
00934     fprintf(of, "Tji_para:               (%.14e, %.14e)\n",
00935                  t_ji_.para().real(), t_ji_.para().imag());
00936     fprintf(of, "Tij_para:               (%.14e, %.14e)\n",
00937                  t_ij_.para().real(), t_ij_.para().imag());
00938     fprintf(of, "Rij_para:               (%.14e, %.14e)\n",
00939                  rflcoef_.para().real(), rflcoef_.para().imag());
00940     fprintf(of, "Rij^2 (para):           (%.14e, %.14e)\n",
00941                  r2_para_.real(), r2_para_.imag());
00942     fprintf(of, "Tij Tji (para):         (%.14e, %.14e)\n",
00943                  tij_tji_para_.real(), tij_tji_para_.imag());
00944     fprintf(of, "Tij_para-Rij_para:      (%.14e, %.14e)\n",
00945                  identpara.real(), identpara.imag());
00946     fprintf(of, "Rij^2+Tij Tji (para):   (%.14e, %.14e)\n",
00947                  r2_tij_tji_para_.real(), r2_tij_tji_para_.imag());
00948     fprintf(of, "\n");
00949   }
00950   fprintf(of, "is_vacuum:              %d\n", is_vacuum());
00951   fprintf(of, "is_substrate:           %d\n", is_substrate_);
00952 
00953   if ( strlen(pst) )
00954   { fprintf(of, "%s", pst); }
00955 }

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