Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

sfc.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Carlos Pascual-Izarra                           *
00003  *   carlos.pascual@itn.pt                                                 *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 
00021 #include <stdio.h>
00022 #include <math.h>
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include "libcpixe.h"
00026 #include "compilopt.h"  //here we store variables for the C preprocessor for conditional compiling
00027 
00028 
00029 /**\file sfc.c
00030 sfc.c contains the portion of libcpixe related to secondary fluorescence corrections.
00031 
00032 This is still (in v1.0) under development so nothing is really used yet.
00033 */
00034 
00035 
00036 int createSFCList(const EXP_PARAM *pexp, const int *PresentElems, const XrayYield *XYldArray, const AbsCoef *TotAbsCoefArray, int *nSFCList, SFCListElem **SFCList)
00037 {
00038   int Za,Zb;
00039   int dim;
00040   
00041   *nSFCList=0;
00042   *SFCList=NULL;
00043   
00044   dim=pexp->simpar.MaxZinsample+1;
00045   
00046   for(Zb=minK;Zb<dim;Zb++){
00047     if(PresentElems[Zb]){ 
00048       for(Za=minK;Za<dim;Za++){
00049         if(PresentElems[Za]){
00050           needSFC(Za, Zb, &XYldArray[Za].ener, &TotAbsCoefArray[Zb], nSFCList, SFCList);
00051         }
00052       }  
00053     }
00054   }
00055   return(0);
00056 }
00057 
00058 int needSFC(atomicnumber Za, atomicnumber Zb, const CalibYld *enerA, const AbsCoef *AbsC, int *nSFCList, SFCListElem **SFCList )
00059 {
00060   int j,l,i,ib,nabs;
00061   int n;
00062   double enerB,enerB_K,enerB_LIII;
00063   SFCListElem tempList[135]; ///<@todo 135=9x15 (absorption lines x emission_lines). If more lines or absorptions are added, this should be raised. Note that a conditional compilation for the case in which M absorption lines are not used, could reduce it to 4x15 or even to 4x12 if M emission lines are neither considered.
00064   
00065   if(Za<minK || Zb <minK ) {
00066     return(0);
00067   }
00068   
00069   
00070   nabs=4; ///<@todo Only K and L absorption lines are considered (since M lines are hard to quantify anyway, we don't waste time). If SFC is desired for M lines too, change nabs to 9 here. Also, a conditional compilation could be implemented depending on a preproc variable called ,i.e., QUANTIFYMLINES
00071   
00072   if(Zb<minL)nabs=1;
00073   
00074   enerB_K=AbsC->enr[0];
00075   if(enerB_K<0.001)enerB_K=HUGE;
00076   enerB_LIII=AbsC->enr[4];
00077   if(enerB_LIII<0.001)enerB_LIII=HUGE;
00078   
00079   //loop through all the absorption energies of the B element
00080   for (n=0, ib=1;ib<=nabs;ib++){
00081     enerB=AbsC->enr[ib]; //energy of absorption edge
00082     if(enerB>0){
00083       //K emission lines:
00084       for (j = 1; j <= 3; j++) {
00085         if(enerA->K_[j]>enerB){
00086           tempList[n].Za=Za;
00087           tempList[n].Zb=Zb;
00088           tempList[n].epri=0;  //this means K lines
00089           tempList[n].esec=j;   //this is the index inside the K group 
00090           tempList[n].abs=ib;  //Absorptions for: ib=1-->K ; ib=2,..4--> L ; ib=5,..9-->M 
00091           tempList[n].Ea=enerA->K_[j];
00092           tempList[n].sigmaphoto=sigmaphoto(ib, AbsC, Zb, enerA->K_[j]);
00093           n++;
00094         }
00095       }
00096       //L emission lines
00097       if(Za>minL) for (j = 1; j <= 3 ; j++) for (l = 1; l <= 3; l++) {
00098         if(inrange(enerA->L_[j][l],enerB,enerB_K)) {
00099           tempList[n].Za=Za;
00100           tempList[n].Zb=Zb;
00101           tempList[n].epri=j;  //j=1-->LIII, j=2-->LII, j=3-->LI 
00102           tempList[n].esec=l;   //this is the index inside the Lj group
00103           tempList[n].abs=ib;
00104           tempList[n].Ea=enerA->L_[j][l];
00105           tempList[n].sigmaphoto=sigmaphoto(ib, AbsC, Zb, enerA->L_[j][l]);
00106           n++;
00107         }
00108       }
00109       //M emission lines
00110       ///@todo In case M emission lines should not be considered for SFC, this for loop can be eliminated by a conditional compilation
00111       if(Za>minM) for (j = 1; j <= 3; j++) {
00112         if(inrange(enerA->M_[j],enerB,enerB_LIII) ) {
00113           tempList[n].Za=Za;
00114           tempList[n].Zb=Zb;
00115           tempList[n].epri=4;  //this means M lines 
00116           tempList[n].esec=j;   //this is the index inside the M group 
00117           tempList[n].abs=ib;
00118           tempList[n].Ea=enerA->M_[j];
00119           tempList[n].sigmaphoto=sigmaphoto(ib, AbsC, Zb, enerA->M_[j]);
00120           n++;
00121         }
00122       }
00123     }
00124   }
00125   
00126   //If any pair of emission of A and absorption by B matched the criteria, reallocate the SFClist and write the new entries.
00127   if(n>0){
00128     *SFCList =(SFCListElem*)realloc(*SFCList, (*nSFCList + n)*sizeof(SFCListElem));
00129     if (*SFCList==NULL){fprintf(stderr,"\n Error allocating memory (SFCList)\n");exit(1);}
00130   }
00131   for(i=0;i<n;i++)(*SFCList)[*nSFCList+i]=tempList[i];
00132   
00133   *nSFCList+=n;
00134   
00135   return(n); 
00136 }
00137 
00138 /*(see) eq. 2.18 of ref [1]*/
00139 double sigmaphoto(int iabs, const AbsCoef *AbsC, atomicnumber Zb, double Xray)
00140 {
00141   double result;
00142   double abs;
00143   int iener;
00144   int i;
00145   double stdener[23] = {      1.00, 1.25, 1.50, 1.75, 2.00, 
00146                         2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 
00147                         5.50, 6.00, 6.50, 7.00, 8.00, 10.0,
00148                         12.5, 15.0, 17.5, 20.0, 25.0, 30.0};
00149   
00150   i=iabs-1;
00151   
00152   /*  (S-1)/S = (1-1/S) = ( 1 - 1/(coefener[1]/coefener[0]) ) = ( 1 - coefener[0]/coefener[1] ) */
00153   
00154   switch(iabs){
00155     case 1:  //K absorption
00156       result=( 1.-AbsC->coefenr[0][0]/AbsC->coefenr[0][1] );
00157     break;
00158     case 2:  //LI absorption
00159       result=( 1. - AbsC->coefenr[1][0]/AbsC->coefenr[1][1] );
00160     break;
00161     case 3:  //LII absorption
00162       result=( 1.-AbsC->coefenr[2][0]/AbsC->coefenr[2][1] );
00163       if(Xray > AbsC->enr[2]) result*= AbsC->coefenr[1][0]/AbsC->coefenr[1][1]; //Xray > E(LI)
00164     break;
00165     case 4:  //LIII absorption
00166       result=( 1.-AbsC->coefenr[3][0]/AbsC->coefenr[3][1] );
00167       if(Xray > AbsC->enr[3]) result*= AbsC->coefenr[2][0]/AbsC->coefenr[2][1]; //Xray > E(LII)
00168       if(Xray > AbsC->enr[2]) result*= AbsC->coefenr[1][0]/AbsC->coefenr[1][1]; //Xray > E(LI)
00169     break;
00170     case 5:  //MI absorption
00171     case 6:  //MII absorption
00172     case 7:  //MIII absorption
00173     case 8:  //MIV absorption
00174     case 9:  //MV absorption
00175       result=( 1.-AbsC->coefenr[4][0]/AbsC->coefenr[i][1] ); 
00176     break;
00177   }
00178   
00179   //locate the "std energy index"
00180   for(iener=1;Xray > stdener[iener];iener++);
00181   
00182   //calculate the absorption cross section by the element Zb 
00183   abs=TotAbsor_elemental(iener, AbsC, Zb, Xray);  
00184   
00185   //return the sigmaphoto value
00186   return(result*abs);  
00187 }
00188 
00189 
00190 /* *Calculates the probability for an X-ray (from A) being absorbed (by B) and produce a  from a given line of the element B af
00191  * 
00192  * See eq. (2.5) of ref [1]
00193  *
00194  *Ref. [1]: "Correcoes de Fluorescencia Secundaria em PIXE", M.A. Reis, Master Thesis (1993). 
00195  *
00196  * @param TotAbsCoefArray 
00197  * @param pSFC 
00198  * @param plyr 
00199  * @return Rba*mu(A) in cm2/1e15at
00200  */
00201 /*
00202 double SFC_RbaMu(const AbsCoef *TotAbsCoefArray, const SFCListElem *pSFC, const LYR *plyr)
00203 {
00204 }
00205 */
00206 
00207 /*
00208 void Rbeta(Char *FAbNm, FluorCKCoef FCK, atomicnumber AtNTra,
00209      double XEner, CalibYld *Rba)
00210 {
00211   int i, j;
00212   double SigBA[10];
00213 
00214   memcpy(&SigBA[1], &NineArrayNul[1], sizeof(double) * 9);
00215       //   1-K  2-LI  3-LII  4-LIII   5...-M... 
00216   FotSec(FAbNm, AtNTra, FCK.ck[0], FCK.ck[1], FCK.ck[2], XEner, &SigBA[1]);
00217   *Rba = CYldNul;
00218   
00219   if (SigBA[1] > 0) {
00220     for (i = 1; i <= 3; i++)
00221       Rba->K_[i] = SigBA[1] * FCK.w[1] * FCK.k.K_[i] ;
00222   }
00223   if (SigBA[5] > 0) {
00224     for (i = 1; i <= 3; i++)
00225       Rba->M_[i] = SigBA[5] * FCK.w[5] * FCK.k.M_[i] ;
00226   }
00227   for (i = 1; i <= 3; i++) {
00228     if (SigBA[5 - i] > 0) {
00229       for (j = 1; j <= 3; j++)
00230         Rba->L_[i][j] = SigBA[5 - i] * FCK.w[5 - i] * FCK.k.L_[i][j] ;
00231     }
00232   }
00233 }
00234 */
00235 
00236 
00237 /**Checks if a value is within limits
00238  * 
00239  * @param value (I) Value to check 
00240  * @param min (I) minimum limit 
00241  * @param max (I) maximum limit
00242  * @return 1 if value is inside range, 0 otherwise
00243  */
00244 int inrange(double value,double min, double max)
00245 {
00246   if(value<min || value>max) return(0);
00247   else return(1);
00248 }
00249 

Generated on Fri Jul 15 20:43:49 2005 for LibCPIXE API by  doxygen 1.3.9.1