yanera_reflectivity.c

Go to the documentation of this file.
00001 /*==============================================================================
00002 Copyright 2006 Thad Harroun, Kevin Yager
00003 
00004 This file is part of "yanera 2.0".
00005 
00006 "yanera 2.0" is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
00007 
00008 "yanera 2.0" is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00009 
00010 You should have received a copy of the GNU General Public License along with "yanera 2.0"; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 
00011 ==============================================================================*/ 
00012 /*============================================================================*/
00018 #define _CRT_SECURE_NO_DEPRECATE
00019 
00020 #include "yanera.h"
00021 #include "yanera_reflectivity.h"
00022 #include "yanera_quadrature.h"
00023 /*============================================================================*/
00024 void yanera_write_reflectivity(yanera_container *yanera) 
00025 {
00026   double            dq=0.0, q=0.0, r=0.0;
00027   int               i1, i2;
00028   FILE             *fp;
00029   char              filename[50];
00030   
00031   if (yanera->misc.fit_do == NO)
00032   {
00033     /*
00034      *  Find the step size in q.
00035      */
00036     if (yanera->misc.q_min == 0.0)  yanera->misc.q_min = 1.0E-5;
00037     dq = (yanera->misc.q_max - yanera->misc.q_min)/((double)yanera->misc.q_num);
00038   }
00039   
00040   for (i2=0; i2<yanera->number_of_models; i2++)
00041   {
00042     /* 
00043      * Make a filename for the reflectivity curve.
00044      */
00045     memset(filename, '\0', 50);
00046     if (yanera->data[i2].file_name == NULL) 
00047       { sprintf(filename, "result_%01d.ref", i2); }
00048     else sprintf(filename, "%s.ref", yanera->data[i2].file_name);
00049     
00050     /*
00051      * Break into slabs
00052      */
00053     if ((yanera->type == MODEL_COMPONENT) || \
00054         (yanera->type == MODEL_SLAB)      || \
00055         (yanera->type == MODEL_FUNCTION))
00056     { doQuadrature(&yanera->models_complete[i2], yanera); }
00057     
00058     /*
00059      * Open file and write to it.
00060      */
00061     fp = NULL;
00062     fp = fopen(filename,"w");
00063     if (fp == NULL) 
00064     {
00065       yanera_error("Can't open reflectivity file for writing", \
00066       __FILE__, __LINE__, yanera);
00067     }
00068     
00069     if (yanera->misc.fit_do == NO)
00070     {
00071       for (i1 = 0; i1 <= yanera->misc.q_num; i1++)
00072       {
00073         q = yanera->misc.q_min + dq * (double)i1;
00074         r = calcReflectivity(q, &yanera->data[i2].resolution, \
00075                                 &yanera->models_complete[i2], yanera);
00076         fprintf(fp, "%g\t%g\n", q, r);
00077       }
00078     }
00079     else
00080     {
00081       for (i1 = 0; i1 < yanera->data[i2].n; i1++)
00082       {
00083         q = yanera->data[i2].q[i1];
00084         r = calcReflectivity(q, &yanera->data[i2].resolution, \
00085                                 &yanera->models_complete[i2], yanera);
00086         fprintf(fp, "%g\t%g\n", q, r);
00087       }
00088     }
00089     
00090     fclose(fp);
00091   }
00092     
00093   return;
00094 }
00095 /*============================================================================*/
00096 double calcReflectivity(double q, yanera_resolution *resolution, \
00097                         yanera_model *model, yanera_container *yanera)
00098 {
00099   double tmp, value;
00100 
00101   tmp = yanera->parrattFunction(q, model, yanera);
00102  
00103   /* determine resolution for this q */
00104   value = 0.0;
00105   if ((resolution->type == RESOLUTION_CONSTANT) || \
00106       (resolution->type == RESOLUTION_RELATIVE))
00107   {
00108     value = resolution->value[0];
00109   }
00110   else if ((resolution->type == RESOLUTION_ARRAY_CONSTANT) || \
00111            (resolution->type == RESOLUTION_ARRAY_RELATIVE))
00112   {
00113     value = lookupResolution(q, resolution);
00114   }
00115   
00116   /* instrument resolution, skip if zero for speed */
00117   if (value != 0.0)
00118   {
00119 
00120     if ((resolution->type == RESOLUTION_CONSTANT) || \
00121         (resolution->type == RESOLUTION_ARRAY_CONSTANT))
00122     {
00123       tmp += 0.882*yanera->parrattFunction(q+(0.25*value), model, yanera);
00124       tmp += 0.882*yanera->parrattFunction(q-(0.25*value), model, yanera);
00125       tmp += 0.607*yanera->parrattFunction(q+(0.50*value), model, yanera);
00126       tmp += 0.607*yanera->parrattFunction(q-(0.50*value), model, yanera);
00127       tmp += 0.325*yanera->parrattFunction(q+(0.75*value), model, yanera);
00128       tmp += 0.325*yanera->parrattFunction(q-(0.75*value), model, yanera);
00129       tmp += 0.135*yanera->parrattFunction(q+(1.00*value), model, yanera);
00130       tmp += 0.135*yanera->parrattFunction(q-(1.00*value), model, yanera);
00131     }
00132     else if ((resolution->type == RESOLUTION_RELATIVE) || \
00133              (resolution->type == RESOLUTION_ARRAY_RELATIVE))
00134     {
00135       tmp += 0.882*yanera->parrattFunction(q*(1.0+(0.25*value)), model, yanera);
00136       tmp += 0.882*yanera->parrattFunction(q*(1.0-(0.25*value)), model, yanera);
00137       tmp += 0.607*yanera->parrattFunction(q*(1.0+(0.50*value)), model, yanera);
00138       tmp += 0.607*yanera->parrattFunction(q*(1.0-(0.50*value)), model, yanera);
00139       tmp += 0.325*yanera->parrattFunction(q*(1.0+(0.75*value)), model, yanera);
00140       tmp += 0.325*yanera->parrattFunction(q*(1.0-(0.75*value)), model, yanera);
00141       tmp += 0.135*yanera->parrattFunction(q*(1.0+(1.00*value)), model, yanera);
00142       tmp += 0.135*yanera->parrattFunction(q*(1.0-(1.00*value)), model, yanera);
00143     }
00144     tmp /= (4.898);
00145   }
00146   
00147   /* background */
00148   if (model->background > -1)
00149     tmp += (yanera->parameters.p[model->background] * 1.0E-06);
00150     
00151  return tmp;
00152   
00153 }
00154 /*============================================================================*/
00155 double calcParrattFromSlabs(double q, \
00156                             yanera_model *model, \
00157                             yanera_container *yanera)
00158 {
00159   short        i;
00160   double       kv, tmpr, tmpi, result;
00161   gsl_complex  kzn, kznp1;
00162   gsl_complex  fr, R;
00163   gsl_complex  tmp1, tmp2;
00164   gsl_complex  argm, numtr, denom;
00165   
00166   if (q <= 0.0) return 1.0;
00167   
00168   /*
00169    * k_v: wave vector normal to the interface in vacuum.
00170    * k_0 = n_0*k_v \approx q/2. 
00171    */
00172   tmpr = (q * q / 4.0) + (4.0 * M_PI * model->slabs.rsld[0] * 1E-6);
00173   tmpi = (4.0 * M_PI * model->slabs.isld[0] * 1E-6);
00174   GSL_SET_COMPLEX(&tmp1, tmpr, tmpi);
00175   kv  = gsl_complex_abs(gsl_complex_sqrt(tmp1));
00176   
00177   /*
00178    * Zero the refecltivty variables: 
00179    * R = total reflectivity
00180    * fr = Fresnel reflectivity from any interface.
00181    */ 
00182   GSL_SET_COMPLEX(&R, 0.0, 0.0);
00183   GSL_SET_COMPLEX(&fr, 0.0, 0.0);
00184   
00185   /*
00186    * FORMULA INDEXING OF THE SLABS
00187    * If there are N slabs, infinite fronting material is slab 0, 
00188    * infinite backing material is slab N+1.
00189    * First reflection, from interface between slab N and N+1(bulk),
00190    * is Fresnel reflection only. 
00191    *
00192    * C INDEXING OF THE SLABS
00193    * The C index of n slabs (counting fronting and backing material)
00194    * is 0->n-1, so this first interface is n-2 and n-1.
00195    *
00196    * kzn   : wave vector in slab n
00197    * kznp1 : wave vector in slab n+1
00198    */
00199   i = model->slabs.number_of_slabs-2;
00200   {
00201     tmpr = (kv * kv)-(4.0 * M_PI * model->slabs.rsld[i] * 1E-6);
00202     tmpi = (4.0 * M_PI * model->slabs.isld[i] * 1E-6);
00203     GSL_SET_COMPLEX(&tmp1, tmpr, tmpi);
00204     kzn   = gsl_complex_sqrt(tmp1);
00205     
00206     tmpr = (kv * kv)-(4.0 * M_PI * model->slabs.rsld[i+1] * 1E-6);
00207     tmpi = (4.0 * M_PI * model->slabs.isld[i+1] * 1E-6);
00208     GSL_SET_COMPLEX(&tmp1, tmpr, tmpi);
00209     kznp1   = gsl_complex_sqrt(tmp1);
00210     
00211     /* Fresnel */
00212     tmp1 = gsl_complex_sub(kzn, kznp1);
00213     tmp2 = gsl_complex_add(kzn, kznp1);
00214     R    = gsl_complex_div(tmp1, tmp2);
00215   }
00216   
00217   /* 
00218    *  Subsequent reflections: End on the reflection from slab 0->1.
00219    */
00220   for (i=model->slabs.number_of_slabs-3; i>=0; i--)
00221   {
00222     GSL_SET_COMPLEX(&kznp1, GSL_REAL(kzn), GSL_IMAG(kzn));
00223   
00224     tmpr = (kv * kv)-(4.0 * M_PI * model->slabs.rsld[i] * 1E-6);
00225     tmpi = (4.0 * M_PI * model->slabs.isld[i] * 1E-6);
00226     GSL_SET_COMPLEX(&tmp1, tmpr, tmpi);
00227     kzn   = gsl_complex_sqrt(tmp1);
00228     
00229     /* 
00230      * Save one sqrt(), use the fact that this already calculated during the 
00231      * previous iteration!
00232     tmpr = (kv * kv)-(4.0 * M_PI * model->slabs.rsld[i+1] * 1E-6);
00233     tmpi = (4.0 * M_PI * model->slabs.isld[i+1] * 1E-6);
00234     GSL_SET_COMPLEX(&tmp1, tmpr, tmpi);
00235     kznp1   = gsl_complex_sqrt(tmp1);
00236     */
00237     
00238     /* Fresnel */
00239     tmp1 = gsl_complex_sub(kzn, kznp1);
00240     tmp2 = gsl_complex_add(kzn, kznp1);
00241     fr   = gsl_complex_div(tmp1, tmp2);
00242   
00243     /* argm = R_n+1 * exp(2 i k_n+1 d_n+1) */
00244     tmp1 = gsl_complex_mul_imag(kznp1, 2.0*model->slabs.thik[i+1]);
00245     tmp2 = gsl_complex_exp(tmp1);
00246     argm = gsl_complex_mul(R, tmp2);
00247 
00248     /* numtr = fr_n,n+1 + R_n+1 * exp(2 i k_n+1 d_n+1) */
00249     numtr = gsl_complex_add(fr, argm);
00250         
00251     /* denom = 1 + fr_n,n+1 * R_n+1 * exp(2 i k_n+1 d_n+1) */
00252     denom = gsl_complex_add_real(gsl_complex_mul(fr, argm), 1.0);
00253     
00254     R = gsl_complex_div(numtr, denom);
00255   }
00256   
00257   /* Grand result: |R|^2 */
00258   result = gsl_complex_abs2(R);
00259   
00260   return result;
00261 }
00262 /*============================================================================*/
00263 double calcParrattFromModel(double q, \
00264                             yanera_model *model, \
00265                             yanera_container *yanera)
00266 {
00267   double        kv, tmpr, tmpi, result, rsld;
00268   gsl_complex   kzn, kznp1;
00269   gsl_complex   fr, r, R;
00270   gsl_complex   tmp1, tmp2, tmp3;
00271   gsl_complex   argm, numtr, denom;
00272   yanera_layer *layer;
00273   
00274   if (q < 0) return 1.0;
00275   
00276   /*
00277    * k_v: wave vector normal to the interface in vacuum.
00278    * k_0 = n_0*k_v \approx q/2. 
00279    */
00280   layer = model->first_layer;
00281   rsld = yanera->parameters.p[layer->rsld];
00282   if      (layer->polarized == POLARIZED_UP) 
00283     rsld += yanera->parameters.p[layer->rmag];
00284   else if (layer->polarized == POLARIZED_DOWN) 
00285     rsld -= yanera->parameters.p[layer->rmag];
00286   tmpr = (q * q / 4.0) + (4.0 * M_PI * rsld * 1E-6);
00287   if (layer->isld > -1)  
00288   { tmpi = (4.0 * M_PI * yanera->parameters.p[layer->isld] * 1E-6); }
00289   else tmpi = 0.0;
00290   GSL_SET_COMPLEX(&tmp1, tmpr, tmpi);
00291   kv  = gsl_complex_abs(gsl_complex_sqrt(tmp1));
00292   
00293   /*
00294    * Zero the refecltivty variables: 
00295    * R = total reflectivity
00296    * fr = Fresnel reflectivity from any interface.
00297    */ 
00298   GSL_SET_COMPLEX(&R, 0.0, 0.0);
00299   GSL_SET_COMPLEX(&fr, 0.0, 0.0);
00300   GSL_SET_COMPLEX(&r, 0.0, 0.0);
00301   
00302   /*
00303    * FORMULA INDEXING OF THE SLABS
00304    * If there are N layers, infinite fronting material is layer 0, 
00305    * infinite backing material is layer N+1.
00306    * First reflection, from interface between layers N and N+1(bulk),
00307    * is Fresnel reflection only. 
00308    *
00309    * C INDEXING OF THE SLABS
00310    * The C index of n layers (counting fronting and backing material)
00311    * is 0->n-1, so this interface is n-2 and n-1.
00312    *
00313    * kzn   : wave vector in slab n
00314    * kznp1 : wave vector in slab n+1
00315    */
00316   layer = model->last_layer->prev;
00317   {
00318     rsld = yanera->parameters.p[layer->rsld];
00319     if      (layer->polarized == POLARIZED_UP) 
00320       rsld += yanera->parameters.p[layer->rmag];
00321     else if (layer->polarized == POLARIZED_DOWN) 
00322       rsld -= yanera->parameters.p[layer->rmag];
00323     tmpr = (kv * kv)-(4.0 * M_PI * rsld * 1E-6);
00324     if (layer->isld > -1)  
00325     { tmpi = (4.0 * M_PI * yanera->parameters.p[layer->isld] * 1E-6); }
00326     else tmpi = 0.0;
00327     GSL_SET_COMPLEX(&tmp1, tmpr, tmpi);
00328     kzn   = gsl_complex_sqrt(tmp1);
00329     
00330     rsld = yanera->parameters.p[layer->next->rsld];
00331     if      (layer->next->polarized == POLARIZED_UP) 
00332       rsld += yanera->parameters.p[layer->next->rmag];
00333     else if (layer->next->polarized == POLARIZED_DOWN) 
00334       rsld -= yanera->parameters.p[layer->next->rmag];
00335     tmpr = (kv * kv)-(4.0 * M_PI * rsld * 1E-6);
00336     if (layer->next->isld > -1)  
00337     { tmpi = (4.0 * M_PI * yanera->parameters.p[layer->next->isld] * 1E-6); }
00338     else tmpi = 0.0;
00339     GSL_SET_COMPLEX(&tmp1, tmpr, tmpi);
00340     kznp1   = gsl_complex_sqrt(tmp1);
00341     
00342     /* Fresnel */
00343     tmp1 = gsl_complex_sub(kzn, kznp1);
00344     tmp2 = gsl_complex_add(kzn, kznp1);
00345     fr    = gsl_complex_div(tmp1, tmp2);
00346     
00347     /* r = Fresnel * roughness */
00348     tmp1 = gsl_complex_mul(kzn,kznp1);
00349     tmpr = -2.0 * yanera->parameters.p[layer->next->sigz] * \
00350                   yanera->parameters.p[layer->next->sigz];
00351     tmp2 = gsl_complex_mul_real(tmp1, tmpr);
00352     tmp3 = gsl_complex_exp(tmp2);
00353     R    = gsl_complex_mul(fr, tmp3);
00354   }
00355   
00356   /* 
00357    *  Subsequent reflections: End on the reflection from slab 0->1.
00358    */
00359   do
00360   {
00361     layer = layer->prev;
00362     
00363     GSL_SET_COMPLEX(&kznp1, GSL_REAL(kzn), GSL_IMAG(kzn));
00364     
00365     rsld = yanera->parameters.p[layer->rsld];
00366     if      (layer->polarized == POLARIZED_UP) 
00367       rsld += yanera->parameters.p[layer->rmag];
00368     else if (layer->polarized == POLARIZED_DOWN) 
00369       rsld -= yanera->parameters.p[layer->rmag];
00370     tmpr = (kv * kv)-(4.0 * M_PI * rsld * 1E-6);
00371     if (layer->isld > -1)  
00372     { tmpi = (4.0 * M_PI * yanera->parameters.p[layer->isld] * 1E-6); }
00373     else tmpi = 0.0;
00374     GSL_SET_COMPLEX(&tmp1, tmpr, tmpi);
00375     kzn   = gsl_complex_sqrt(tmp1);
00376     
00377     /* 
00378      * Save one sqrt(), use the fact that this already calculated during the 
00379      * previous iteration!
00380     rsld = yanera->parameters.p[layer->next->rsld];
00381     if      (layer->next->polarized == POLARIZED_UP) 
00382       rsld += yanera->parameters.p[layer->next->rmag];
00383     else if (layer->next->polarized == POLARIZED_DOWN) 
00384       rsld -= yanera->parameters.p[layer->next->rmag];
00385     tmpr = (kv * kv)-(4.0 * M_PI * rsld * 1E-6);
00386     if (layer->next->isld > -1)  
00387     { tmpi = (4.0 * M_PI * yanera->parameters.p[layer->next->isld] * 1E-6); }
00388     else tmpi = 0.0;
00389     GSL_SET_COMPLEX(&tmp1, tmpr, tmpi);
00390     kznp1   = gsl_complex_sqrt(tmp1);
00391     */
00392     
00393     /* Fresnel */
00394     tmp1 = gsl_complex_sub(kzn, kznp1);
00395     tmp2 = gsl_complex_add(kzn, kznp1);
00396     fr   = gsl_complex_div(tmp1, tmp2);
00397     
00398     /* r = Fresnel * roughness */
00399     tmp1 = gsl_complex_mul(kzn,kznp1);
00400     tmpr = -2.0 * yanera->parameters.p[layer->next->sigz] * \
00401                   yanera->parameters.p[layer->next->sigz];
00402     tmp2 = gsl_complex_mul_real(tmp1, tmpr);
00403     tmp3 = gsl_complex_exp(tmp2);
00404     r    = gsl_complex_mul(fr, tmp3);
00405   
00406     /* argm = R_n+1 * exp(2 i k_n+1 d_n+1) */
00407     tmp1 = gsl_complex_mul_imag(kznp1, \
00408                           2.0*yanera->parameters.p[layer->next->thik]);
00409     tmp2 = gsl_complex_exp(tmp1);
00410     argm = gsl_complex_mul(R, tmp2);
00411 
00412     /* numtr = r_n,n+1 + R_n+1 * exp(2 i k_n+1 d_n+1) */
00413     numtr = gsl_complex_add(r, argm);
00414         
00415     /* denom = 1 + r_n,n+1 * R_n+1 * exp(2 i k_n+1 d_n+1) */
00416     denom = gsl_complex_add_real(gsl_complex_mul(r, argm), 1.0);
00417     
00418     R = gsl_complex_div(numtr, denom);
00419     
00420   } while (layer != model->first_layer);
00421   
00422   /* Grand result: |R|^2 */
00423   result = gsl_complex_abs2(R);
00424   
00425   return result;
00426 }
00427 /*============================================================================*/
00428 double lookupResolution(double  q, yanera_resolution *resolution)
00429 {
00430   int i=0;
00431   /* 
00432    *  Walk through the array of q-values in reverse until you walk past
00433    *  the target value 
00434    */
00435   for (i = resolution->n-1; i>=0; i--)
00436   {
00437     if (resolution->q[i] <= q) return resolution->value[i];
00438   }
00439   
00440   /* If no resolution is specified for low-q data, use 0 */
00441   return 0.0;
00442  }
00443 

Generated on Thu May 29 10:56:33 2008 by  doxygen 1.5.5