libcpixe/sfc.c

Go to the documentation of this file.
00001 /***************************************************************************
00002     Copyright (C) 2007 by Carlos Pascual-Izarra
00003     carlos.pascual_AT_users.sourceforge.net                                                  *
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 3 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, see <http://www.gnu.org/licenses/>.
00017 
00018  ***************************************************************************/
00019 
00020 #include <stdio.h>
00021 #include <math.h>
00022 #include <string.h>
00023 #include <stdlib.h>
00024 #include "libcpixe.h"
00025 #include "compilopt.h"  //here we store variables for the C preprocessor for conditional compiling
00026 
00027 
00035 int createSFCList(const EXP_PARAM *pexp, const int *PresentElems, const XrayYield *XYldArray, const AbsCoef *TotAbsCoefArray, int *nSFCList, SFCListElem **SFCList)
00036 {
00037   int Za,Zb;
00038   int dim;
00039 
00040   *nSFCList=0;
00041   *SFCList=NULL;
00042 
00043   dim=pexp->simpar.MaxZinsample+1;
00044 
00045   for(Zb=minK;Zb<dim;Zb++){
00046     if(PresentElems[Zb]){
00047       for(Za=minK;Za<dim;Za++){
00048         if(PresentElems[Za]){
00049           needSFC(Za, Zb, &XYldArray[Za].ener, &TotAbsCoefArray[Zb], nSFCList, SFCList);
00050         }
00051       }
00052     }
00053   }
00054   return(0);
00055 }
00056 
00057 int needSFC(atomicnumber Za, atomicnumber Zb, const CalibYld *enerA, const AbsCoef *AbsC, int *nSFCList, SFCListElem **SFCList )
00058 {
00059   int j,l,i,ib,nabs;
00060   int n;
00061   double enerB,enerB_K,enerB_LIII;
00062   SFCListElem tempList[135]; 
00063 
00064   if(Za<minK || Zb <minK ) {
00065     return(0);
00066   }
00067 
00068   nabs=4; 
00069 
00070   if(Zb<minL)nabs=1;
00071 
00072   enerB_K=AbsC->enr[0];
00073   if(enerB_K<0.001)enerB_K=HUGE;
00074   enerB_LIII=AbsC->enr[4];
00075   if(enerB_LIII<0.001)enerB_LIII=HUGE;
00076 
00077   //loop through all the absorption energies of the B element
00078   for (n=0, ib=1;ib<=nabs;ib++){
00079     enerB=AbsC->enr[ib]; //energy of absorption edge
00080     if(enerB>0){
00081       //K emission lines:
00082       for (j = 1; j <= 3; j++) {
00083         if(enerA->K_[j]>enerB){
00084           tempList[n].Za=Za;
00085           tempList[n].Zb=Zb;
00086           tempList[n].epri=0;  //this means K lines
00087           tempList[n].esec=j;   //this is the index inside the K group
00088           tempList[n].abs=ib;  //Absorptions for: ib=1-->K ; ib=2,..4--> L ; ib=5,..9-->M
00089           tempList[n].Ea=enerA->K_[j];
00090           tempList[n].sigmaphoto=sigmaphoto(ib, AbsC, Zb, enerA->K_[j]);
00091           n++;
00092         }
00093       }
00094       //L emission lines
00095       if(Za>minL) for (j = 1; j <= 3 ; j++) for (l = 1; l <= 3; l++) {
00096         if(inrange(enerA->L_[j][l],enerB,enerB_K)) {
00097           tempList[n].Za=Za;
00098           tempList[n].Zb=Zb;
00099           tempList[n].epri=j;  //j=1-->LIII, j=2-->LII, j=3-->LI
00100           tempList[n].esec=l;   //this is the index inside the Lj group
00101           tempList[n].abs=ib;
00102           tempList[n].Ea=enerA->L_[j][l];
00103           tempList[n].sigmaphoto=sigmaphoto(ib, AbsC, Zb, enerA->L_[j][l]);
00104           n++;
00105         }
00106       }
00107       //M emission lines
00109       if(Za>minM) for (j = 1; j <= 3; j++) {
00110         if(inrange(enerA->M_[j],enerB,enerB_LIII) ) {
00111           tempList[n].Za=Za;
00112           tempList[n].Zb=Zb;
00113           tempList[n].epri=4;  //this means M lines
00114           tempList[n].esec=j;   //this is the index inside the M group
00115           tempList[n].abs=ib;
00116           tempList[n].Ea=enerA->M_[j];
00117           tempList[n].sigmaphoto=sigmaphoto(ib, AbsC, Zb, enerA->M_[j]);
00118           n++;
00119         }
00120       }
00121     }
00122   }
00123 
00124   //If any pair of emission of A and absorption by B matched the criteria, reallocate the SFClist and write the new entries.
00125   if(n>0){
00126     *SFCList =(SFCListElem*)realloc(*SFCList, (*nSFCList + n)*sizeof(SFCListElem));
00127     if (*SFCList==NULL){fprintf(stderr,"\n Error allocating memory (SFCList)\n");exit(1);}
00128   }
00129   for(i=0;i<n;i++)(*SFCList)[*nSFCList+i]=tempList[i];
00130 
00131   *nSFCList+=n;
00132 
00133   return(n);
00134 }
00135 
00136 /*(see) eq. 2.18a-h of ref [1]*/
00137 double sigmaphoto(int iabs, const AbsCoef *AbsC, atomicnumber Zb, double Xray)
00138 {
00139   double result;
00140   double abs;
00141   int iener;
00142   int i;
00143   double stdener[23] = {      1.00, 1.25, 1.50, 1.75, 2.00,
00144                         2.50, 3.00, 3.50, 4.00, 4.50, 5.00,
00145                         5.50, 6.00, 6.50, 7.00, 8.00, 10.0,
00146                         12.5, 15.0, 17.5, 20.0, 25.0, 30.0};
00147 
00148   i=iabs-1;
00149 
00150   /*  (S-1)/S = (1-1/S) = ( 1 - 1/(coefener[1]/coefener[0]) ) = ( 1 - coefener[0]/coefener[1] ) */
00151 
00152   switch(iabs){
00153     case 1:  //K absorption
00154       result=( 1.-AbsC->coefenr[0][0]/AbsC->coefenr[0][1] );
00155     break;
00156     case 2:  //LI absorption
00157       result=( 1. - AbsC->coefenr[1][0]/AbsC->coefenr[1][1] );
00158     break;
00159     case 3:  //LII absorption
00160       result=( 1.-AbsC->coefenr[2][0]/AbsC->coefenr[2][1] );
00161       if(Xray > AbsC->enr[2]) result*= AbsC->coefenr[1][0]/AbsC->coefenr[1][1]; //Xray > E(LI)
00162     break;
00163     case 4:  //LIII absorption
00164       result=( 1.-AbsC->coefenr[3][0]/AbsC->coefenr[3][1] );
00165       if(Xray > AbsC->enr[3]) result*= AbsC->coefenr[2][0]/AbsC->coefenr[2][1]; //Xray > E(LII)
00166       if(Xray > AbsC->enr[2]) result*= AbsC->coefenr[1][0]/AbsC->coefenr[1][1]; //Xray > E(LI)
00167     break;
00168     case 5:  //MI absorption
00169     case 6:  //MII absorption
00170     case 7:  //MIII absorption
00171     case 8:  //MIV absorption
00172     case 9:  //MV absorption
00173       result=( 1.-AbsC->coefenr[4][0]/AbsC->coefenr[i][1] );
00174     break;
00175   }
00176 
00177   //locate the "std energy index"
00178   for(iener=1;Xray > stdener[iener];iener++);
00179 
00180   //calculate the absorption cross section by the element Zb
00181   abs=TotAbsor_elemental(iener, AbsC, Zb, Xray);
00182 
00183   //return the sigmaphoto value
00184   return(result*abs);
00185 }
00186 
00187 
00188 /* *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
00189  *
00190  * See eq. (2.5) of ref [1]
00191  *
00192  *Ref. [1]: "Correcoes de Fluorescencia Secundaria em PIXE", M.A. Reis, Master Thesis (1993).
00193  *
00194  * @param TotAbsCoefArray
00195  * @param pSFC
00196  * @param plyr
00197  * @return Rba*mu(A) in cm2/1e15at
00198  */
00199 /*
00200 double SFC_RbaMu(const AbsCoef *TotAbsCoefArray, const SFCListElem *pSFC, const LYR *plyr)
00201 {
00202 }
00203 */
00204 
00205 /*
00206 void Rbeta(Char *FAbNm, FluorCKCoef FCK, atomicnumber AtNTra,
00207      double XEner, CalibYld *Rba)
00208 {
00209   int i, j;
00210   double SigBA[10];
00211 
00212   memcpy(&SigBA[1], &NineArrayNul[1], sizeof(double) * 9);
00213       //   1-K  2-LI  3-LII  4-LIII   5...-M...
00214   FotSec(FAbNm, AtNTra, FCK.ck[0], FCK.ck[1], FCK.ck[2], XEner, &SigBA[1]);
00215   *Rba = CYldNul;
00216 
00217   if (SigBA[1] > 0) {
00218     for (i = 1; i <= 3; i++)
00219       Rba->K_[i] = SigBA[1] * FCK.w[1] * FCK.k.K_[i] ;
00220   }
00221   if (SigBA[5] > 0) {
00222     for (i = 1; i <= 3; i++)
00223       Rba->M_[i] = SigBA[5] * FCK.w[5] * FCK.k.M_[i] ;
00224   }
00225   for (i = 1; i <= 3; i++) {
00226     if (SigBA[5 - i] > 0) {
00227       for (j = 1; j <= 3; j++)
00228         Rba->L_[i][j] = SigBA[5 - i] * FCK.w[5 - i] * FCK.k.L_[i][j] ;
00229     }
00230   }
00231 }
00232 */
00233 
00234 
00242 int inrange(double value,double min, double max)
00243 {
00244   if(value<min || value>max) return(0);
00245   else return(1);
00246 }
00247 

Generated on Sat Dec 8 23:11:36 2007 for libCPIXE by  doxygen 1.5.4