libcpixe/libcpixe.c

Go to the documentation of this file.
00001 
00002 /***************************************************************************
00003     Copyright (C) 2007 by Carlos Pascual-Izarra
00004     carlos.pascual_AT_users.sourceforge.net                                                  *
00005 
00006     This program is free software: you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation, either version 3 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 
00019  ***************************************************************************/
00020 
00043 
00044 
00045 
00046 
00047 
00048 #include <stdio.h>
00049 #include <math.h>
00050 #include <string.h>
00051 #include <stdlib.h>
00052 #include "libcpixe.h"
00053 #include "stop96.h"
00054 #include "compilopt.h"  //here we store variables for the C preprocessor for conditional compiling
00055 
00056 
00057 
00058 
00059 /*Global Constants*/
00060 
00061 /*Physical constants of interest*/
00062 // double m0c2 = 1.503186433e-0010, keV = 1.60621e-0016, uAtmass = 1 / 1822.887,
00063 //        M1sme = 1836.076012, m0pamu = 1.007276470, m0pMeV = 938.3,
00064 //        MeVpamu = 931.52181, v0 = 2.187578544e6, v02 = 4.785499886e12,
00065 //        c2 = 8.98740441e16, cau = 137.03604, pi = 3.141592654,
00066 //        a02 = 2.800283608e-21, Ry = 13.6, Hr = 27.2116, barn = 1.0e-28;
00067 
00068 
00069 
00070 /*Functions*/
00071 
00072 
00080 int readINPUT(const char *InputFileNm, EXP_PARAM *pexppar, EXTRAINFO *pExtraInfo)
00081 {
00082   FILE *f;
00083   int i;
00084   char *command,*arg;
00085   char line[LONGSTRINGLENGTH]="";
00086   int flag[16]; /*We use 11 control flags to check that the reading was fine (they must all end with a value different than 0)*/
00087 
00088   /*Reset control flags*/
00089   for(i=0;i<16;i++)flag[i]=0;
00090   pExtraInfo->WantOutputfile=0;
00091   pexppar->ioncharge=-1; //initialize the ion charge to an impossible value
00092   //set to -1 (which is true) some flags regarding to non-mandatory commands (and set default value for those commands);
00093   pexppar->simpar.AllowSXFCorr=0;flag[10]=-1;
00094   pexppar->simpar.AllowXEqCalc=0; flag[11]=-1;
00095   f = fopen(InputFileNm, "r");
00096   if (f == NULL)
00097     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",InputFileNm);exit(1);}
00098 
00099   /*Skip until "BEGIN_INPUT"*/
00100   for(;!feof(f) && strcasecmp(line, "BEGIN_INPUT");){
00101    fscanf(f,"%255s",line);
00102    flag[0]=1;
00103   }
00104 
00105   for(;!feof(f);){
00106     //reads an entire line of at much LONGSTRINGLENGTH characters
00107     fgets(line,sizeof(line),f);
00108     //Now we parse the line looking for a known command and discarding comments
00109     command = strtok( line, "\n\t \r" ) ;
00110     if( command != NULL && command[0] != '#' ){
00111 
00112 
00113 
00114       /*"END_INPUT" command just exits the for loop*/
00115       if(!strcmp(command,"END_INPUT")){
00116         flag[1]=1;
00117         break;
00118       }
00119       else if(!strcmp(command,"ION")){
00120         /*Syntax:
00121         ION symbol   <---"symbol" is the beam ion chem. symbol. The Most abundant isotope will be used by default. */
00122         arg=strtok( NULL,"\n\t \r");
00123         strncpy(pexppar->ion.symbol,arg,3);
00125         if (strncasecmp(pexppar->ion.symbol,"H",3))
00126           {fprintf(stderr,"\nERROR: Currently, only H ions are supported\n");exit(1);}
00127         pexppar->ion.Z=symbol2Z(pexppar->ion.symbol);
00128         pexppar->ion.A=Z2mass(pexppar->ion.Z, &pexppar->ion.IM,'m');
00129         Z2mass(pexppar->ion.Z, &pexppar->ion.M,'n');
00130         flag[2]=1;
00131         //printf("\n\n!!!!!!!!!!!!!!!!!!!!!!!! ION='%s'\n\n",pexppar->ion.symbol);getchar();
00132       }
00133       else if(!strcmp(command,"IONMASS")){
00134         /*Syntax:
00135         IONMASS mass   <---"mass" is the beam ion weight in amu. This can be used for defining isotopes. */
00136         arg=strtok( NULL,"\n\t \r");
00137         pexppar->ion.M=atof(arg);
00138         /*Note that this is an optional command, no flag is changed*/
00139       }
00140       else if(!strcmp(command,"IONCHARGE")){
00141         /*Syntax:
00142         IONCHARGE charge   <---"charge" is the beam ion charge in electron charge units.*/
00143         arg=strtok( NULL,"\n\t \r");
00144         pexppar->ioncharge=abs(atof(arg));
00145         /*Note that this is an optional command, no flag is changed. Default value=1 */
00146       }
00147       else if(!strcmp(command,"KEV")){
00148         /*Syntax:
00149         KEV Ebeam   <---"Ebeam" is Beam energy in keV.  */
00150         arg=strtok( NULL,"\n\t \r");
00151         pexppar->BeamEner=atof(arg);
00152         flag[3]=1;
00153       }
00154       else if(!strcmp(command,"INCANG")){
00155         /*Syntax:
00156         INCANG thetavalue   <---Incience angle: Sample normal to beam*/
00157         arg=strtok( NULL,"\n\t \r");
00158         pexppar->IncAng=atof(arg);
00159         pexppar->IncAng *= DEG2RAD;
00160         pexppar->cosInc = cos(pexppar->IncAng);
00161         flag[4]=1;
00162         }
00163       else if(!strcmp(command,"EXITANG")){
00164         /*Syntax:
00165         EXITANG phivalue   <---Exit angle. Sample normal to detector. */
00166         arg=strtok( NULL,"\n\t \r");
00167         pexppar->DetAng=atof(arg);
00168         pexppar->DetAng *= DEG2RAD;
00169         pexppar->cosDet = cos(pexppar->DetAng);
00170         flag[5]=1;
00171       }
00172       else if(!strcmp(command,"BEAMCOL")){
00173         /*Syntax:
00174         BEAMCOL diameter   <--Beam diameter, in mm */
00175         arg=strtok( NULL,"\n\t \r");
00176         pexppar->BeamCol=atof(arg);
00177         pexppar->BeamCross = M_PI * (pexppar->BeamCol*pexppar->BeamCol) / 400;   /* beam cross-section in cm2 */
00178         flag[6]=1;
00179       }
00180       else if(!strcmp(command,"DETCOLFAC")){
00181         /*Syntax:
00182         DETCOLFAC factor   <---Detector colimator factor
00183         (Use this if using DATTPIXE-style calibration files... [DEPRECATED] )*/
00184         arg=strtok( NULL,"\n\t \r");
00185         pexppar->DetColFac=atof(arg);
00186         flag[7]=1;  //note that this flag can also be raised true (but 2) with SOLIDANGLE
00187         fprintf(stderr,"\n WARNING: Deprecated command '%s'. It may trigger bugs.\n Press <INTRO> to continue ...***\n",command);
00188         getchar();
00189       }
00190       else if(!strcmp(command,"SOLIDANGLE")){
00191         /*Syntax:
00192         SOLIDANGLE factor   <---Detector Solid Angle in msr [DEPRECATED]
00193         (Use this if using Efficiency-style calibration files [Recomended])*/
00194         arg=strtok( NULL,"\n\t \r");
00195         pexppar->SAngFract=atof(arg)/(4000.*M_PI);
00196         flag[7]=2;  //note that this flag be raised true with DETCOLFAC, SOLIDANGLE, SOLIDANGLEMSR or SOLIDANGLEFRAC
00197         fprintf(stderr,"\n WARNING: Deprecated command '%s'. Use SOLIDANGLEFRAC or SOLIDANGLEMSR instead.\n Press <INTRO> to continue ...***\n",command);
00198         getchar();
00199       }
00200       else if(!strcmp(command,"SOLIDANGLEMSR")){
00201         /*Syntax:
00202         SOLIDANGLEMSR msr   <---Detector Solid Angle in msr
00203         (Use this if using Efficiency-style calibration files [Recomended])*/
00204         arg=strtok( NULL,"\n\t \r");
00205         pexppar->SAngFract=atof(arg)/(4000.*M_PI);
00206         flag[7]=3;  
00207       }
00208       else if(!strcmp(command,"SOLIDANGLEFRAC")){
00209         /*Syntax:
00210         SOLIDANGLEFRAC factor   <---Detector Solid Angle fraction (solid angle/4PI)
00211         (Use this if using Efficiency-style calibration files [Recomended])*/
00212         arg=strtok( NULL,"\n\t \r");
00213         pexppar->SAngFract=atof(arg);
00214         flag[7]=4;  //note that this flag be raised true with DETCOLFAC, SOLIDANGLE, SOLIDANGLEMSR or SOLIDANGLEFRAC
00215       }
00216       else if(!strcmp(command,"CHARGE")){
00217         /*Syntax:
00218         CHARGE ColCharge   <---Collected charge, in uC */
00219         arg=strtok( NULL,"\n\t \r");
00220         pexppar->simpar.ColCharge=atof(arg);
00221         flag[8]=1;
00222       }
00223       else if(!strcmp(command,"LIVETIME")){
00224         /*Syntax:
00225         LIVETIME factor   <---Dead time correction (Integrated"Charge"/IntegratedCounts) */
00226         arg=strtok( NULL,"\n\t \r");
00227         pexppar->simpar.DTCC=atof(arg);
00228         flag[9]=1;
00229       }
00230       else if(!strcmp(command,"ALLOWSXFCORR")){
00231         /*Syntax:
00232         ALLOWSXFCORR flag   <---Flag allowing for calculation of Sec. Fluorescence  */
00233         arg=strtok( NULL,"\n\t \r"); 
00234         pexppar->simpar.AllowSXFCorr=atoi(arg);
00235         flag[10]=1;
00236       }
00237       else if(!strcmp(command,"ALLOWXEQCALC")){
00238         /*Syntax:
00239         ALLOWXEQCALC flag   <---Deat time correction (Integrated"Charge"/IntegratedCounts) */
00240         arg=strtok( NULL,"\n\t \r"); 
00241         pexppar->simpar.AllowXEqCalc=atoi(arg);
00242         flag[11]=1;
00243       }
00244       else if(!strcmp(command,"CALIBFILE") || !strcmp(command,"DTCALIBFILE")){
00245         /*Syntax:
00246         DTCALIBFILE Calfilename     <---Name of the calibration  (XrayYld) file
00247         (Use this if using DATTPIXE-style calibration files [DEPRECATED])
00248         Note CALIBFILE is, at this moment an alias for DTCALIBFILE, but this will change to EFFCALIBFILE in a future
00249         */
00250         arg=strtok( NULL,"\n\t \r");
00251         if(!(pExtraInfo->CalibFileNm=(char*)calloc(LONGSTRINGLENGTH,sizeof(char)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00252         strncpy(pExtraInfo->CalibFileNm,arg,LONGSTRINGLENGTH);
00253         flag[12]=1;
00254         fprintf(stderr,"\n WARNING: Deprecated command '%s'. It may trigger bugs.\n Press <INTRO> to continue ...***\n",command);
00255       }
00256       else if(!strcmp(command,"EFFCALIBFILE")){
00257         /*Syntax:
00258         EFFCALIBFILE Calfilename     <---Name of the Efficiency calibration file
00259         (Use this if using Efficiency-style calibration files [Recomended])
00260         */
00261         arg=strtok( NULL,"\n\t \r");
00262         if(!(pExtraInfo->CalibFileNm=(char*)calloc(LONGSTRINGLENGTH,sizeof(char)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00263         strncpy(pExtraInfo->CalibFileNm,arg,LONGSTRINGLENGTH);
00264         flag[12]=2;
00265       }
00266       else if(!strcmp(command,"SAMPLEFILE")){
00267         /*Syntax:
00268         SAMPLEFILE SampleFilename     <---Name of the Sample definition file
00269         */
00270         arg=strtok( NULL,"\n\t \r");
00271         if(!(pExtraInfo->SampleFileNm=(char*)calloc(LONGSTRINGLENGTH,sizeof(char)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00272         strncpy(pExtraInfo->SampleFileNm,arg,LONGSTRINGLENGTH);
00273         flag[13]=1;
00274       }
00275       else if(!strcmp(command,"FILTERFILE")){
00276         /*Syntax:
00277         FILTERFILE Filterfilename     <---Name of the Filter definition file
00278         */
00279         arg=strtok( NULL,"\n\t \r");
00280         if(!(pExtraInfo->FilterFileNm=(char*)calloc(LONGSTRINGLENGTH,sizeof(char)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00281         strncpy(pExtraInfo->FilterFileNm,arg,LONGSTRINGLENGTH);
00282         flag[14]=1;
00283       }
00284       else if(!strcmp(command,"CFLAGSFILE")){
00285         /*Syntax:
00286         CFLAGSFILE CFlagsfilename     <---Name of the Calculation flags definition file
00287         */
00288         arg=strtok( NULL,"\n\t \r");
00289         if(!(pExtraInfo->AreasFileNm=(char*)calloc(LONGSTRINGLENGTH,sizeof(char)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00290         strncpy(pExtraInfo->AreasFileNm,arg,LONGSTRINGLENGTH);
00291         pExtraInfo->AreasFormat=1;
00292         flag[15]=1;
00293       }
00294       else if(!strcmp(command,"DTAREASFILE")){
00295         /*Syntax:
00296         DTAREASFILE DTAreasfilename     <---Name of the Areas file (in DATTPIXE format)
00297         */
00298         arg=strtok( NULL,"\n\t \r");
00299         if(!(pExtraInfo->AreasFileNm=(char*)calloc(LONGSTRINGLENGTH,sizeof(char)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00300         strncpy(pExtraInfo->AreasFileNm,arg,LONGSTRINGLENGTH);
00301         pExtraInfo->AreasFormat=2;
00302         flag[15]=1;
00303       }
00304       else if(!strcmp(command,"DBPATH")){
00305         /*Syntax:
00306         DBPATH Path   <---Path to DataBase files (optional)
00307         */
00308         arg=strtok( NULL,"\n\t \r");
00309         if(!(pExtraInfo->DBpath=(char*)calloc(LONGSTRINGLENGTH,sizeof(char)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00310         strncpy(pExtraInfo->DBpath,arg,LONGSTRINGLENGTH);
00311       }
00312       else if(!strcmp(command,"OUTPUTFILE")){
00313         /*Syntax:
00314         OUTPUTFILE Outputfilename   <---Name for the output file
00315         */
00316         arg=strtok( NULL,"\n\t \r");
00317         if(!(pExtraInfo->OutputFileNm=(char*)calloc(LONGSTRINGLENGTH,sizeof(char)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00318         strncpy(pExtraInfo->OutputFileNm,arg,LONGSTRINGLENGTH);
00319         pExtraInfo->WantOutputfile=1;
00320         /*note: this command is optional, but a flag indicating if it was used is passed*/
00321       }
00322       else if(!strcmp(command,"DETECTORFILE")){
00323         /*Syntax:
00324         DETECTORFILE Detectorfilename   <---Name for the detector definition file (Optional)
00325         */
00326         arg=strtok( NULL,"\n\t \r");
00327         if(!(pExtraInfo->DetectorFileNm=(char*)calloc(LONGSTRINGLENGTH,sizeof(char)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00328         strncpy(pExtraInfo->DetectorFileNm,arg,LONGSTRINGLENGTH);
00329         pExtraInfo->givendetectorfile=1;
00330         /*note: this command is optional, but a flag indicating if it was used is passed*/
00331       }
00332       /*If "command" is not valid...*/
00333       else {
00334         fprintf(stderr,"\n ERROR:ReadInput: command '%s' not known. Press <INTRO> to continue ...***\n",command);
00335         getchar();
00336       }
00337     }
00338   }
00339 
00340   //close input file
00341   fclose(f);
00342 
00343   /*check control flags*/
00344   for(i=0;i<16;i++)if(flag[i]==0){fprintf(stderr,"\n ERROR:ReadInput: Missing command in inputfile (#%i)\n",i);exit(1);}
00345 
00346   pexppar->cosFac = pexppar->cosInc / pexppar->cosDet;
00347 
00348   pexppar->FinalEner = 0.1 * pexppar->BeamEner;  //below this energy no calculations will be done
00349   if(pexppar->FinalEner>100.)pexppar->FinalEner = 100.;
00350 
00351   /*Calculate Fluence*/
00352   if (pexppar->ioncharge <0.){
00353     pexppar->ioncharge=1.;
00354     if (pexppar->ion.Z>1) printf("\n Warning: Ion charge not provided, assuming =1\n");
00355     }
00356   pexppar->Fluence=pexppar->simpar.ColCharge*pexppar->simpar.DTCC/(pexppar->ioncharge*ELECTRONCHARGE_IN_UC);
00357 
00358   /*Decide which scheme for calibration will be used*/
00359   if (flag[7]==1 && flag[12]==1) pExtraInfo->useefficiencies=0;
00360   else if (flag[7]>=2 && flag[12]==2) pExtraInfo->useefficiencies=1;
00361   else {fprintf(stderr,"\n ERROR:use either [DETCOLFAC+CALIBFILE] or [SOLIDANGLE+EFFCALIBFILE] \n");exit(1);}
00362 
00363   return(0);
00364 
00365 }
00366 
00367 
00368 
00369 
00377 int symbol2Z
00378 (char *symbol){
00379   int Z;
00381 /*  ChemSymb chsymbols[110] = {
00382     "--", "H" , "He", "Li", "Be", "B" , "C" , "N" , "O" , "F" , "Ne", "Na",
00383     "Mg", "Al", "Si", "P" , "S" , "Cl", "Ar", "K" , "Ca", "Sc", "Ti", "V" ,
00384     "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br",
00385     "Kr", "Rb", "Sr", "Y" , "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag",
00386     "Cd", "In", "Sn", "Sb", "Te", "I" , "Xe", "Cs", "Ba", "La", "Ce", "Pr",
00387     "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu",
00388     "Hf", "Ta", "W" , "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi",
00389     "Po", "At", "Rn", "Fr", "Ra", "Ac", "Th", "Pa", "U" , "Np", "Pu", "Am",
00390     "Cm", "Bk", "Cf", "Es", "Fm", "Md", "No", "Lr", "Rf", "Db", "Sg", "Bh",
00391     "Hs", "Mt"
00392   };*/
00393   for(Z=1;strncasecmp(symbol,ChemicalSymbol[Z],3) && Z<=99;Z++);
00394   if(Z<1 || Z> 109) {fprintf(stderr,"\nERROR: Chemical Symbol '%s' not known.\n",symbol);exit(1);}
00395   else return(Z);
00396 }
00397 
00398 
00409 int Z2mass(int Z, double *mass, char option)
00410 {
00411   int maiAArray[93]={
00412       0 ,       1 ,       4 ,       7 ,       9 ,      11 ,      12 ,      14 ,
00413      16 ,      19 ,      20 ,      23 ,      24 ,      27 ,      28 ,      31 ,
00414      32 ,      35 ,      40 ,      39 ,      40 ,      45 ,      48 ,      51 ,
00415      52 ,      55 ,      56 ,      59 ,      58 ,      63 ,      64 ,      69 ,
00416      74 ,      75 ,      80 ,      79 ,      84 ,      85 ,      88 ,      89 ,
00417      90 ,      93 ,      98 ,      97 ,     102 ,     103 ,     106 ,     107 ,
00418     114 ,     115 ,     120 ,     121 ,     130 ,     127 ,     132 ,     133 ,
00419     138 ,     139 ,     140 ,     141 ,     142 ,     148 ,     152 ,     153 ,
00420     158 ,     159 ,     164 ,     165 ,     166 ,     169 ,     174 ,     175 ,
00421     180 ,     181 ,     184 ,     187 ,     192 ,     193 ,     195 ,     197 ,
00422     202 ,     205 ,     208 ,     209 ,     209 ,     210 ,     222 ,     223 ,
00423     226 ,     227 ,     232 ,     231 ,     238};
00424 
00425   double maiMArray[93]={
00426      0.000  ,   1.008 ,   4.003 ,   7.016 ,   9.012 ,  11.009 ,  12.000 ,  14.003 ,
00427      15.995 ,  18.998 ,  19.992 ,  22.990 ,  23.985 ,  26.982 ,  27.977 ,  30.974 ,
00428      31.972 ,  34.969 ,  39.962 ,  38.964 ,  39.963 ,  44.956 ,  47.950 ,  50.940 ,
00429      51.940 ,  54.940 ,  55.935 ,  58.930 ,  57.940 ,  62.930 ,  63.930 ,  68.930 ,
00430      73.920 ,  74.920 ,  79.920 ,  78.920 ,  83.912 ,  84.910 ,  87.910 ,  88.906 ,
00431      89.900 ,  92.910 ,  97.905 ,  97.000 , 101.900 , 102.900 , 105.900 , 106.900 ,
00432     113.900 , 114.900 , 119.900 , 120.900 , 129.906 , 126.900 , 131.904 , 132.905 ,
00433     137.905 , 139.000 , 140.000 , 141.000 , 142.000 , 148.000 , 152.000 , 153.000 ,
00434     157.900 , 158.925 , 164.000 , 165.000 , 166.000 , 169.000 , 174.000 , 175.000 ,
00435     180.000 , 181.000 , 184.000 , 187.000 , 192.000 , 193.000 , 195.000 , 197.000 ,
00436     202.000 , 205.000 , 208.000 , 209.000 , 208.982 , 210.000 , 222.000 , 223.000 ,
00437     226.000 , 227.000 , 232.000 , 231.000 , 238.040 };
00438 
00439   double natMArray[93]={
00440       0.000 ,   1.008 ,   4.003 ,   6.941 ,   9.012 ,  10.811 ,  12.011 ,  14.007 ,
00441      15.999 ,  18.998 ,  20.180 ,  22.990 ,  24.305 ,  26.982 ,  28.086 ,  30.974 ,
00442      32.066 ,  35.453 ,  39.948 ,  39.098 ,  40.080 ,  44.956 ,  47.900 ,  50.942 ,
00443      51.996 ,  54.938 ,  55.847 ,  58.933 ,  58.690 ,  63.546 ,  65.390 ,  69.720 ,
00444      72.610 ,  74.922 ,  78.960 ,  79.904 ,  83.800 ,  85.470 ,  87.620 ,  88.905 ,
00445      91.220 ,  92.906 ,  95.940 ,  97.000 , 101.070 , 102.910 , 106.400 , 107.870 ,
00446     112.400 , 114.820 , 118.710 , 121.750 , 127.600 , 126.900 , 131.300 , 132.910 ,
00447     137.327 , 138.910 , 140.120 , 140.910 , 144.240 , 148.000 , 150.360 , 151.970 ,
00448     157.250 , 158.930 , 162.500 , 164.930 , 167.260 , 168.930 , 173.040 , 174.970 ,
00449     178.490 , 180.950 , 183.850 , 186.200 , 190.200 , 192.200 , 195.080 , 196.970 ,
00450     200.590 , 204.380 , 207.190 , 208.980 , 210.000 , 210.000 , 222.000 , 223.000 ,
00451     226.000 , 227.000 , 232.000 , 231.000 , 238.030 };
00452 
00453   if(Z<1 || Z> 92) {fprintf(stderr,"\nERROR: Data for Atomic number '%d' not available.\n",Z);exit(1);}
00454 
00455   switch(option){
00456     case 'n':  // Natural Mass (i.e., isotopic average) , in amu
00457       *mass=natMArray[Z];
00458       break;
00459     case 'm':  // Most Abundant Isotope mass, in amu
00460       *mass=maiMArray[Z];
00461       break;
00462     default:
00463       {fprintf(stderr,"\nERROR: Z2mass() Option argument can only be 'n' (natural) or 'm' (most abundant) \n");exit(1);}
00464       break;
00465   }
00466 
00467   return(maiAArray[Z]);
00468 }
00469 
00470 
00485 int readCOMPOUND(FILE *f, int nelem, COMPOUND *c)
00486 {
00487   int i,nchar1,nchar2,maxZ;
00488   double sumM;
00489   char temp[30],temp2[30];
00490 
00491   //if(nelem==0)readCOMPOUND2(f, c);  //Modified from the original
00492   if(nelem<1){fprintf(stderr,"\n ERROR: readCOMPOUND must read at least 1 element\n");exit(1);}
00493   else{
00494     c->nelem=nelem;
00495     if(!(c->elem=(ELEMENT*)calloc(nelem,sizeof(ELEMENT)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00496     if(!(c->X=(double*)calloc(nelem,sizeof(double)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00497     if(!(c->xn=(double*)calloc(nelem,sizeof(double)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00498     if(!(c->w=(double*)calloc(nelem,sizeof(double)))){fprintf(stderr,"\n Error allocating memory\n");exit(1);}
00499     for(maxZ=0.,c->sumX=0.,sumM=0.,i=0,nchar1=0,nchar2=0 ; i<nelem ; i++){
00500       fscanf(f,"%2s%lf",(c->elem[i].symbol),&(c->X[i]));
00501       c->elem[i].Z=symbol2Z(c->elem[i].symbol);
00502       c->elem[i].A=Z2mass(c->elem[i].Z, &c->elem[i].IM, 'm');
00503       Z2mass(c->elem[i].Z, &c->elem[i].M, 'n');
00504 
00505 
00506       if(c->elem[i].Z==0){fprintf(stderr,"\n ERROR: Chemical symbol '%s' not valid\n",c->elem[i].symbol);exit(1);}
00507       c->sumX+=c->X[i];
00508       sumM+=c->elem[i].M*c->X[i];
00509       if(c->elem[i].Z>maxZ)maxZ=c->elem[i].Z;
00510       nchar1+=strlen(c->elem[i].symbol);
00511       nchar2+=snprintf(temp,30,"%4lf",c->X[i]);
00512     }
00513     /*Normalize concentrations and calculate the MASS concentration*/
00514     for(i=0;i<nelem;i++){
00515       c->xn[i]=c->X[i]/c->sumX;
00516       c->w[i]=c->X[i]*c->elem[i].M/sumM;
00517     }
00518     /*Build the name of the compound*/
00519     strcpy(temp2,"");
00520     strcpy(temp,"");
00521     if(nchar1+nchar2 < 30 && nelem<4){
00522       for(i=0;i<nelem;i++){
00523         if(c->X[i]!=1.)snprintf(temp,30,"%s%1.lf",c->elem[i].symbol,c->X[i]);
00524         else snprintf(temp,30,"%s",c->elem[i].symbol);
00525         strcat(temp2,temp);
00526       }
00527     }
00528     else if(nchar1<30){
00529       for(i=0;i<nelem;i++){
00530         snprintf(temp,30,"%s",c->elem[i].symbol);
00531         strcat(temp2,temp);
00532       }
00533     }
00534     else{
00535       for(i=0;i<nelem;i++){
00536         snprintf(temp2,25,"%s%s",temp,c->elem[i].symbol);
00537         strcpy(temp,temp2);
00538       }
00539       snprintf(temp2,30,"%s+",temp);
00540     }
00541     strcpy(c->name,temp2);
00542   }
00543   return(maxZ);
00544 }
00545 
00546 
00547 
00548 
00575 int readsample(char *SampleDefFileNm, int *MaxZ, int *NFoil, foil **Sample)
00576 {
00577 
00578   FILE *SampleDefFile;
00579   char dummy[LONGSTRINGLENGTH];
00580   int i,tempZ,j;
00581   foil *pfoil;
00582   double ug2at,natmass;
00583   SampleDefFile = fopen(SampleDefFileNm, "r");
00584   if (SampleDefFile == NULL)
00585     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",SampleDefFileNm);exit(1);}
00586 
00587   /*Skip until "NUMBER OF FOILS"*/
00588   do {
00589     fscanf(SampleDefFile,"%255s",dummy);
00590   } while (strcasecmp(dummy, "NUMBER_OF_FOILS"));
00591 
00592   fscanf(SampleDefFile, "%d", NFoil);
00593 
00594   /*Initialize  Sample*/
00595   //if(*Sample!=NULL)free(*Sample);
00596   *Sample=(foil*)malloc((*NFoil)*sizeof(foil));
00597   if (*Sample==NULL){fprintf(stderr,"\n Error allocating memory (Sample)\n");exit(1);}
00598 
00599   for (*MaxZ=0,i = 0; i < *NFoil ; i++) {
00600     pfoil=&((*Sample)[i]);
00601     do {
00602       fscanf(SampleDefFile,"%255s",dummy);
00603       } while (strcasecmp(dummy, "FOIL"));
00604 
00605     fscanf(SampleDefFile, "%lg %10s", &pfoil->thick, dummy);
00606     if(strcasecmp(dummy,"cm2") && strcasecmp(dummy,"mg")){
00607       fprintf(stderr,"\n Error: Bad syntax in sample definition file: '%s' is not a known thickness unit\n",dummy);exit(1);
00608     }
00609     fscanf(SampleDefFile, "%d",  &pfoil->nfoilelm);
00610     tempZ=readCOMPOUND(SampleDefFile, pfoil->nfoilelm, &pfoil->comp);
00611     if(tempZ>*MaxZ) *MaxZ=tempZ;
00612 
00613     if(!strcasecmp(dummy,"mg")){
00614       /*Convert the value in pfoil->thick from mg/cm2 to 1e15at/cm2 */
00615       for(natmass=0, j=0 ; j<pfoil->nfoilelm ; j++) natmass += pfoil->comp.xn[j] * pfoil->comp.elem[j].M;
00616       ug2at=natmass/602.2141; // (Pm [g/mol] *1e6 [ug/g] / (Navo [at/mol])) * 1e15
00617                               // ==> ug2at is in [ug/1e15at]
00618       pfoil->thick *= (1e3/ug2at);  //Before this, thick was in mg/cm2, hence multiply by 1e3 to get ug/cm2
00619                                      //and then divide by ug2at to get 1e15at/cm2
00620     }
00621 
00622   }
00623   fclose(SampleDefFile);
00624 
00625   return(0);
00626 }
00627 
00640 int createPresentElems(int MaxZ, int NFoil, const foil *MatArray, int **PresentElems)
00641 {
00642   const COMPOUND *pcmp;
00643   int tempZ;
00644   int i,j;
00645 
00646   /*Initialize and fill the PresentElems Array (it is calloc'ed so by default contains 0's*/
00647   *PresentElems=(int*)calloc((MaxZ+1),sizeof(int));
00648   if (*PresentElems==NULL){fprintf(stderr,"\n Error allocating memory (PresentElems)\n");exit(1);}
00649   for(i=0;i<NFoil; i++) {
00650     pcmp=&MatArray[i].comp;
00651     for(j=0 ; j< pcmp->nelem ; j++)  {
00652       tempZ=pcmp->elem[j].Z;
00653       if(tempZ<=MaxZ) (*PresentElems)[tempZ]=1;
00654       else {fprintf(stderr,"\n ERROR: in createPresentElems(): %d > MaxZ (=%d)\n",tempZ,MaxZ);exit(1);}
00655     }
00656   }
00657   return(0);
00658 }
00659 
00660 
00700 int readCalcFlags(const char *CalcFlagsFileNm, const int *PresentElems, int MaxZinsample, int AreasFormat,  CPIXERESULTS **CalcFlags){
00701 
00702   int i,j,tempZ,nread=0;
00703   char dummy[LONGSTRINGLENGTH];
00704   double trash;
00705   ChemSymb tempchem;
00706   CPIXERESULTS *pCFlags;
00707   FILE *CalcFlagsFile;
00708   /*Open File*/
00709   CalcFlagsFile = fopen(CalcFlagsFileNm, "r");
00710   if (CalcFlagsFile== NULL)
00711     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",CalcFlagsFileNm);exit(1);}
00712 
00713   /*Initialize CalcFlags */
00714   *CalcFlags=(CPIXERESULTS*)calloc(MaxZinsample+1,sizeof(CPIXERESULTS));
00715   if (*CalcFlags==NULL){fprintf(stderr,"\n Error allocating memory (CalcFlags)\n");exit(1);}
00716 
00717   /*Initialize the atnums of the present elems (to prevent crashes afterwards) */
00718   for(i=0;i<=MaxZinsample;i++)if(PresentElems[i])(*CalcFlags)[i].atnum=i;
00719 
00720   do {
00721     fscanf(CalcFlagsFile,"%255s",dummy);
00722     if(feof(CalcFlagsFile)) {fprintf(stderr,"\nERROR: 'DATA' not found in '%s'\n",CalcFlagsFileNm);exit(1);}
00723   } while (strcasecmp(dummy, "DATA"));
00724 
00725   /*Read Data blocks*/
00726   for(;!feof(CalcFlagsFile);){
00727     fscanf(CalcFlagsFile,"%255s",dummy);
00728 
00729     if( (!strcmp(dummy,"END_DATA") && AreasFormat==1) || (AreasFormat==2 && !strcmp(dummy,"CALIB" )) ) {
00730       break;
00731     }
00732     /*
00733     else if(!strcmp(dummy,"INCLUDE")){
00734       fscanf(CalcFlagsFileNm,"%3s",tempchem);
00735     }
00736     */
00737 
00738 
00739     //If the reading continues, "dummy" contains either a chem. symbol or a Z value
00740     if(AreasFormat==1){
00741       strncpy(tempchem,dummy,3);
00742       tempZ = symbol2Z(tempchem);
00743     }
00744     else if (AreasFormat==2){
00745       strncpy(tempchem,"-",3);
00746       tempZ = atoi(dummy);
00747     }
00748     else tempZ=0;
00749 
00750     if(tempZ<=MaxZinsample && PresentElems[tempZ]){
00751       nread++;
00752 
00753       pCFlags=&(*CalcFlags)[tempZ];
00754       pCFlags->atnum=tempZ;
00755 
00756       /*Read K-lines*/
00757       for(i=1;i<=3;i++) {
00758         fscanf(CalcFlagsFile, "%lg", &pCFlags->simareas.K_[i]);
00759         if(AreasFormat==2)fscanf(CalcFlagsFile, "%lg", &pCFlags->err.K_[i]);
00760       }
00761       /*Read L-lines*/
00762       for(i=1;i<=3;i++){
00763         for(j=1;j<=3;j++){
00764           fscanf(CalcFlagsFile, "%lg", &pCFlags->simareas.L_[i][j]);
00765           if(AreasFormat==2)fscanf(CalcFlagsFile, "%lg", &pCFlags->err.L_[i][j]);
00766         }
00767       }
00768       /*read M-lines*/
00769       for(i=1;i<=3;i++) {
00770         fscanf(CalcFlagsFile, "%lg", &pCFlags->simareas.M_[i]);
00771         if(AreasFormat==2)fscanf(CalcFlagsFile, "%lg", &pCFlags->err.M_[i]);
00772       }
00773       #if CPIXEVERBOSITY > 0
00774       printf("\n CalcFlags for Z=%2d (%2s) read", pCFlags->atnum,tempchem);
00775       #endif
00776       #if CPIXEVERBOSITY > 0
00777       printf("\n");
00778       fprintCALIBYLD(stdout,&pCFlags->simareas);
00779       #endif
00780     }
00781     else {
00782       for(i=0;i<15;i++)fscanf(CalcFlagsFile, "%lg",&trash);//just discard the 3+9+3 following numbers
00783       if(AreasFormat==2)for(i=0;i<15;i++)fscanf(CalcFlagsFile, "%lg",&trash); //plus 15 more if err are present
00784       #if CPIXEVERBOSITY > 0
00785       printf("\n Warning: Element '%s' ignored (not present in sample).",tempchem);
00786       #endif
00787     }
00788   }
00789   fclose(CalcFlagsFile);
00790   //Do some checks on the read data
00791   if(AreasFormat==2 && strcmp(dummy,"CALIB"))
00792     {fprintf(stderr,"\nERROR: Bad DT format in '%s'\n",CalcFlagsFileNm);exit(1);}
00793   if(AreasFormat==1 && strcmp(dummy,"END_DATA"))
00794     {fprintf(stderr,"\nERROR: 'END_DATA' not found in '%s'\n",CalcFlagsFileNm);exit(1);}
00795   if(nread==0){fprintf(stderr,"\nERROR: '%s' contained no valid data\n",CalcFlagsFileNm);exit(1);}
00796 
00797   return(0);
00798 }
00799 
00800 
00843 int readEff(const char *CalibFileNm, const int *PresentElems, int MaxZinsample, CalibYld **EffArray)
00844 {
00845   FILE *CalibFile;
00846   char dummy[LONGSTRINGLENGTH];
00847   int maxZ;
00848   int i,tempZ,result,version;
00849   ChemSymb tempchem;
00850   double trash;
00851 
00852   CalibFile = fopen(CalibFileNm, "r");
00853   if (CalibFile == NULL)
00854     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",CalibFileNm);exit(1);}
00855 
00856   /*Check file version*/
00857   do {
00858     fscanf(CalibFile,"%255s",dummy);
00859     if(feof(CalibFile)) {fprintf(stderr,"\nERROR: 'EFFIFILEVERSION' not found in '%s'\n",CalibFileNm);exit(1);}
00860   } while (strcasecmp(dummy, "EFFIFILEVERSION"));
00861 
00862   fscanf(CalibFile, "%d", &version);
00863   if(version!=EFFIFILEVERSION1){fprintf(stderr,"\nERROR: Calib. file '%s' version=%d!=%d\n",CalibFileNm,version,EFFIFILEVERSION1);exit(1);}
00864 
00865   /*Read Max Z*/
00866   do {
00867     fscanf(CalibFile,"%255s",dummy);
00868     if(feof(CalibFile)) {fprintf(stderr,"\nERROR: 'MAXZ' not found in '%s'\n",CalibFileNm);exit(1);}
00869   } while (strcasecmp(dummy, "MAXZ"));
00870 
00871   fscanf(CalibFile, "%d", &maxZ);
00872   if(MaxZinsample>maxZ){fprintf(stderr,"\nERROR: Calib. file '%s' maxZ=%d<%d\n",CalibFileNm,maxZ,MaxZinsample);exit(1);}
00873 
00874   /*Initialize EffArray */
00875   *EffArray=(CalibYld*)calloc(MaxZinsample+1,sizeof(CalibYld));
00876   if (*EffArray==NULL){fprintf(stderr,"\n Error allocating memory (EffArray)\n");exit(1);}
00877 
00878   do {
00879     fscanf(CalibFile,"%255s",dummy);
00880     if(feof(CalibFile)) {fprintf(stderr,"\nERROR: 'DATA' not found in '%s'\n",CalibFileNm);exit(1);}
00881   } while (strcasecmp(dummy, "DATA"));
00882 
00883   /*Read Data blocks*/
00884   for(result=0,tempZ=0;!feof(CalibFile) && tempZ!=MaxZinsample;){
00885     fscanf(CalibFile, "%d", &tempZ);
00886     if(tempZ<1 || tempZ>MaxZinsample){
00887       fprintf(stderr,"\nERROR: Bad format in Calib. file '%s' (Z=%d)\n",CalibFileNm,tempZ);
00888       exit(1);
00889     }
00890     fscanf(CalibFile,"%3s",tempchem);
00891     if(tempZ != symbol2Z(tempchem)){
00892       fprintf(stderr,"\nERROR: Bad format in Calib. file '%s' (Z=%d)\n",CalibFileNm,tempZ);
00893       exit(1);
00894     }
00895     if(PresentElems[tempZ]){
00896       result++;
00897 
00898       fscanCALIBYLD(CalibFile,&(*EffArray)[tempZ]); //Detector efficiency
00899 
00900       #if CPIXEVERBOSITY > 0
00901       printf("\n Efficiency for Z=%2d (%2s) read", tempZ,tempchem);
00902       #endif
00903       #if CPIXEVERBOSITY > 1
00904       printf("\n");
00905       fprintCALIBYLD(stdout,&(*EffArray)[tempZ]);
00906       #endif
00907 
00908     }
00909     else for(i=0;i<15;i++)fscanf(CalibFile, "%lg",&trash);//just discard the 15 following numbers
00910   }
00911   fclose(CalibFile);
00912 
00913   return(result);
00914 }
00915 
00916 
00917 
00952 int readEff2(const char *CalibFileNm, const int *PresentElems, int MaxZinsample, const CalibYld *LinesEnerArray, CalibYld **EffArray)
00953 {
00954   FILE *CalibFile;
00955   char dummy[LONGSTRINGLENGTH];
00956   int i,jj,ll,tempZ,result,version,ndata;
00957   double tempEner,tempEff;
00958   double *tempEnerArray,*tempEffArray;
00959   const CalibYld *pLineEner;
00960   CalibYld *pEff;
00961 
00962   CalibFile = fopen(CalibFileNm, "r");
00963   if (CalibFile == NULL)
00964     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",CalibFileNm);exit(1);}
00965 
00966   /*Check file version*/
00967   do {
00968     fscanf(CalibFile,"%255s",dummy);
00969     if(feof(CalibFile)) {fprintf(stderr,"\nERROR: 'EFFIFILEVERSION' not found in '%s'\n",CalibFileNm);exit(1);}
00970   } while (strcasecmp(dummy, "EFFIFILEVERSION"));
00971 
00972   fscanf(CalibFile, "%d", &version);
00973   if(version!=EFFIFILEVERSION2){fprintf(stderr,"\nERROR: Calib. file '%s' version=%d!=%d\n",CalibFileNm,version,EFFIFILEVERSION2);exit(1);}
00974 
00975   /*Initialize EffArray */
00976   *EffArray=(CalibYld*)calloc(MaxZinsample+1,sizeof(CalibYld));
00977   if (*EffArray==NULL){fprintf(stderr,"\n Error allocating memory (EffArray)\n");exit(1);}
00978 
00979   do {
00980     fscanf(CalibFile,"%255s",dummy);
00981     if(feof(CalibFile)) {fprintf(stderr,"\nERROR: 'DATA' not found in '%s'\n",CalibFileNm);exit(1);}
00982   } while (strcasecmp(dummy, "DATA"));
00983 
00984   /*Check the length of the data (number of data points) and leave the file
00985    cursor at the same point for further reading*/
00986   for (ndata=-1;!feof(CalibFile);ndata++){
00987     fscanf(CalibFile,"%lf%lf",&tempEner,&tempEff);
00988   }
00989   fclose(CalibFile);
00990   CalibFile = fopen(CalibFileNm, "r");
00991   if (CalibFile == NULL)
00992      {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",CalibFileNm);exit(1);}
00993   do {
00994     fscanf(CalibFile,"%255s",dummy);
00995     if(feof(CalibFile)) {fprintf(stderr,"\nERROR: 'DATA' not found in '%s'\n",CalibFileNm);exit(1);}
00996   } while (strcasecmp(dummy, "DATA"));
00997 
00998   /*Initialize tempEnerArray and tempEeffArray*/
00999   tempEnerArray=(double*)calloc(ndata,sizeof(double));
01000   if (tempEnerArray==NULL){fprintf(stderr,"\n Error allocating memory (tempEnerArray)\n");exit(1);}
01001   tempEffArray=(double*)calloc(ndata,sizeof(double));
01002   if (tempEffArray==NULL){fprintf(stderr,"\n Error allocating memory (tempEffArray)\n");exit(1);}
01003 
01004   /*Load the efficiencies versus energy in memory*/
01005   for(i=0,tempEner=-1.;i<ndata;i++){
01006     fscanf(CalibFile,"%lf%lf",&tempEnerArray[i],&tempEffArray[i]);
01007     //printf("\nDEBUG: %d)  %lf\t%lf",i,tempEnerArray[i],tempEffArray[i]);
01008     if (tempEner>tempEnerArray[i] || tempEnerArray[i]<0 )
01009        {fprintf(stderr,"\nERROR: format not valid in '%s' (energies must be sorted and not negative).\n",CalibFileNm);exit(1);}
01010   }
01011 
01012   /*Fill the Effarray blocks by interpolating each line energy from the tempEffArray values*/
01013   for(result=0,tempZ=0; tempZ<=MaxZinsample;tempZ++){
01014     if(PresentElems[tempZ]){
01015       result++;
01016       pLineEner=&LinesEnerArray[tempZ];
01017       pEff=&(*EffArray)[tempZ];
01018 
01019       /*Fill K lines*/
01020       for (jj = 1; jj <= 3; jj++) pEff->K_[jj]=interpolate_efficiency(ndata,tempEnerArray,tempEffArray,pLineEner->K_[jj]);
01021 
01022       /*Fill M lines*/
01023       for (jj = 1; jj <= 3; jj++) pEff->M_[jj]=interpolate_efficiency(ndata,tempEnerArray,tempEffArray,pLineEner->M_[jj]);
01024 
01025       /*Fill L lines*/
01026       for (jj = 1; jj <= 3; jj++) for (ll = 1; ll <= 3; ll++)
01027         pEff->L_[jj][ll]=interpolate_efficiency(ndata,tempEnerArray,tempEffArray,pLineEner->L_[jj][ll]);
01028 
01029       #if CPIXEVERBOSITY > 0
01030       fprintf(stdout,"\n Efficiencies for Z=%2d read", tempZ);
01031       #endif
01032       #if CPIXEVERBOSITY > 1
01033       fprintf(stdout,"\n");
01034       fprintCALIBYLD(stdout,&(*EffArray)[tempZ]);
01035       #endif
01036 
01037     }
01038   }
01039   fclose(CalibFile);
01040   free(tempEnerArray);
01041   free(tempEffArray);
01042 
01043   return(result);
01044 }
01045 
01054 double interpolate_efficiency(int ndata, const double *Xarray, const double *Yarray, double X)
01055 {
01056   int i;
01057   double result;
01058 
01059   if(X<=0.) return 0.;
01060   if(X>Xarray[ndata-1]) {
01061     #if CPIXEVERBOSITY > 0
01062     printf("\nWARNING:Line energy (%g keV) exceded maximum energy in efficiency database (%g keV)", X,Xarray[ndata]);
01063     #endif
01064     return 0.;
01065   }
01066   /*finds the index of the energy inmediately superior*/
01067   for(i=0;Xarray[i]<=X && i<ndata;i++);
01068   /*returns the interpolated value*/
01069   result=(X-Xarray[i-1])*(Yarray[i]-Yarray[i-1])/(Xarray[i]-Xarray[i-1])+Yarray[i-1];
01070   //printf("\nDEBUG:--> EL=%lg =>i=%d   E=%lg - %lf   eff=%lg - %lg",X,i,Xarray[i-1],Xarray[i],Yarray[i-1],Yarray[i]);
01071   //printf("\nDEBUG:--> Interpol:%lg ",result);
01072   return result;
01073 }
01074 
01075 
01076 
01123 int readEff3(const char *CalibFileNm, const int *PresentElems, int MaxZinsample, const CalibYld *LinesEnerArray, CalibYld **EffArray)
01124 {
01125   FILE *CalibFile;
01126   char dummy[LONGSTRINGLENGTH],dummy2[LONGSTRINGLENGTH];
01127   int i,jj,ll,tempZ,result,version,ndata,singlelineflag,exceptionflag;
01128   double tempEner,tempEff;
01129   double *tempEnerArray,*tempEffArray;
01130   ChemSymb tempchem="";
01131   const CalibYld *pLineEner;
01132   CalibYld *pEff;
01133   double trash;
01134 
01135   CalibFile = fopen(CalibFileNm, "r");
01136   if (CalibFile == NULL)
01137     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",CalibFileNm);exit(1);}
01138 
01139   /*Check file version*/
01140   do {
01141     fscanf(CalibFile,"%255s",dummy);
01142     if(feof(CalibFile)) {fprintf(stderr,"\nERROR: 'EFFIFILEVERSION' not found in '%s'\n",CalibFileNm);exit(1);}
01143   } while (strcasecmp(dummy, "EFFIFILEVERSION"));
01144 
01145   fscanf(CalibFile, "%d", &version);
01146   if(version!=EFFIFILEVERSION3){fprintf(stderr,"\nERROR: Calib. file '%s' version=%d!=%d\n",CalibFileNm,version,EFFIFILEVERSION3);exit(1);}
01147 
01148   /*Initialize EffArray */
01149   *EffArray=(CalibYld*)calloc(MaxZinsample+1,sizeof(CalibYld));
01150   if (*EffArray==NULL){fprintf(stderr,"\n Error allocating memory (EffArray)\n");exit(1);}
01151 
01152   do {
01153     fscanf(CalibFile,"%255s",dummy);
01154     if(feof(CalibFile)) {fprintf(stderr,"\nERROR: 'DETECTORCURVE' not found in '%s'\n",CalibFileNm);exit(1);}
01155   } while (strcasecmp(dummy, "DETECTORCURVE"));
01156 
01157   /*Check the length of the data (number of data points) and leave the file
01158    cursor at the same point for further reading*/
01159   for (ndata=-1;!feof(CalibFile) && strcasecmp(dummy, "LINEEFFICIENCIES") ;ndata++){
01160     fscanf(CalibFile,"%255s%255s",dummy,dummy2);
01161     if(strcasecmp(dummy, "LINEEFFICIENCIES"))exceptionflag=1;
01162   }
01163   fclose(CalibFile);
01164   CalibFile = fopen(CalibFileNm, "r");
01165   if (CalibFile == NULL)
01166      {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",CalibFileNm);exit(1);}
01167   do {
01168     fscanf(CalibFile,"%255s",dummy);
01169     if(feof(CalibFile)) {fprintf(stderr,"\nERROR: 'DETECTORCURVE' not found in '%s'\n",CalibFileNm);exit(1);}
01170   } while (strcasecmp(dummy, "DETECTORCURVE"));
01171 
01172   //fprintf(stderr,"\n\nDEBUG--->%d\n",ndata);getchar();
01173 
01174   /*Initialize tempEnerArray and tempEeffArray*/
01175   tempEnerArray=(double*)calloc(ndata,sizeof(double));
01176   if (tempEnerArray==NULL){fprintf(stderr,"\n Error allocating memory (tempEnerArray)\n");exit(1);}
01177   tempEffArray=(double*)calloc(ndata,sizeof(double));
01178   if (tempEffArray==NULL){fprintf(stderr,"\n Error allocating memory (tempEffArray)\n");exit(1);}
01179 
01180   /*Load the efficiencies versus energy in memory*/
01181   for(i=0,tempEner=-1.;i<ndata;i++){
01182     fscanf(CalibFile,"%lf%lf",&tempEnerArray[i],&tempEffArray[i]);
01183     //printf("\nDEBUG: %d)  %lf\t%lf",i,tempEnerArray[i],tempEffArray[i]);
01184     if (tempEner>tempEnerArray[i] || tempEnerArray[i]<0 )
01185        {fprintf(stderr,"\nERROR: format not valid in '%s' (energies must be sorted and not negative).\n",CalibFileNm);exit(1);}
01186   }
01187 
01188   /*Fill the Effarray blocks by interpolating each line energy from the tempEffArray values*/
01189   for(result=0,tempZ=0; tempZ<=MaxZinsample;tempZ++){
01190     if(PresentElems[tempZ]){
01191       result++;
01192       pLineEner=&LinesEnerArray[tempZ];
01193       pEff=&(*EffArray)[tempZ];
01194 
01195       /*Fill K lines*/
01196       for (jj = 1; jj <= 3; jj++) pEff->K_[jj]=interpolate_efficiency(ndata,tempEnerArray,tempEffArray,pLineEner->K_[jj]);
01197 
01198       /*Fill M lines*/
01199       for (jj = 1; jj <= 3; jj++) pEff->M_[jj]=interpolate_efficiency(ndata,tempEnerArray,tempEffArray,pLineEner->M_[jj]);
01200 
01201       /*Fill L lines*/
01202       for (jj = 1; jj <= 3; jj++) for (ll = 1; ll <= 3; ll++)
01203         pEff->L_[jj][ll]=interpolate_efficiency(ndata,tempEnerArray,tempEffArray,pLineEner->L_[jj][ll]);
01204 
01205       #if CPIXEVERBOSITY > 0
01206       fprintf(stdout,"\n Efficiencies for %2s extracted from detector curve", ChemicalSymbol[tempZ]);
01207       #endif
01208       #if CPIXEVERBOSITY > 1
01209       fprintf(stdout,"\n");
01210       fprintCALIBYLD(stdout,&(*EffArray)[tempZ]);
01211       #endif
01212 
01213     }
01214   }
01215 
01216   /*Now overwrite with exceptions if present*/
01217   if(exceptionflag){
01218     fscanf(CalibFile,"%255s",dummy); //this just reads and discards the LINEFFICIENCIES keyword
01219     for(result=0,tempZ=0;!feof(CalibFile); ){
01220       fscanf(CalibFile, "%d", &tempZ);
01221       fscanf(CalibFile,"%3s",tempchem);
01222       if(tempZ==0){ //This means that a single line will be modified (instead of a block)
01223         tempZ=symbol2Z(tempchem);
01224         singlelineflag=1;
01225         //printf("\nDEBUG: :::::::::: '%s'----'%d'\n",tempchem,tempZ);
01226       }
01227 
01228       if(tempZ != symbol2Z(tempchem)){
01229         fprintf(stderr,"\nERROR: Bad format in Calib. file '%s' (Z=%d)\n",CalibFileNm,tempZ);exit(1);
01230         exit(1);
01231       }
01232       if(singlelineflag){  /*Read Single line*/
01233         fscanf(CalibFile,"%255s%lf",dummy,&tempEff);
01234         if( tempZ<=MaxZinsample && PresentElems[tempZ]){  //This relies in the fact that the left check is done BEFORE the right one
01235           pEff=&(*EffArray)[tempZ];
01236           if      (!strcasecmp(dummy, "Ka12" ))pEff->K_[1]=tempEff;
01237           else if (!strcasecmp(dummy, "Kb1"))pEff->K_[2]=tempEff;
01238           else if (!strcasecmp(dummy, "Kb2"))pEff->K_[3]=tempEff;
01239 
01240           else if (!strcasecmp(dummy, "La12" ))pEff->L_[1][1]=tempEff;
01241           else if (!strcasecmp(dummy, "Lb2"))pEff->L_[1][2]=tempEff;
01242           else if (!strcasecmp(dummy, "Ll" ))pEff->L_[1][3]=tempEff;
01243 
01244           else if (!strcasecmp(dummy, "Lb1"))pEff->L_[2][1]=tempEff;
01245           else if (!strcasecmp(dummy, "Lg1"))pEff->L_[2][2]=tempEff;
01246           else if (!strcasecmp(dummy, "Le" ))pEff->L_[2][3]=tempEff;
01247 
01248           else if (!strcasecmp(dummy, "Lb3"))pEff->L_[3][1]=tempEff;
01249           else if (!strcasecmp(dummy, "Lb4"))pEff->L_[3][2]=tempEff;
01250           else if (!strcasecmp(dummy, "Lg3"))pEff->L_[3][3]=tempEff;
01251 
01252           else if (!strcasecmp(dummy, "Ma" ))pEff->M_[1]=tempEff;
01253           else if (!strcasecmp(dummy, "Mb" ))pEff->M_[2]=tempEff;
01254           else if (!strcasecmp(dummy, "Mg" ))pEff->M_[3]=tempEff;
01255           else {
01256             fprintf(stderr,"\nERROR: Bad format in Calib. file '%s'. Unrecognized line name '%s'\n",CalibFileNm,dummy);
01257             exit(1);
01258           }
01259           #if CPIXEVERBOSITY > 0
01260           printf("\n Exception Efficiency for %2s (Line %s) read", tempchem,dummy);
01261           #endif
01262           #if CPIXEVERBOSITY > 1
01263           printf("\n");
01264           fprintCALIBYLD(stdout,&(*EffArray)[tempZ]);
01265           #endif
01266         }
01267         else{
01268           #if CPIXEVERBOSITY > 0
01269           printf("\n Warning: Exception for %2s ignored (not present in sample).",tempchem);
01270           #endif
01271         }
01272       }
01273       else{  /*Read Data blocks*/
01274         if(tempZ<=MaxZinsample && PresentElems[tempZ]){
01275           result++;
01276           fscanCALIBYLD(CalibFile,&(*EffArray)[tempZ]); //Detector efficiency
01277 
01278           #if CPIXEVERBOSITY > 0
01279           printf("\n Exception Efficiency Block for Z=%2d (%2s) read", tempZ,tempchem);
01280           #endif
01281           #if CPIXEVERBOSITY > 1
01282           printf("\n");
01283           fprintCALIBYLD(stdout,&(*EffArray)[tempZ]);
01284           #endif
01285         }
01286         else for(i=0;i<15;i++)fscanf(CalibFile, "%lg",&trash);//just discard the 15 following numbers
01287       }
01288     }
01289   }
01290   fclose(CalibFile);
01291   free(tempEnerArray);
01292   free(tempEffArray);
01293 
01294   return(result);
01295 }
01296 
01339 int readLinesEner(const char *LinesEnerFileNm, const int *PresentElems, int MaxZinsample, CalibYld **LinesEnerArray)
01340 {
01341   FILE *LinesEnerFile;
01342   char dummy[LONGSTRINGLENGTH];
01343   int maxZ;
01344   int i,tempZ,result;
01345   ChemSymb tempchem;
01346   double trash;
01347 
01348   LinesEnerFile = fopen(LinesEnerFileNm, "r");
01349   if (LinesEnerFile == NULL)
01350     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",LinesEnerFileNm);exit(1);}
01351 
01352 
01353   /*Read Max Z*/
01354   do {
01355     fscanf(LinesEnerFile,"%255s",dummy);
01356     if(feof(LinesEnerFile)) {fprintf(stderr,"\nERROR: 'MAXZ' not found in '%s'\n",LinesEnerFileNm);exit(1);}
01357   } while (strcasecmp(dummy, "MAXZ"));
01358 
01359   fscanf(LinesEnerFile, "%d", &maxZ);
01360   if(MaxZinsample>maxZ){fprintf(stderr,"\nERROR: while reading file '%s' maxZ=%d<%d\n",LinesEnerFileNm,maxZ,MaxZinsample);exit(1);}
01361 
01362   /*Initialize LinesEnerArray */
01363   *LinesEnerArray=(CalibYld*)calloc(MaxZinsample+1,sizeof(CalibYld));
01364   if (*LinesEnerArray==NULL){fprintf(stderr,"\n Error allocating memory (LinesEnerArray)\n");exit(1);}
01365 
01366   do {
01367     fscanf(LinesEnerFile,"%255s",dummy);
01368     if(feof(LinesEnerFile)) {fprintf(stderr,"\nERROR: 'DATA' not found in '%s'\n",LinesEnerFileNm);exit(1);}
01369   } while (strcasecmp(dummy, "DATA"));
01370 
01371   /*Read Data blocks*/
01372   for(result=0,tempZ=0;!feof(LinesEnerFile) && tempZ!=MaxZinsample;){
01373     fscanf(LinesEnerFile, "%d", &tempZ);
01374     if(tempZ<1 || tempZ>MaxZinsample){
01375       fprintf(stderr,"\nERROR: Bad format in LinesEner file '%s' (Z=%d)\n",LinesEnerFileNm,tempZ);
01376       exit(1);
01377     }
01378     fscanf(LinesEnerFile,"%3s",tempchem);
01379     if(tempZ != symbol2Z(tempchem)){
01380       fprintf(stderr,"\nERROR: Bad format in LinesEner file '%s' (Z=%d)\n",LinesEnerFileNm,tempZ);
01381       exit(1);
01382     }
01383     if(PresentElems[tempZ]){
01384       result++;
01385 
01386       fscanCALIBYLD(LinesEnerFile,&(*LinesEnerArray)[tempZ]);    //emission energies
01387       //fscanCALIBYLD(LinesEnerFile,&pEff->raweffi); //Detector efficiency
01388 
01389       #if CPIXEVERBOSITY > 0
01390       printf("\n Lines Energy for Z=%2d (%2s) read", tempZ,tempchem);
01391       #endif
01392       #if CPIXEVERBOSITY > 1
01393       printf("\n");
01394       fprintCALIBYLD(stdout,&(*LinesEnerArray)[tempZ]);
01395       #endif
01396 
01397     }
01398     else for(i=0;i<15;i++)fscanf(LinesEnerFile, "%lg",&trash);//just discard the 15 following numbers
01399   }
01400   fclose(LinesEnerFile);
01401 
01402   return(result);
01403 }
01404 
01405 
01451 int readXYld(const char *XYldFileNm, const int *PresentElems, const CPIXERESULTS *CalcFlags, int MaxZinsample, double *CalEner, XrayYield **XYldArray)
01452 {
01453   FILE *XYldFile;
01454   char dummy[LONGSTRINGLENGTH];
01455   int maxZ;
01456   XrayYield *pXYld;
01457   int i,j,tempZ,result,iel;
01458   ChemSymb tempchem;
01459   double natmass,ug2at, trash;
01460   const CalibYld *pFlag;
01461   int atomicunits=0;
01462 
01463   XYldFile = fopen(XYldFileNm, "r");
01464   if (XYldFile == NULL)
01465     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",XYldFileNm);exit(1);}
01466 
01467   do {
01468     fscanf(XYldFile,"%255s",dummy);
01469     if(feof(XYldFile)) {fprintf(stderr,"\nERROR: 'CALENER' not found in '%s'\n",XYldFileNm);exit(1);}
01470   } while (strcasecmp(dummy, "CALENER"));
01471 
01472   fscanf(XYldFile, "%lf", CalEner);
01473 
01474   do {
01475     fscanf(XYldFile,"%255s",dummy);
01476     if(feof(XYldFile)) {fprintf(stderr,"\nERROR: 'MAXZ' not found in '%s'\n",XYldFileNm);exit(1);}
01477   } while (strcasecmp(dummy, "MAXZ"));
01478 
01479   fscanf(XYldFile, "%d", &maxZ);
01480   if(MaxZinsample>maxZ){fprintf(stderr,"\nERROR: Calib. file '%s' maxZ=%d<%d\n",XYldFileNm,maxZ,MaxZinsample);exit(1);}
01481 
01482   /*Initialize XYldArray */
01483   *XYldArray=(XrayYield*)calloc(MaxZinsample+1,sizeof(XrayYield));
01484   if (*XYldArray==NULL){fprintf(stderr,"\n Error allocating memory (XYldArray)\n");exit(1);}
01485 
01486   do {
01487     fscanf(XYldFile,"%255s",dummy);
01488     if(feof(XYldFile)) {fprintf(stderr,"\nERROR: 'UNITS' not found in '%s'\n",XYldFileNm);exit(1);}
01489   } while (strcasecmp(dummy, "UNITS"));
01490 
01491   fscanf(XYldFile, "%255s",dummy);
01492   if(!strcasecmp(dummy, "atom"))atomicunits=1;
01493   else if(!strcasecmp(dummy, "mass"))atomicunits=0;
01494   else {fprintf(stderr,"\nERROR: unknown UNITS ('%s') in '%s'. Valid values are 'atom' or 'mass'\n",dummy,XYldFileNm);exit(1);}
01495 
01496   do {
01497     fscanf(XYldFile,"%255s",dummy);
01498     if(feof(XYldFile)) {fprintf(stderr,"\nERROR: 'DATA' not found in '%s'\n",XYldFileNm);exit(1);}
01499   } while (strcasecmp(dummy, "DATA"));
01500 
01501   /*Read Data blocks*/
01502   for(result=0,tempZ=0;!feof(XYldFile) && tempZ!=MaxZinsample;){
01503     fscanf(XYldFile, "%d", &tempZ);
01504     if(tempZ<1 || tempZ>MaxZinsample || (*XYldArray)[tempZ].atnum != 0){
01505       fprintf(stderr,"\nERROR: Bad format in Calib. file '%s' (Z=%d)\n",XYldFileNm,tempZ);
01506       exit(1);
01507     }
01508     fscanf(XYldFile,"%3s",tempchem);
01509     if(tempZ != symbol2Z(tempchem)){
01510       fprintf(stderr,"\nERROR: Bad format in Calib. file '%s' (Z=%d)\n",XYldFileNm,tempZ);
01511       exit(1);
01512     }
01513     if(PresentElems[tempZ]){
01514       result++;
01515       pXYld=&(*XYldArray)[tempZ];
01516       pXYld->atnum=tempZ;
01517       strcpy(pXYld->symb, tempchem);
01518       for(iel=0;CalcFlags[iel].atnum!=tempZ;iel++){} //findout the iel corresponding to tempZ
01519 
01520       pFlag=&CalcFlags[iel].simareas;
01521 
01522       if(!atomicunits){
01523         Z2mass(tempZ, &natmass,'n');
01524         ug2at=natmass/602.2141; // (Pm [g/mol] *1e6 [ug/g] / (Navo [at/mol])) * 1e15
01525                                 // ==> ug2at is in [ug/1e15at]
01526       }
01527       else ug2at=1; //If Units are already atomic, the conversion shouldn't be done
01528 
01529       /*Read K-lines*/
01530       for(i=1;i<=3;i++) fscanf(XYldFile, "%lg", &pXYld->ener.K_[i]);
01531       for(i=1;i<=3;i++) {
01532         fscanf(XYldFile, "%lg", &pXYld->XYld.K_[i]);
01533         pXYld->XYld.K_[i]*=ug2at;  // ug2at is in [ug/1e15at]
01534         //If the line is not to be used, put it at 0
01535         if(!(int)pFlag->K_[i]){ pXYld->XYld.K_[i]=0. ; pXYld->ener.K_[i]=0.;}
01536       }
01537       /*Read L-lines*/
01538       for(i=1;i<=3;i++){
01539         for(j=1;j<=3;j++){
01540           fscanf(XYldFile, "%lg", &pXYld->ener.L_[i][j]);
01541         }
01542         for(j=1;j<=3;j++){
01543           fscanf(XYldFile, "%lg", &pXYld->XYld.L_[i][j]);
01544           pXYld->XYld.L_[i][j]*=ug2at;
01545           if(!(int)pFlag->L_[i][j]){ pXYld->XYld.L_[i][j]=0. ; pXYld->ener.L_[i][j]=0.;}
01546         }
01547       }
01548 
01549       /*read M-lines*/
01550       for(i=1;i<=3;i++) fscanf(XYldFile, "%lg", &pXYld->ener.M_[i]);
01551       for(i=1;i<=3;i++) {
01552         fscanf(XYldFile, "%lg", &pXYld->XYld.M_[i]);
01553         pXYld->XYld.M_[i]*=ug2at;
01554         if(!(int)pFlag->M_[i]){ pXYld->XYld.M_[i]=0. ; pXYld->ener.M_[i]=0.;}
01555       }
01556       #if CPIXEVERBOSITY > 0
01557       printf("\n XyldArray[%2d] (%2s) read", pXYld->atnum,tempchem);
01558       #endif
01559     }
01560     else for(i=0;i<30;i++)fscanf(XYldFile, "%lg",&trash);//just discard the 3*2+9*2+3*2 following numbers
01561   }
01562   fclose(XYldFile);
01563 
01564   return(result);
01565 }
01566 
01567 
01568 
01569 
01611 int readFCK(char *FCKCoefFileNm, int MaxZinsample, FluorCKCoef **FCKCoefArray)
01612 {
01613   FILE *FCKCoefFile;
01614   char dummy[LONGSTRINGLENGTH];
01615   int maxZ;
01616   FluorCKCoef *pFCKCoef;
01617   int i,tempZ;
01618   ChemSymb tempchem;
01619 
01620   maxZ=0;
01621   FCKCoefFile= fopen(FCKCoefFileNm, "r");
01622   if (FCKCoefFile == NULL)
01623     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",FCKCoefFileNm);exit(1);}
01624 
01625   do {
01626   fscanf(FCKCoefFile,"%255s",dummy);
01627   if(feof(FCKCoefFile)) {fprintf(stderr,"\nERROR: 'MAXZ' not found in '%s'\n",FCKCoefFileNm);exit(1);}
01628   } while (strcasecmp(dummy, "MAXZ"));
01629 
01630   fscanf(FCKCoefFile, "%d", &maxZ);
01631   if(MaxZinsample>maxZ){fprintf(stderr,"\nERROR: FCK file '%s' maxZ=%d<%d\n",FCKCoefFileNm,maxZ,MaxZinsample);exit(1);}
01632 
01633   /*Initialize FCKCoefArray*/
01634   *FCKCoefArray=(FluorCKCoef*)calloc(MaxZinsample+1,sizeof(FluorCKCoef));
01635   if (*FCKCoefArray==NULL){fprintf(stderr,"\n Error allocating memory (FCKCoefArray)\n");exit(1);}
01636 
01637   do {
01638   fscanf(FCKCoefFile,"%255s",dummy);
01639   if(feof(FCKCoefFile)) {fprintf(stderr,"\nERROR: 'DATA' not found in '%s'\n",FCKCoefFileNm);exit(1);}
01640   } while (strcasecmp(dummy, "DATA"));
01641 
01642   /*Read Data blocks*/
01643   for(tempZ=0;!feof(FCKCoefFile) && tempZ!=MaxZinsample;){
01644     fscanf(FCKCoefFile, "%d", &tempZ);
01645     if(tempZ<1 || tempZ>MaxZinsample || (*FCKCoefArray)[tempZ].atnum != 0){
01646       fprintf(stderr,"\nERROR: Bad format in FCKCoef file '%s' (Z=%d)\n",FCKCoefFileNm,tempZ);
01647       exit(1);
01648     }
01649     fscanf(FCKCoefFile,"%3s",tempchem);
01650     if(tempZ != symbol2Z(tempchem)){
01651       fprintf(stderr,"\nERROR: Bad format in FCKCoef file '%s' (Z=%d)\n",FCKCoefFileNm,tempZ);
01652       exit(1);
01653     }
01654     pFCKCoef=&(*FCKCoefArray)[tempZ];
01655     pFCKCoef->atnum=tempZ;
01656 
01657     /*Read Fluorescence coeffs*/
01658     for (i = 1; i <= 9; i++) fscanf(FCKCoefFile, "%lg", &pFCKCoef->w[i]);
01659 
01660     /*Read f12,f13,f23 coeffs (Coster-Kronig)*/
01661     fscanf(FCKCoefFile, "%lg%lg%lg", &pFCKCoef->ck[0], &pFCKCoef->ck[1], &pFCKCoef->ck[2]);
01662 
01663     /*Read Line fractions*/
01664     fscanf(FCKCoefFile, "%lg%lg%lg", &pFCKCoef->k.K_[1], &pFCKCoef->k.K_[2], &pFCKCoef->k.K_[3]);
01665     for (i = 1; i <= 3; i++) fscanf(FCKCoefFile, "%lg%lg%lg", &pFCKCoef->k.L_[i][1], &pFCKCoef->k.L_[i][2], &pFCKCoef->k.L_[i][3]);
01666     fscanf(FCKCoefFile, "%lg%lg%lg", &pFCKCoef->k.M_[1], &pFCKCoef->k.M_[2], &pFCKCoef->k.M_[3]);
01667 
01668 //     printf("\n DEBUG: FCKCoef[%2d] (%2s) read", pFCKCoef->atnum,tempchem);
01669   }
01670   fclose(FCKCoefFile);
01671   return(0);
01672 }
01673 
01674 
01713 int readAbsCoef(const char *TotAbsCoefFileNm, int MaxZinsample, AbsCoef **TotAbsCoefArray)
01714 {
01715   FILE *TotAbsCoefFile;
01716   char dummy[LONGSTRINGLENGTH];
01717   int maxZ,Nread;
01718   AbsCoef *pTotAbsCoef;
01719   int i,tempZ;
01720   ChemSymb tempchem;
01721   double natmass;
01722   double mg2at; //conversion factor from cm2/mg to cm2/(1e15at) , which depends on the mass.
01723 
01724   TotAbsCoefFile= fopen(TotAbsCoefFileNm, "r");
01725   if (TotAbsCoefFile == NULL)
01726     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",TotAbsCoefFileNm);exit(1);}
01727 
01728   do {
01729   fscanf(TotAbsCoefFile,"%255s",dummy);
01730   if(feof(TotAbsCoefFile)) {fprintf(stderr,"\nERROR: 'MAXZ' not found in '%s'\n",TotAbsCoefFileNm);exit(1);}
01731   } while (strcasecmp(dummy, "MAXZ"));
01732 
01733   fscanf(TotAbsCoefFile, "%d", &maxZ);
01734   if(MaxZinsample>maxZ){fprintf(stderr,"\nERROR: X-Absorption file '%s' maxZ=%d<%d\n",TotAbsCoefFileNm,maxZ,MaxZinsample);exit(1);}
01735 
01736   /*Initialize TotAbsCoefArray to hold the WHOLE table*/
01737   *TotAbsCoefArray=(AbsCoef*)calloc(maxZ+1,sizeof(AbsCoef));
01738   if (*TotAbsCoefArray==NULL){fprintf(stderr,"\n Error allocating memory (TotAbsCoefArray)\n");exit(1);}
01739 
01740   do {
01741   fscanf(TotAbsCoefFile,"%255s",dummy);
01742   if(feof(TotAbsCoefFile)) {fprintf(stderr,"\nERROR: 'DATA' not found in '%s'\n",TotAbsCoefFileNm);exit(1);}
01743   } while (strcasecmp(dummy, "DATA"));
01744 
01745   /*Read Data blocks*/
01746   for(Nread=0,tempZ=0;!feof(TotAbsCoefFile) && tempZ!=maxZ;Nread++){
01747     fscanf(TotAbsCoefFile, "%d", &tempZ);
01748     if(tempZ<1 || tempZ>maxZ || (*TotAbsCoefArray)[tempZ].atnum != 0){
01749       fprintf(stderr,"\nERROR: Bad format in X-Absorption file '%s' (Z=%d)\n",TotAbsCoefFileNm,tempZ);
01750       exit(1);
01751     }
01752     fscanf(TotAbsCoefFile,"%3s",tempchem);
01753     if(tempZ != symbol2Z(tempchem)){
01754       fprintf(stderr,"\nERROR: Bad format in X-Absorption file '%s' (Z=%d)\n",TotAbsCoefFileNm,tempZ);
01755       exit(1);
01756     }
01757     pTotAbsCoef=&(*TotAbsCoefArray)[tempZ];
01758     pTotAbsCoef->atnum=tempZ;
01759 
01760     Z2mass(tempZ, &natmass,'n');
01761     mg2at=natmass/602214.1; // (Pm [g/mol] *1e3 [mg/g] / (Navo [at/mol])) * 1e15
01762                             // ==> mg2at is in [mg/1e15at]
01763 
01764     for (i = 0; i < 23; i++){
01765       fscanf(TotAbsCoefFile, "%lg", &pTotAbsCoef->coefstd[i]);
01766       /*Transform: from cm2/mg to cm2/(1e15at)*/
01767       pTotAbsCoef->coefstd[i]*=mg2at;
01768     }
01769     for (i = 1; i <= 9; i++){
01770       fscanf(TotAbsCoefFile, "%lg%lg%lg", &pTotAbsCoef->enr[i], &pTotAbsCoef->coefenr[i-1][0],&pTotAbsCoef->coefenr[i-1][1]);
01771       /*Transform: from cm2/mg to cm2/(1e15at)*/
01772       pTotAbsCoef->coefenr[i-1][0]*=mg2at;
01773       pTotAbsCoef->coefenr[i-1][1]*=mg2at;
01774     }
01775     #if CPIXEVERBOSITY > 1
01776     printf("\n TotAbsCoef[%2d] (%2s) read", pTotAbsCoef->atnum,tempchem);
01777     #endif
01778   }
01779   fclose(TotAbsCoefFile);
01780   #if CPIXEVERBOSITY > 0
01781   printf("\n Absorption Coefs. for %d elements read", Nread);
01782   #endif
01783 
01784   return(0);
01785 }
01786 
01787 
01828 int readAbsCoef_OLD(char *TotAbsCoefFileNm, int MaxZinsample, const int *PresentElems, const FILTER *Filter, AbsCoef **TotAbsCoefArray)
01829 {
01830   FILE *TotAbsCoefFile;
01831   char dummy[LONGSTRINGLENGTH];
01832   int maxZ;
01833   AbsCoef *pTotAbsCoef;
01834   int i,tempZ;
01835   ChemSymb tempchem;
01836   double trash, natmass;
01837   double mg2at; //conversion factor from cm2/mg to cm2/(1e15at) , which depends on the mass.
01838 
01839   TotAbsCoefFile= fopen(TotAbsCoefFileNm, "r");
01840   if (TotAbsCoefFile == NULL)
01841     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",TotAbsCoefFileNm);exit(1);}
01842 
01843   do {
01844   fscanf(TotAbsCoefFile,"%255s",dummy);
01845   if(feof(TotAbsCoefFile)) {fprintf(stderr,"\nERROR: 'MAXZ' not found in '%s'\n",TotAbsCoefFileNm);exit(1);}
01846   } while (strcasecmp(dummy, "MAXZ"));
01847 
01848   fscanf(TotAbsCoefFile, "%d", &maxZ);
01849   if(MaxZinsample>maxZ){fprintf(stderr,"\nERROR: X-Absorption file '%s' maxZ=%d<%d\n",TotAbsCoefFileNm,maxZ,MaxZinsample);exit(1);}
01850 
01851   /*Initialize TotAbsCoefArray*/
01852   *TotAbsCoefArray=(AbsCoef*)calloc(MaxZinsample+1,sizeof(AbsCoef));
01853   if (*TotAbsCoefArray==NULL){fprintf(stderr,"\n Error allocating memory (TotAbsCoefArray)\n");exit(1);}
01854 
01855   do {
01856   fscanf(TotAbsCoefFile,"%255s",dummy);
01857   if(feof(TotAbsCoefFile)) {fprintf(stderr,"\nERROR: 'DATA' not found in '%s'\n",TotAbsCoefFileNm);exit(1);}
01858   } while (strcasecmp(dummy, "DATA"));
01859 
01860   /*Read Data blocks*/
01861   for(tempZ=0;!feof(TotAbsCoefFile) && tempZ!=MaxZinsample;){
01862     fscanf(TotAbsCoefFile, "%d", &tempZ);
01863     if(tempZ<1 || tempZ>MaxZinsample || (*TotAbsCoefArray)[tempZ].atnum != 0){
01864       fprintf(stderr,"\nERROR: Bad format in X-Absorption file '%s' (Z=%d)\n",TotAbsCoefFileNm,tempZ);
01865       exit(1);
01866     }
01867     fscanf(TotAbsCoefFile,"%3s",tempchem);
01868     if(tempZ != symbol2Z(tempchem)){
01869       fprintf(stderr,"\nERROR: Bad format in X-Absorption file '%s' (Z=%d)\n",TotAbsCoefFileNm,tempZ);
01870       exit(1);
01871     }
01872     if(PresentElems[tempZ] || ( tempZ<=Filter->MaxZ && Filter->FilterElems[tempZ] ) ){
01873       pTotAbsCoef=&(*TotAbsCoefArray)[tempZ];
01874       pTotAbsCoef->atnum=tempZ;
01875 
01876       Z2mass(tempZ, &natmass,'n');
01877       mg2at=natmass/602214.1; // (Pm [g/mol] *1e3 [mg/g] / (Navo [at/mol])) * 1e15
01878                               // ==> mg2at is in [mg/1e15at]
01879 
01880       for (i = 0; i < 23; i++){
01881         fscanf(TotAbsCoefFile, "%lg", &pTotAbsCoef->coefstd[i]);
01882         /*Transform: from cm2/mg to cm2/(1e15at)*/
01883         pTotAbsCoef->coefstd[i]*=mg2at;
01884       }
01885       for (i = 1; i <= 9; i++){
01886         fscanf(TotAbsCoefFile, "%lg%lg%lg", &pTotAbsCoef->enr[i], &pTotAbsCoef->coefenr[i-1][0],&pTotAbsCoef->coefenr[i-1][1]);
01887         /*Transform: from cm2/mg to cm2/(1e15at)*/
01888          pTotAbsCoef->coefenr[i-1][0]*=mg2at;
01889          pTotAbsCoef->coefenr[i-1][1]*=mg2at;
01890       }
01891       #if CPIXEVERBOSITY > 0
01892       printf("\n TotAbsCoef[%2d] (%2s) read", pTotAbsCoef->atnum,tempchem);
01893       #endif
01894     }
01895     else for (i = 0; i < 50; i++) fscanf(TotAbsCoefFile, "%lg", &trash); //just discard the 23+9*3 following numbers
01896   }
01897   fclose(TotAbsCoefFile);
01898   return(0);
01899 }
01900 
01901 
01902 
01921 int createSPTs(const char *path, const EXP_PARAM *pexp, int MaxZinsample, const int *PresentElems, double step, SPT **SPTArray)
01922 {
01923   int Z,j;
01924   SPT *pSPT;
01925   double E;
01926   double *nucSP;
01927   char afilename[FILENMLENGTH], bfilename[FILENMLENGTH];
01929   snprintf(afilename,FILENMLENGTH,"%sSCOEF.95A",path);
01930   snprintf(bfilename,FILENMLENGTH,"%sSCOEF.95B",path);
01931   readstopcoef(afilename, bfilename);
01932 
01933   /*Initialize SPTables*/
01934   /*Calloc is used, so all the non-explicitely initialized, remain 0/NULL */
01935   *SPTArray=(SPT*)calloc(MaxZinsample+1,sizeof(SPT));
01936   if (*SPTArray==NULL){fprintf(stderr,"\n Error allocating memory (SPTArray)\n");exit(1);}
01937 
01938   for(Z=1; Z<=MaxZinsample ;Z++){
01939     if(PresentElems[Z]){
01940       pSPT=&(*SPTArray)[Z];
01941 
01942       pSPT->Emax=1.1*pexp->BeamEner;
01943       pSPT->Estep=step;
01944       pSPT->logmode=0;  
01945       pSPT->nrows=1+(int)ceil(pSPT->Emax/pSPT->Estep);
01946 
01947       /*Initialize the arrays*/
01948       pSPT->E=(double*)malloc(pSPT->nrows*sizeof(double));
01949       if (pSPT->E==NULL){fprintf(stderr,"\n Error allocating memory (SPTArray[%d].E)\n",Z);exit(1);}
01950       pSPT->S=(double*)malloc(pSPT->nrows*sizeof(double));
01951       if (pSPT->S==NULL){fprintf(stderr,"\n Error allocating memory (SPTArray[%d].S)\n",Z);exit(1);}
01952       pSPT->dSdE=(double*)malloc(pSPT->nrows*sizeof(double));
01953       if (pSPT->dSdE==NULL){fprintf(stderr,"\n Error allocating memory (SPTArray[%d].dSdE)\n",Z);exit(1);}
01954 
01955       nucSP=(double*)malloc(pSPT->nrows*sizeof(double));
01956       if (nucSP==NULL){fprintf(stderr,"\n Error allocating memory (nucSP)\n");exit(1);}
01957 
01958       for(j=0 ,E=0; j< pSPT->nrows ; j++, E+=step)pSPT->E[j]=E;
01959 
01960       stop96d(pexp->ion.Z, Z, pexp->ion.IM,  pSPT->E, pSPT->nrows, pSPT->S);
01961       nuclearstopping_ZBL(pexp->ion.Z, Z, pexp->ion.IM, (double)(-1.), pSPT->E, pSPT->nrows, nucSP);
01962 
01963       for(pSPT->Smax=0., j=0 ; j< pSPT->nrows ; j++){
01964         pSPT->S[j] += nucSP[j];
01965         pSPT->S[j] *=0.001; //Return stopping in keV/(1e15at/cm2)
01966         if(pSPT->Smax < pSPT->S[j]) pSPT->Smax = pSPT->S[j];  //obtain the maximum of S
01967       }
01968       for(j=0 ; j< pSPT->nrows-1 ; j++){
01969       pSPT->dSdE[j]=(pSPT->S[j+1] - pSPT->S[j])/(pSPT->E[j+1] - pSPT->E[j]);
01970       }
01971       pSPT->dSdE[pSPT->nrows-1]=pSPT->dSdE[pSPT->nrows -2];
01972 
01973       free(nucSP);
01974       #if CPIXEVERBOSITY > 0
01975       printf("\n Created SP table for Z=%2d (%d rows)",Z,pSPT->nrows);
01976       #endif
01977     }
01978   }
01979 
01980   return(0);
01981 }
01982 
01983 
01992 double getSP(const COMPOUND *pcmp, const SPT *SPTArray, double E)
01993 {
01994   int i,j;
01995   double SP;
01996   const SPT *pspt;
01997 
01998   /*For each element in the compound, obtain the stopping power from its table and apply bragg rule*/
01999   for(SP=0, i=0 ; i< pcmp->nelem ; i++){
02000     pspt= &SPTArray[pcmp->elem[i].Z];
02001     j=(int)floor(E / pspt->Estep);  // j is the index in the table (index of nearest lower tabulated energy)
02002     SP+= (pspt->S[j] + pspt->dSdE[j]*(E - pspt->E[j]) )* pcmp->xn[i];    //linear interpolation + Bragg rule
02003   }
02004   return (SP);
02005 }
02006 
02007 
02008 
02022 int initlyrarray(const EXP_PARAM *pexp, const foil *MatArray, const CalibYld *LinesEnerArray, const AbsCoef *TotAbsCoefArray, const SPT *SPTArray, const int *PresentElems, int NFoil, int *NFoilUsed, LYR **plyrarray)
02023 {
02024   int i;
02025   int Eovermin;
02026   double MajAbsCoef;
02027   LYR *plyr, *plyrold;
02028 
02029   *plyrarray=(LYR*)calloc(NFoil+1,sizeof(LYR));
02030   if (*plyrarray==NULL){fprintf(stderr,"\n Error allocating memory (lyrarray)\n");exit(1);}
02031 
02032   /*The following definitions for layer 0 are done for convenience even when first "real" layer has index 1.*/
02033   plyr=&(*plyrarray)[0];
02034 
02035 //   (*plyrarray)[0].FoilOutEner=pexp->BeamEner;
02036 //   (*plyrarray)[0].absolutepos=0.;
02037 //   (*plyrarray)[0].ThickIn=0.;
02038   plyr->FoilOutEner=pexp->BeamEner;
02039   plyr->absolutepos=0.;
02040   plyr->ThickIn=0.;
02041 
02042   for(Eovermin=1, i=1; i<=NFoil && Eovermin; i++){
02043 //     printf("\n\nDEBUG:  Layer %d: \n",i);
02044 //     (*plyrarray)[i].absolutepos=(*plyrarray)[i-1].absolutepos + (*plyrarray)[i-1].ThickIn;
02045 //     (*plyrarray)[i].FoilInEner=(*plyrarray)[i-1].FoilOutEner;
02046 //     initlyr(pexp, &MatArray[i-1], XYldArray, TotAbsCoefArray, &(*plyrarray)[i], &MajAbsCoef);
02047 //     createsublyrs(pexp, &MatArray[i-1], SPTArray, MajAbsCoef, &(*plyrarray)[i] );
02048 //     Eovermin=((*plyrarray)[i].FoilOutEner > pexp->FinalEner);
02049     plyrold=plyr;
02050     plyr=&(*plyrarray)[i];
02051     plyr->absolutepos=plyrold->absolutepos + plyrold->ThickIn;
02052     plyr->FoilInEner=plyrold->FoilOutEner;
02053     plyr->pFoil=&MatArray[i-1];
02054     initlyr(pexp, LinesEnerArray, TotAbsCoefArray, PresentElems, plyr, &MajAbsCoef);
02055     createsublyrs(pexp, &MatArray[i-1], SPTArray, MajAbsCoef, plyr);
02056     Eovermin=(plyr->FoilOutEner > pexp->FinalEner);
02057   }
02058 
02059   /*if the lyr initialization loop was exited without initializing some layers,
02060     reallocate the lyr structure and change the (used) number of foils.
02061     */
02062   *NFoilUsed=i-1;
02063   if(*NFoilUsed<NFoil){
02064     #if CPIXEVERBOSITY >0
02065     printf("\n\nWarning: Layer %d (and deeper) Have been ignored during calculation\n",*NFoilUsed+1);
02066     #endif
02067   }
02068 
02069   return(0);
02070 }
02071 
02072 
02087 int initlyr(const EXP_PARAM *pexp, const CalibYld *LinesEnerArray, const AbsCoef *TotAbsCoefArray, const int *PresentElems, LYR *plyr, double *MACoef)
02088 {
02089   int i,j,jj,ll,Z;
02090   /*Auxiliary vars (or pointers):*/
02091   CalibYld *AbsFac;
02092   XrayYield *ResYld;
02093   double geomcorr;
02094 
02095 
02096   plyr->NumOfTrc=plyr->pFoil->nfoilelm;
02097 
02098 //   plyr->ResArray=(XrayYield*)calloc(plyr->NumOfTrc,sizeof(XrayYield));
02099 //   if (plyr->ResArray==NULL){fprintf(stderr,"\n Error allocating memory (plyr->ResArray)\n");exit(1);}
02100 
02101   plyr->ResYldArray=(XrayYield*)calloc(plyr->NumOfTrc,sizeof(XrayYield));
02102   if (plyr->ResYldArray==NULL){fprintf(stderr,"\n Error allocating memory (plyr->ResYldArray)\n");exit(1);}
02103 
02104   plyr->SecResArray=(SecResType*)calloc(plyr->NumOfTrc,sizeof(SecResType));
02105   if (plyr->SecResArray==NULL){fprintf(stderr,"\n Error allocating memory (plyr->SecResArray)\n");exit(1);}
02106 
02108   plyr->TrcUse=(int*)calloc(plyr->NumOfTrc,sizeof(int));
02109   if (plyr->TrcUse==NULL){fprintf(stderr,"\n Error allocating memory (plyr->TrcUse)\n");exit(1);}
02110 
02112    plyr->NeedSFC=(int*)calloc(plyr->NumOfTrc,sizeof(int));
02113    if (plyr->NeedSFC==NULL){fprintf(stderr,"\n Error allocating memory (plyr->NeedSFC)\n");exit(1);}
02115 //   plyr->NeedSFC=NULL;
02116 
02118   plyr->TrcAtnum=(int*)calloc(plyr->NumOfTrc,sizeof(int));
02119   if (plyr->TrcAtnum==NULL){fprintf(stderr,"\n Error allocating memory (plyr->TrcAtnum)\n");exit(1);}
02120 
02121 
02122   plyr->dimTrans=pexp->simpar.MaxZinsample + 1;  //The dimenssion of the Transmission vector must be enough to hold the element with Z=MaxZinsample
02123   plyr->Trans=(CalibYld*)calloc(plyr->dimTrans,sizeof(CalibYld));
02124   if (plyr->Trans==NULL){fprintf(stderr,"\n Error allocating memory (plyr->Trans)\n");exit(1);}
02125 
02126   /*Calculation of Transmission coefficient in this layer for each element present in the sample*/
02127   geomcorr= 1. / pexp->cosDet; //the thickness will be corrected considering the detector direction
02128   for(Z=1;Z<plyr->dimTrans;Z++){
02129     if(PresentElems[Z]){
02130       Transmission(LinesEnerArray, TotAbsCoefArray, Z, plyr->pFoil, geomcorr, (CalibYld*)NULL, &plyr->Trans[Z]);
02131     }
02132   }
02133 
02134 
02135   /*Initializations for each element in the layer*/
02136   for (*MACoef=0, i = 0; i < plyr->NumOfTrc; i++){
02137     /*Select which elements should be simulated*/
02138     Z=plyr->pFoil->comp.elem[i].Z;
02139     plyr->TrcUse[i]= (Z > minK);
02140     if (plyr->TrcUse[i]) {
02141       /*Initialization for plyr->ResXYldArray */
02142       ResYld=&(plyr->ResYldArray[i]);
02143       ResYld->ener=LinesEnerArray[Z];
02144       ResYld->atnum=Z;
02145       /*Some (stupid?) initialization for SecResArray*/
02146       plyr->SecResArray[i].Pk.atnum=Z;
02147       for(j=0;j<3;j++){plyr->SecResArray[i].Pk.area[j][0]=1; plyr->SecResArray[i].Pk.area[j][1]=1;}
02148 
02149       /*Calculate absorption coefficients ONLY FOR THOSE ELEMENTS THAT WILL BE NEEDED*/
02150       /*Note: */
02151 
02152       plyr->TrcAtnum[i] = Z;   //<Fills the TrcAtnum Array
02153       AbsFac= &(plyr->SecResArray[i].SR.AbsFact);
02154 
02155       if (ResYld->ener.K_[1] > 0 && ResYld->atnum < maxK) {
02156         for (jj = 1; jj <= 3; jj++) {
02157           AbsFac->K_[jj] = TotAbsor(TotAbsCoefArray, &plyr->pFoil->comp, ResYld->ener.K_[jj]);
02158           if (*MACoef < AbsFac->K_[jj]) *MACoef = AbsFac->K_[jj];
02159         }
02160       }
02161       if (ResYld->ener.M_[1] > 0 && Z > minM) {
02162         for (jj = 1; jj <= 3; jj++) {
02163           AbsFac->M_[jj] = TotAbsor(TotAbsCoefArray, &plyr->pFoil->comp, ResYld->ener.M_[jj]);
02165           /* if *MACoef<AbsC[ii].M[jj] then *MACoef:=AbsC[ii].M[jj] ;  */
02166         }
02167       }
02168       if (ResYld->ener.L_[1][1] > 0 && Z > minL) {
02169         for (jj = 1; jj <= 3; jj++) {
02170           for (ll = 1; ll <= 3; ll++) {
02171             AbsFac->L_[jj][ll] = TotAbsor(TotAbsCoefArray, &plyr->pFoil->comp, ResYld->ener.L_[jj][ll]);
02172             if (*MACoef < AbsFac->L_[jj][ll])  *MACoef = AbsFac->L_[jj][ll];
02173           }
02174         }
02175       }
02176     }
02177   }
02178   return(0);
02179 }
02180 
02181 
02189 int readFilter(const char *FilterDefFileNm, FILTER *Filter)
02190 {
02191 
02192   FILE *FilterDefFile;
02193   char dummy[LONGSTRINGLENGTH];
02194   int i,tempZ,j;
02195   foil *pfoil;
02196   double mg2at,natmass;
02197 
02198 
02199   Filter->geomcorr=1.;  
02200 
02201   FilterDefFile = fopen(FilterDefFileNm, "r");
02202   if (FilterDefFile == NULL)
02203     {fprintf(stderr,"\nERROR: Could not open file '%s' for read.\n",FilterDefFileNm);exit(1);}
02204 
02205   /*Skip until "NUMBER OF FOILS"*/
02206   do {
02207     fscanf(FilterDefFile,"%255s",dummy);
02208   } while (strcasecmp(dummy, "NUMBER_OF_FOILS"));
02209 
02210   fscanf(FilterDefFile, "%d", &Filter->nlyr);
02211 
02212   /*Initialize  Sample*/
02213   //if(*Sample!=NULL)free(*Sample);
02214   Filter->foil=(foil*)malloc((Filter->nlyr)*sizeof(foil));
02215   if (Filter->foil==NULL){fprintf(stderr,"\n Error allocating memory (Filter->foil)\n");exit(1);}
02216 
02217   for (Filter->MaxZ=0, i = 0; i < Filter->nlyr ; i++) {
02218     pfoil=&(Filter->foil[i]);
02219     do {
02220       fscanf(FilterDefFile,"%255s",dummy);
02221       } while (strcasecmp(dummy, "FOIL"));
02222 
02223     fscanf(FilterDefFile, "%lg %10s", &pfoil->thick, dummy);
02224     if(strcasecmp(dummy,"cm2") && strcasecmp(dummy,"mg")){
02225       fprintf(stderr,"\n Error: Bad syntax in filter definition file: '%s' is not a known thickness unit\n",dummy);exit(1);
02226     }
02227     fscanf(FilterDefFile, "%d",  &pfoil->nfoilelm);
02228     tempZ=readCOMPOUND(FilterDefFile, pfoil->nfoilelm, &pfoil->comp);
02229     if(Filter->MaxZ < tempZ) Filter->MaxZ = tempZ;
02230 
02231     if(!strcasecmp(dummy,"mg")){
02232       /*Convert the value in pfoil->thick from mg/cm2 to 1e15at/cm2 */
02233       for(natmass=0, j=0 ; j<pfoil->nfoilelm ; j++) natmass += pfoil->comp.xn[j] * pfoil->comp.elem[j].M;
02234       mg2at=natmass/602214.1; // (Pm [g/mol] *1e3 [mg/g] / (Navo [at/mol])) * 1e15
02235                               // ==> mg2at is in [mg/1e15at]
02236       pfoil->thick /= mg2at;  //Before this, thick was in mg/cm2, hence divide by mg2at to get 1e15at/cm2
02237     }
02238 
02239   }
02240   fclose(FilterDefFile);
02241 
02242   createPresentElems(Filter->MaxZ, Filter->nlyr, Filter->foil, &Filter->FilterElems);
02243 
02244   return(0);
02245 }
02246 
02272 int CreateEff(const char *TotAbsCoefFileNm, const  char *LinesEnerFileNm, const char *WindowDefFileNm, const char *CrystalDefFileNm, double factor ,CalibYld **EffBlockArray, int *dimEffTable, TwoCol **EffTable)
02273 {
02274   int maxZ=92, nlines=15;
02275   int ielem,jj,ll,*AllPresentElems;
02276   CalibYld *pEff, *pwin, *pcry, *pLinesEner, *LinesEner,*WindowAFTArray,*CrystalAFTArray;
02277   TwoCol *pEffTable;
02278 
02279   /*The maximum dimension of Energy and efficiency vectors*/
02280   *dimEffTable=maxZ*nlines;
02281 
02282   /*initialize The arrays that should be returned*/
02283   *EffTable=(TwoCol*)calloc(*dimEffTable,sizeof(double));
02284   if (*EffTable==NULL){fprintf(stderr,"\n Error allocating memory (EffTable)\n");exit(1);}
02285   *EffBlockArray=(CalibYld*)calloc(maxZ+1,sizeof(CalibYld));
02286   if (*EffBlockArray==NULL){fprintf(stderr,"\n Error allocating memory (EffBlockArray)\n");exit(1);}
02287 
02288   /*initialize the arrays that won't be returned (local use only)*/
02289   WindowAFTArray=(CalibYld*)calloc(maxZ+1,sizeof(CalibYld));
02290   if (WindowAFTArray==NULL){fprintf(stderr,"\n Error allocating memory (WindowAFTArray)\n");exit(1);}
02291   CrystalAFTArray=(CalibYld*)calloc(maxZ+1,sizeof(CalibYld));
02292   if (CrystalAFTArray==NULL){fprintf(stderr,"\n Error allocating memory (CrystalAFTArray)\n");exit(1);}
02293   AllPresentElems=(int*)calloc(maxZ+1,sizeof(int));
02294   if (AllPresentElems==NULL){fprintf(stderr,"\n Error allocating memory (AllPresentElems)\n");exit(1);}
02295   for(AllPresentElems[0]=0,jj=1 ; jj<=maxZ ; jj++)AllPresentElems[jj]=1; //create fake PresentElems (all present)
02296   readLinesEner(LinesEnerFileNm, AllPresentElems, maxZ, &LinesEner);
02297 
02298   AllFilterTrans(TotAbsCoefFileNm, LinesEnerFileNm, WindowDefFileNm, WindowAFTArray);
02299   AllFilterTrans(TotAbsCoefFileNm, LinesEnerFileNm, CrystalDefFileNm, CrystalAFTArray);
02300 
02301   /*Reset the dimension for Energy and Efficiency*/
02302   *dimEffTable=0;
02303 
02304   for (ielem=1,pEffTable=*EffTable;ielem<maxZ;ielem++){
02305     pEff=&(*EffBlockArray)[ielem];
02306     pwin=&WindowAFTArray[ielem];
02307     pcry=&CrystalAFTArray[ielem];
02308     pLinesEner=&LinesEner[ielem];
02309     /*Fill K lines*/
02310     for (jj = 1; jj <= 3; jj++) {
02311       pEff->K_[jj]=pwin->K_[jj] * (1.-pcry->K_[jj]) * factor;
02312       if( pLinesEner->K_[jj]>0.){
02313         pEffTable->x=pLinesEner->K_[jj];
02314         pEffTable->y=pEff->K_[jj];
02315         pEffTable++;
02316       }
02317     }
02318     /*Fill M lines*/
02319     for (jj = 1; jj <= 3; jj++){
02320       pEff->M_[jj]=pwin->M_[jj] * (1.-pcry->M_[jj]) * factor;
02321       if( pLinesEner->M_[jj]>0.){
02322         pEffTable->x=pLinesEner->M_[jj];
02323         pEffTable->y=pEff->M_[jj];
02324         pEffTable++;
02325       }
02326     }
02327     /*Fill L lines*/
02328     for (jj = 1; jj <= 3; jj++) for (ll = 1; ll <= 3; ll++) {
02329       pEff->L_[jj][ll]=pwin->L_[jj][ll] * (1.-pcry->L_[jj][ll]) * factor;
02330       if( pLinesEner->L_[jj][ll]>0.){
02331         pEffTable->x=pLinesEner->L_[jj][ll];
02332         pEffTable->y=pEff->L_[jj][ll];
02333         pEffTable++;
02334       }
02335     }
02336 
02337     #if CPIXEVERBOSITY > 0
02338     fprintf(stdout,"\n Efficiency for %2s:", ChemicalSymbol[ielem]);
02339     #endif
02340     #if CPIXEVERBOSITY > 1
02341     fprintf(stdout,"\n");
02342     fprintCALIBYLD(stdout,&(*EffBlockArray)[ielem]);
02343     #endif
02344 
02345   }
02346 
02347   /*Reallocate the Energy and Efficiency vectors to free unused space*/
02348   *dimEffTable=pEffTable-(*EffTable);
02349   *EffTable=(TwoCol*)realloc(*EffTable,(*dimEffTable)*sizeof(TwoCol));
02350   if (*EffTable==NULL){fprintf(stderr,"\n Error reallocating memory (Efftable)\n");exit(1);}
02351 
02352   /*Sort the arrays by ascending energy*/
02353   qsort(*EffTable,*dimEffTable,sizeof(TwoCol),(void*)compare_Twocol_x);
02354 
02355   #if CPIXEVERBOSITY > 0
02356   fprintf(stdout,"\n Efficiency for %d lines generated", *dimEffTable);
02357   #endif
02358   #if CPIXEVERBOSITY > 1
02359   for(jj=0; jj<*dimEffTable; jj++)fprintf(stdout,"\n%le\t\%le",(*EffTable)[jj].x,(*EffTable)[jj].y);
02360   #endif
02361 
02362   free(WindowAFTArray);
02363   free(CrystalAFTArray);
02364   free(LinesEner);
02365   free(AllPresentElems);
02366   return(maxZ);
02367 }
02368 
02378 int AllFilterTrans(const char *TotAbsCoefFileNm, const  char *LinesEnerFileNm, const char *FilterDefFileNm, CalibYld *AFTArray)
02379 {
02380   int i;
02381   int maxZ=92;
02382   int *AllPresentElems;
02383   CalibYld *LinesEnerArray;
02384   AbsCoef *TotAbsCoefArray;
02385   FILTER Filter;
02386 
02387   AllPresentElems=(int*)calloc(maxZ+1,sizeof(int));
02388   if (AllPresentElems==NULL){fprintf(stderr,"\n Error allocating memory (AllPresentElems)\n");exit(1);}
02389   for(AllPresentElems[0]=0,i=1 ; i<=maxZ ; i++)AllPresentElems[i]=1; //create fake PresentElems
02390 
02391   /*Read the energies for All the lines*/
02392   readLinesEner(LinesEnerFileNm, AllPresentElems, maxZ, &LinesEnerArray);
02393   /*Read the Absorption Coefs*/
02394   readAbsCoef(TotAbsCoefFileNm, maxZ, &TotAbsCoefArray);
02395   /*Read the Filter*/
02396   readFilter(FilterDefFileNm, &Filter);
02397 
02398   /*Calculate transmission for all the elements*/
02399   FilterTrans(maxZ, LinesEnerArray, TotAbsCoefArray, AllPresentElems, &Filter);
02400   for(i=1;i<maxZ;i++)AFTArray[i]=Filter.Trans[i];
02401 
02402   free(AllPresentElems);
02403   free(TotAbsCoefArray);
02404   free(LinesEnerArray);
02405   freeFilter(&Filter);
02406   return(maxZ);
02407 }
02408 
02409 
02419 int FilterTrans(int MaxZinsample, const CalibYld *LinesEnerArray, const AbsCoef *TotAbsCoefArray, const int *PresentElems, FILTER *Filter)
02420 {
02421   int Z,i;
02422   CalibYld auxTrans, *pTrans, *pauxTrans;
02423   CalibYld unitTrans={ { 0.0, 1.0, 1.0, 1.0 },
02424                        { { 0.0, 0.0, 0.0, 0.0 },
02425                          { 0.0, 1.0, 1.0, 1.0 },
02426                          { 0.0, 1.0, 1.0, 1.0 },
02427                          { 0.0, 1.0, 1.0, 1.0 }},
02428                        { 0.0, 1.0, 1.0, 1.0 }};
02429 
02430   //Initialize the Filter->Trans array
02431   Filter->dimTrans=MaxZinsample + 1;  //The dimenssion of the Transmission vector must be enough to hold the element with Z=MaxZinsample
02432   Filter->Trans=(CalibYld*)calloc(Filter->dimTrans,sizeof(CalibYld));
02433   if (Filter->Trans==NULL){fprintf(stderr,"\n Error allocating memory (Filter->Trans)\n");exit(1);}
02434 
02435   for(Z=1;Z<Filter->dimTrans;Z++){
02436 //     for(Z=1;Z<Filter->dimTrans;Z++)
02437     if(PresentElems[Z]){
02438       pauxTrans=NULL; //Initially, we have nothing to accumulate
02439       pTrans=&Filter->Trans[Z];
02440       *pTrans=unitTrans;
02441 
02442       for (i=0 ; i < Filter->nlyr ; i++){
02443         Transmission(LinesEnerArray, TotAbsCoefArray, Z, &Filter->foil[i], Filter->geomcorr, pauxTrans, pTrans);
02444         auxTrans= *pTrans;  //backup the last pTrans values (not the pointer but the values!)
02445         pauxTrans=&auxTrans; //pauxTrans is set to the last foil transmission for accumulating
02446       }
02447     }
02448   }
02449 
02450   return(0);
02451 }
02452 
02453 
02466 int Transmission(const CalibYld *LinesEnerArray, const AbsCoef *TotAbsCoefArray, int Z, const foil *pFoil, double geomcorr, const CalibYld *pTransOld, CalibYld *pTrans)
02467 {
02468   int jj,ll;
02469   double thickout;
02470   const CalibYld *pXYldener;
02471 
02472   thickout=pFoil->thick * geomcorr;  //Effective thickness
02473   pXYldener=&LinesEnerArray[Z];  //energies of lines for element with at.number Z
02474 
02475   /*Transmission coefs for K lines*/
02476   if (pXYldener->K_[1] > 0 && Z < maxK) {
02477     for (jj = 1; jj <= 3; jj++) {
02478       pTrans->K_[jj] = exp(-thickout * TotAbsor(TotAbsCoefArray, &pFoil->comp, pXYldener->K_[jj]) );
02479       if(pTransOld!=NULL)
02480         pTrans->K_[jj] *= pTransOld->K_[jj];
02481     }
02482   }
02483   /*Transmission coefs for M lines*/
02484   if (pXYldener->M_[1] > 0 && Z > minM) {
02485     for (jj = 1; jj <= 3; jj++) {
02486       pTrans->M_[jj] = exp(-thickout * TotAbsor(TotAbsCoefArray, &pFoil->comp, pXYldener->M_[jj]) );
02487       if(pTransOld!=NULL) pTrans->M_[jj] *= pTransOld->M_[jj];
02488     }
02489   }
02490   /*Transmission coefs for L lines*/
02491   if (pXYldener->L_[1][1] > 0 && Z > minL) {
02492     for (jj = 1; jj <= 3; jj++) {
02493       for (ll = 1; ll <= 3; ll++) {
02494         pTrans->L_[jj][ll] = exp(-thickout * TotAbsor(TotAbsCoefArray, &pFoil->comp, pXYldener->L_[jj][ll]) );
02495         if(pTransOld!=NULL) pTrans->L_[jj][ll] *= pTransOld->L_[jj][ll];
02496       }
02497     }
02498   }
02499   return(0);
02500 }
02501 
02509 double TotAbsor(const AbsCoef *TotAbsCoefArray, const COMPOUND *cmp, double Xray)
02510 {
02511   int i,iener;
02512   double absaux;
02513   int dimstdener;
02514   const AbsCoef *Absco;
02515   double stdener[23] = {      1.00, 1.25, 1.50, 1.75, 2.00,
02516                         2.50, 3.00, 3.50, 4.00, 4.50, 5.00,
02517                         5.50, 6.00, 6.50, 7.00, 8.00, 10.0,
02518                         12.5, 15.0, 17.5, 20.0, 25.0, 30.0};
02519 
02520   dimstdener=23-1;
02532   if (Xray < stdener[0] || Xray >= stdener[dimstdener])  return (0.);
02533 
02534   for(iener=1;Xray > stdener[iener];iener++);
02535 
02536 
02537   for (absaux=0, i = 0; i < cmp->nelem; i++) {
02538     Absco=&(TotAbsCoefArray[cmp->elem[i].Z]);
02539     absaux += cmp->xn[i] * TotAbsor_elemental(iener, Absco, cmp->elem[i].Z, Xray);
02540   }
02541 
02542   return(absaux);
02543 }
02544 
02553 double TotAbsor_elemental(int iener, const AbsCoef *Absco, int Z, double Xray)
02554 {
02555   int j,limj;
02556   double absaux = 0.0;
02557   double enermaj, enermin, a, b, majcoef, mincoef;
02558   double stdener[23] = {      1.00, 1.25, 1.50, 1.75, 2.00,
02559                         2.50, 3.00, 3.50, 4.00, 4.50, 5.00,
02560                         5.50, 6.00, 6.50, 7.00, 8.00, 10.0,
02561                         12.5, 15.0, 17.5, 20.0, 25.0, 30.0};
02562 
02575   enermaj = stdener[iener];
02576   enermin = stdener[iener-1];
02577   majcoef = Absco->coefstd[iener];
02578   mincoef = Absco->coefstd[iener-1];
02579 
02580   if(Z<11) limj=0;     //No absorp edges in the 1-30keV range for elements of Z<11
02581   else{
02582   if(Z<28) limj=1;     //Only K absorp edges in the 1-30keV range for elements of Z<28
02583     else{
02584       if(Z<52) limj=4; //Only K & L absorp edges in the 1-30keV range for elements of Z<52
02585       else limj=9;                  // K, L & M  absorp edges in the 1-30keV range for elements of Z>52
02586     }
02587   }
02588   /*Check wether the energy is affected by an absorption edge*/
02589   for (j = 1; j <= limj; j++) {
02590     if (Absco->enr[j] > 0 && Absco->enr[j] > enermin && Absco->enr[j] < Xray) {
02591       enermin = Absco->enr[j];
02592       mincoef = Absco->coefenr[j-1][1];
02593     }
02594     if (Absco->enr[j] > 0 && Absco->enr[j] < enermaj && Absco->enr[j] > Xray) {
02595       enermaj = Absco->enr[j];
02596       majcoef = Absco->coefenr[j-1][0];
02597     }
02598   }
02599   /*Logarithmic average*/
02600   a = log(majcoef / mincoef) / log(enermaj / enermin);
02601   b = log(majcoef) - a * log(enermaj);
02602   absaux = exp(a * log(Xray) + b);
02603 
02604   return(absaux);
02605 }
02606 
02607 
02608 
02618 int createsublyrs(const EXP_PARAM *pexp, const foil *pMat, const SPT *SPTArray, double MajAbsCoef, LYR *plyr)
02619 {
02620   ESxType ESx1,ESx2,ESx3;
02621   int i,Fpos;
02622   double Range,range1,range2, Smax;
02623 
02624   //Before starting, find out the maximum stopping force for this layer (Smax)
02625   for(Smax=0., i=0 ; i < pMat->nfoilelm ; i++) Smax += SPTArray[pMat->comp.elem[i].Z].Smax * pMat->comp.xn[i];
02626 
02627 
02628   plyr->ThickIn=pMat->thick/pexp->cosInc;
02629 
02630   Fpos=1;
02631   plyr->ESxArray=(ESxType*)malloc((Fpos)*sizeof(ESxType));
02632   if (plyr->ESxArray==NULL){fprintf(stderr,"\n Error allocating memory (plyr->ESxArray)\n");exit(1);}
02633 
02634   ESx1.ep = plyr->FoilInEner;     //note that FoilInEner has been already initialized in initlyrarray()
02635   ESx1.stpp = getSP(&pMat->comp, SPTArray, ESx1.ep);
02636   ESx1.x = 0.0;
02637   plyr->ESxArray[Fpos-1]=ESx1;
02638 
02640   ESx2.ep = plyr->FoilInEner * 0.90;
02641   ESx2.stpp = getSP(&pMat->comp, SPTArray, ESx2.ep);
02642   ESx2.x = 0.0;
02643 
02644   ESx3.ep=pexp->FinalEner;
02645   ESx3.stpp = getSP(&pMat->comp, SPTArray, ESx3.ep);
02646   ESx3.x = 0.0;
02647 
02648 //   ESx2.ep = plyr->FoilInEner - plyr->ThickIn * Smax;
02649 //   if(ESx2.ep < pexp->FinalEner)ESx2.ep= pexp->FinalEner;
02650 //   ESx2.stpp = getSP(&pMat->comp, SPTArray, ESx2.ep);
02651 //   ESx2.x = plyr->ThickIn;
02652 //
02653 //   ESx3.ep=pexp->FinalEner;
02654 //   ESx3.stpp = getSP(&pMat->comp, SPTArray, ESx3.ep);
02655 //   ESx3.x = (plyr->FoilInEner - pexp->FinalEner)/Smax;
02656 
02657 
02658   SSThick(pexp, pMat, SPTArray, MajAbsCoef, plyr->ThickIn, ESx1, &ESx2, &Fpos, &range1, &plyr->ESxArray);
02659 
02660   ESx2=  plyr->ESxArray[Fpos - 1];
02661 
02662   if (ESx2.x == plyr->ThickIn) {
02663     plyr->FoilOutEner = ESx2.ep;
02664     Range = ESx2.x;
02665     plyr->FESxlen= Fpos;
02666   }
02667   else {
02668     SSThick(pexp, pMat, SPTArray, MajAbsCoef, plyr->ThickIn, ESx2, &ESx3, &Fpos, &range2, &plyr->ESxArray);
02669     ESx3=plyr->ESxArray[Fpos-1];
02670 
02671     plyr->FoilOutEner = ESx3.ep;
02672     Range = range1 + range2;
02673     if (Range < plyr->ThickIn) plyr->ThickIn = Range;
02674     plyr->FESxlen = Fpos;
02675   }
02676 
02677   return(0);
02678 }
02679 
02680 
02695 int SSThick(const EXP_PARAM *pexp, const foil *pMat, const SPT *SPTArray, double MajAbsCoef,
02696             double LayerThickness, ESxType ESxin,  ESxType *ESxfin, int *pFpos, double *thick, ESxType **ESxA)
02697 {
02698   double tck1, tck2, auxdecis, auxstpchange,auxaux;
02699   ESxType ESxm1, ESxaux;
02700 
02701   auxaux=exp(-MajAbsCoef * ESxin.x * pexp->cosFac);
02702   if (auxaux > 1e-7){
02703     /*calculate the relative transmission
02704       Note: auxdecis is the relative contribution to the transmission due to the present layer
02705             compared to the transmission from the present layer to the surface.
02706             The cosFac transforms distances from in-going to out-going paths.
02707     */
02708     auxdecis = exp(MajAbsCoef * (ESxin.x - ESxfin->x) * pexp->cosFac) /auxaux;
02709 
02710   }
02711   else auxdecis = 1.0;
02712 
02713   /*Calculate the relative change in stopping forces (with an ad-hoc weight based on the relative energy)
02714   */
02715   auxstpchange= (ESxin.ep / pexp->BeamEner)* fabs(ESxin.stpp - ESxfin->stpp) / ((ESxin.stpp + ESxfin->stpp)/2.);
02716 
02717   /* Exit condition (no more recursive calls)*/
02720    if ( auxstpchange < 0.005  && auxdecis > 0.997 ){
02721 //    if ( auxstpchange < 0.05   ){    //DEBUG!!!!!!!
02722     ESxaux.ep = (ESxin.ep + ESxfin->ep) / 2.; //mean energy
02723     ESxaux.stpp = getSP(&pMat->comp, SPTArray, ESxaux.ep);//stopping at mean energy
02724     *thick = (ESxin.ep - ESxfin->ep) / ((ESxin.stpp + 4. *ESxaux.stpp  + ESxfin->stpp) / 6.); //
02725     ESxfin->x = ESxin.x + *thick;
02726 
02727     if (ESxfin->x > LayerThickness) {
02728       *thick = LayerThickness - ESxin.x;
02729       ESxfin->x = LayerThickness;
02730       ESxfin->ep = ESxin.ep - 0.5*(ESxin.stpp + ESxfin->stpp) * (*thick) ;
02731       ESxaux.ep = (ESxin.ep + ESxfin->ep) / 2.;
02732       ESxaux.stpp = getSP(&pMat->comp, SPTArray, ESxaux.ep);
02733     }
02734 
02735     ESxaux.x = ESxin.x + *thick / 2.;
02736 
02737     //Reallocating ESxA
02738     *ESxA=(ESxType*)realloc(*ESxA,((*pFpos)+2)*sizeof(ESxType));
02739     if (*ESxA==NULL){fprintf(stderr,"\n Error allocating memory (ESxA)\n");exit(1);}
02740 
02741     (*ESxA)[*pFpos]=ESxaux;
02742     (*pFpos)++;
02743 
02744     (*ESxA)[*pFpos]= *ESxfin;
02745     (*pFpos)++;
02746 
02747 
02749 //      printf("\nDEBUG :  x[%d]=%.3le (E=%.2lf)\tx[%d]=%.3le (E=%.2lf) ",*pFpos-2,ESxaux.x,ESxaux.ep,*pFpos-1, ESxfin->x,ESxfin->ep);
02750 //     printf("\nDEBUG : %d) xin=%.3le (E=%.2lf)\txfin=%.3le (E=%.2lf) ",*pFpos,ESxin.x,ESxin.ep,ESxfin->x,ESxfin->ep);
02751   }
02752   else{ //split in two and call SSThick() for each part
02753 //      if(auxdecis<0.97) printf("\nDEBUG :  R[%d]=A (%.4le)  x=%.4le",*pFpos,auxdecis,ESxfin->x);
02754 //      else printf("\nDEBUG :  R[%d]=S",*pFpos);
02755 
02756     ESxm1.ep = (ESxin.ep + ESxfin->ep) / 2;
02757     ESxm1.stpp = getSP(&pMat->comp, SPTArray, ESxm1.ep);
02758     ESxm1.x = ESxin.x + (ESxin.ep - ESxm1.ep) / ESxin.stpp;
02759     //if (ESxm1.x > LayerThickness)ESxm1.x = LayerThickness; //note: this value of ESxm1.x is only used for the calc of auxdecis, but does not affect to the stopping and E calcs, so we don't need to update ESxm1.ep and ESxm1.stpp
02760 
02761     SSThick(pexp, pMat, SPTArray, MajAbsCoef, LayerThickness, ESxin, &ESxm1, pFpos, &tck1, ESxA);
02762 
02763     if (ESxm1.x < LayerThickness) {
02764       SSThick(pexp, pMat, SPTArray, MajAbsCoef, LayerThickness, ESxm1, ESxfin, pFpos, &tck2, ESxA);
02765       *thick = tck1 + tck2;
02766     }
02767     else *thick = tck1;
02768   }
02769   return(0);
02770 }
02771 
02772 
02773 
02785 int integrate_Simpson2(const EXP_PARAM *pexp, const AbsCoef *TotAbsCoefArray,
02786                        const FluorCKCoef *FCKCoefArray, const CalibYld *RawEffiArray,
02787                        int NFoilUsed, const FILTER *Filter, LYR *plyrarray, CalibYld *XYldSums){
02788   int ilyr, itrans, ii, jj, ll,mm;
02789   LYR *plyr;
02790   CalibYld *AbsFac;
02791   CalibYld *pSSYld, *pSSTrs;
02792   const AbsCoef *AbsC;
02793   const FluorCKCoef *pFCKTrc;
02794   XrayYield *pResYld;
02795   const CalibYld *pEff;
02796   SecResType *pSecRes;
02797   CalibYld tempPenInt;
02798   CalibYld *pXYldSum;
02799   double tckout,tempE,tempM,attfraction;
02800   int tempZ, FirstReg;
02801   const SIM_PARAM *psim;
02802   CalibYld tempTr0;
02803   psim=&pexp->simpar;
02804 
02805   for(ilyr=1; ilyr<=NFoilUsed; ilyr++){
02806     plyr=&plyrarray[ilyr];
02807 
02808     /*Initialize (with 0 values) the SSTrsArray. (Simpson Transmission)*/
02809     plyr->SSTrsArray=(CalibYld*)calloc((plyr->NumOfTrc * plyr->FESxlen),sizeof(CalibYld));
02810     if (plyr->SSTrsArray==NULL){fprintf(stderr,"\n Error allocating memory (lyr[layer].SSTrsArray)\n");exit(1);}
02811     /*Initialize (with 0 values) the SSYldArray. (Simpson Yield) */
02812     plyr->SSYldArray=(CalibYld*)calloc((plyr->NumOfTrc * plyr->FESxlen),sizeof(CalibYld));
02813     if (plyr->SSYldArray==NULL){fprintf(stderr,"\n Error allocating memory (lyr[layer].SSYldArray)\n");exit(1);}
02814 
02815 
02816     /*Calculate the transmission array (all sublayers x all elements) FOR THE GIVEN LAYER ONLY*/
02817 
02818     for (jj = 0; jj < plyr->NumOfTrc ; jj++) {
02819       if (plyr->TrcUse[jj]) {
02820 
02821         AbsFac= &(plyr->SecResArray[jj].SR.AbsFact);
02822         tempZ=plyr->TrcAtnum[jj];
02823 
02824         for (ii = 0; ii < plyr->FESxlen; ii++) {
02825           tckout=plyr->ESxArray[ii].x * pexp->cosFac;  //effective thicknes to the surface of this layer from the sublayer ii
02826           pSSTrs=&(plyr->SSTrsArray[ii + plyr->FESxlen * jj]);  //points to the "transmission matrix element"
02827 
02828           if (tempZ < maxK) {
02829             for (ll = 1; ll <= 3; ll++) {
02830               if (AbsFac->K_[ll] > 0)
02831                 pSSTrs->K_[ll] = exp(-AbsFac->K_[ll] * tckout);
02832             }
02833           }
02834           if (tempZ > minM) {
02835             for (ll = 1; ll <= 3; ll++) {
02836               if (AbsFac->M_[ll] > 0)
02837                 pSSTrs->M_[ll] = exp(-AbsFac->M_[ll] * tckout);
02838             }
02839           }
02840           if (tempZ > minL) {
02841             for (ll = 1; ll <= 3; ll++) {
02842               for (mm = 1; mm <= 3; mm++) {
02843                 if (AbsFac->L_[ll][mm] > 0)
02844                   pSSTrs->L_[ll][mm] = exp(-AbsFac->L_[ll][mm] * tckout);
02845               }
02846             }
02847           }
02848         }
02849       }
02850     }
02851 
02852     /*Perform "Simpson" Calculation of yield.
02853     (Originally this was done in a separated function called SimpSSYld()*/
02854     for (jj = 0; jj < plyr->NumOfTrc; jj++) {
02855       if (plyr->TrcUse[jj]) {
02856 
02857         tempZ=plyr->TrcAtnum[jj];
02858         Z2mass(tempZ, &tempM, 'n');
02859         pFCKTrc=&FCKCoefArray[tempZ];
02860         AbsC=&TotAbsCoefArray[tempZ];
02861 
02862         for (ii = 0; ii < plyr->FESxlen; ii++) {
02863           tempE=plyr->ESxArray[ii].ep;
02864           pSSYld=&( plyr->SSYldArray[ (ii + plyr->FESxlen * jj) ] );
02865 
02866           Xprod(AbsC, pFCKTrc, pexp->ion.Z, tempZ, tempM, tempE, pSSYld);
02867 
02868         }
02869       }
02870     }
02871 
02872   }
02873 
02874   /*clears any previously used Sum*/
02875 
02876   /*Calculates the Penetration Integral*/
02877   for(ilyr=1; ilyr<=NFoilUsed; ilyr++){
02878     plyr=&plyrarray[ilyr];
02879 
02880     for (ii = 0; ii < plyr->NumOfTrc ; ii++) {
02881 
02882       if (plyr->TrcUse[ii]) {
02883         tempZ=plyr->TrcAtnum[ii];
02884         Z2mass(tempZ, &tempM, 'n');
02885         pFCKTrc=&FCKCoefArray[tempZ];
02886         AbsC=&TotAbsCoefArray[tempZ];
02887         pResYld=&plyr->ResYldArray[ii];
02888         pSecRes=&plyr->SecResArray[ii];
02889         AbsFac= &(plyr->SecResArray[ii].SR.AbsFact);
02890         pEff=&RawEffiArray[tempZ];
02891         pXYldSum=&XYldSums[tempZ];
02892         attfraction=plyr->pFoil->comp.xn[ii];
02893 
02894 //         printf("\n DEBUG: Calculating Penetration Integral for : %s in layer %d\n",pResYld->symb,ilyr) ;
02895 
02896         //pSSTrs and pSSYld are reused to hold now one-dimensional arrays of CalibYld structures containing the Transmission and yield values for the ii element in all sublayers. More precisely, they point to subsections (rows) of the 2-dim arrays SSTrsArray and SSYldArray that contain the mentioned info.
02897         FirstReg = (ii) * plyr->FESxlen;
02898         pSSTrs=&plyr->SSTrsArray[FirstReg];
02899         pSSYld=&plyr->SSYldArray[FirstReg];
02900 
02901         // keep in mind that YFirstReg and TFirstReg (now combined in just FirstReg) have been shifted down by one to accomodate to the redefiniton of the SSTrsArray and Yield matrices (which start in 0 for both indexes)
02902 
02903         //correction due to transmission in layers over the one we are considering
02904         tempTr0=plyr->SSTrsArray[FirstReg];  //the relevant lines become initialized at value=1
02905         //For K lines...
02906         if (tempZ < maxK) {
02907           for (ll = 1; ll <= 3; ll++) {
02908             tempTr0.K_[ll] *= Filter->Trans[tempZ].K_[ll]; //Apply transmission of filter
02909             for(itrans=ilyr-1 ; itrans>0 ; itrans--){ //apply transmission of every layer on top of current one
02910               tempTr0.K_[ll] *= plyrarray[itrans].Trans[tempZ].K_[ll];
02911             }
02912           }
02913         }
02914         //Same for M lines...
02915         if (tempZ > minM) {
02916           for (ll = 1; ll <= 3; ll++) {
02917             tempTr0.M_[ll] *= Filter->Trans[tempZ].M_[ll];
02918             for(itrans=ilyr-1 ; itrans>0 ; itrans--){
02919               tempTr0.M_[ll] *= plyrarray[itrans].Trans[tempZ].M_[ll];
02920             }
02921           }
02922         }
02923         //Same for L lines...
02924         if (tempZ > minL) {
02925           for (ll = 1; ll <= 3; ll++) {
02926             for (mm = 1; mm <= 3; mm++) {
02927               tempTr0.L_[ll][mm] *= Filter->Trans[tempZ].L_[ll][mm];
02928               for(itrans=ilyr-1 ; itrans>0 ; itrans--){
02929                 tempTr0.L_[ll][mm] *= plyrarray[itrans].Trans[tempZ].L_[ll][mm];
02930               }
02931             }
02932           }
02933         }
02934 
02935         PenInteg(tempZ, AbsFac, plyr->ESxArray, pSSYld,
02936                 pSSTrs, &tempTr0, plyr->FESxlen,
02937                 plyr->NeedSFC[ii], psim->AllowXEqCalc, plyr->absolutepos, pexp->cosInc,
02938                 &pResYld->XYld, &pSecRes->SR.SFCr, &pSecRes->SR.Xeq);
02939 
02940         tempPenInt=pResYld->XYld; //make a copy of the penetration integral results for this element
02941         deNormalize2(pexp, tempZ, attfraction, pEff, &tempPenInt, &pResYld->XYld, pXYldSum);
02942       }
02943     }
02944   }
02945 
02946 
02947   return(0);
02948 }
02949 
02950 
02951 
02963 int integrate_Simpson(const EXP_PARAM *pexp, const AbsCoef *TotAbsCoefArray,
02964                        const FluorCKCoef *FCKCoefArray, const XrayYield *XYldArray,
02965                        int NFoilUsed, const FILTER *Filter, LYR *plyrarray, CalibYld *XYldSums){
02966   int ilyr, itrans, ii, jj, ll,mm;
02967   LYR *plyr;
02968   CalibYld *AbsFac;
02969   CalibYld *pSSYld, *pSSTrs;
02970   const AbsCoef *AbsC;
02971   const FluorCKCoef *pFCKTrc;
02972   XrayYield *pResYld;
02973   const CalibYld *pXYld;
02974   SecResType *pSecRes;
02975   CalibYld *pXYldSum;
02976   double tckout,tempE,tempM,attfraction;
02977   int tempZ, FirstReg;
02978   const SIM_PARAM *psim;
02979   CalibYld tempTr0;
02980   psim=&pexp->simpar;
02981 
02982   for(ilyr=1; ilyr<=NFoilUsed; ilyr++){
02983     plyr=&plyrarray[ilyr];
02984 
02985     /*Initialize (with 0 values) the SSTrsArray. (Simpson Transmission)*/
02986     plyr->SSTrsArray=(CalibYld*)calloc((plyr->NumOfTrc * plyr->FESxlen),sizeof(CalibYld));
02987     if (plyr->SSTrsArray==NULL){fprintf(stderr,"\n Error allocating memory (lyr[layer].SSTrsArray)\n");exit(1);}
02988     /*Initialize (with 0 values) the SSYldArray. (Simpson Yield) */
02989     plyr->SSYldArray=(CalibYld*)calloc((plyr->NumOfTrc * plyr->FESxlen),sizeof(CalibYld));
02990     if (plyr->SSYldArray==NULL){fprintf(stderr,"\n Error allocating memory (lyr[layer].SSYldArray)\n");exit(1);}
02991 
02992 
02993     /*Calculate the transmission array (all sublayers x all elements) FOR THE GIVEN LAYER ONLY*/
02994 
02995     for (jj = 0; jj < plyr->NumOfTrc ; jj++) {
02996       if (plyr->TrcUse[jj]) {
02997 
02998         AbsFac= &(plyr->SecResArray[jj].SR.AbsFact);
02999         tempZ=plyr->TrcAtnum[jj];
03000 
03001         for (ii = 0; ii < plyr->FESxlen; ii++) {
03002           tckout=plyr->ESxArray[ii].x * pexp->cosFac;  //effective thicknes to the surface of this layer from the sublayer ii
03003           pSSTrs=&(plyr->SSTrsArray[ii + plyr->FESxlen * jj]);  //points to the "transmission matrix element"
03004 
03005           if (tempZ < maxK) {
03006             for (ll = 1; ll <= 3; ll++) {
03007               if (AbsFac->K_[ll] > 0)
03008                 pSSTrs->K_[ll] = exp(-AbsFac->K_[ll] * tckout);
03009             }
03010           }
03011           if (tempZ > minM) {
03012             for (ll = 1; ll <= 3; ll++) {
03013               if (AbsFac->M_[ll] > 0)
03014                 pSSTrs->M_[ll] = exp(-AbsFac->M_[ll] * tckout);
03015             }
03016           }
03017           if (tempZ > minL) {
03018             for (ll = 1; ll <= 3; ll++) {
03019               for (mm = 1; mm <= 3; mm++) {
03020                 if (AbsFac->L_[ll][mm] > 0)
03021                   pSSTrs->L_[ll][mm] = exp(-AbsFac->L_[ll][mm] * tckout);
03022               }
03023             }
03024           }
03025         }
03026       }
03027     }
03028 
03029     /*Perform "Simpson" Calculation of yield.
03030     (Originally this was done in a separated function called SimpSSYld()*/
03031     for (jj = 0; jj < plyr->NumOfTrc; jj++) {
03032       if (plyr->TrcUse[jj]) {
03033 
03034         tempZ=plyr->TrcAtnum[jj];
03035         Z2mass(tempZ, &tempM, 'n');
03036         pFCKTrc=&FCKCoefArray[tempZ];
03037         AbsC=&TotAbsCoefArray[tempZ];
03038 
03039         for (ii = 0; ii < plyr->FESxlen; ii++) {
03040           tempE=plyr->ESxArray[ii].ep;
03041           pSSYld=&( plyr->SSYldArray[ (ii + plyr->FESxlen * jj) ] );
03042 
03043           Xprod(AbsC, pFCKTrc, pexp->ion.Z, tempZ, tempM, tempE, pSSYld);
03044 
03045         }
03046       }
03047     }
03048 
03049   }
03050 
03051   /*clears any previously used Sum*/
03052 
03053   /*Calculates the Penetration Integral*/
03054   for(ilyr=1; ilyr<=NFoilUsed; ilyr++){
03055     plyr=&plyrarray[ilyr];
03056 
03057     for (ii = 0; ii < plyr->NumOfTrc ; ii++) {
03058 
03059       if (plyr->TrcUse[ii]) {
03060         tempZ=plyr->TrcAtnum[ii];
03061         Z2mass(tempZ, &tempM, 'n');
03062         pFCKTrc=&FCKCoefArray[tempZ];
03063         AbsC=&TotAbsCoefArray[tempZ];
03064         pResYld=&plyr->ResYldArray[ii];
03065         pSecRes=&plyr->SecResArray[ii];
03066         AbsFac= &(plyr->SecResArray[ii].SR.AbsFact);
03067         pXYld=&XYldArray[tempZ].XYld;
03068         pXYldSum=&XYldSums[tempZ];
03069         attfraction=plyr->pFoil->comp.xn[ii];
03070 
03071 //         printf("\n DEBUG: Calculating Penetration Integral for : %s in layer %d\n",pResYld->symb,ilyr) ;
03072 
03073         //pSSTrs and pSSYld are reused to hold now one-dimensional arrays of CalibYld structures containing the Transmission and yield values for the ii element in all sublayers. More precisely, they point to subsections (rows) of the 2-dim arrays SSTrsArray and SSYldArray that contain the mentioned info.
03074         FirstReg = (ii) * plyr->FESxlen;
03075         pSSTrs=&plyr->SSTrsArray[FirstReg];
03076         pSSYld=&plyr->SSYldArray[FirstReg];
03077 
03078         // keep in mind that YFirstReg and TFirstReg (now combined in just FirstReg) have been shifted down by one to accomodate to the redefiniton of the SSTrsArray and Yield matrices (which start in 0 for both indexes)
03079 
03080         //correction due to transmission in layers over the one we are considering
03081         tempTr0=plyr->SSTrsArray[FirstReg];  //the relevant lines become initialized at value=1
03082         //For K lines...
03083         if (tempZ < maxK) {
03084           for (ll = 1; ll <= 3; ll++) {
03085             tempTr0.K_[ll] *= Filter->Trans[tempZ].K_[ll]; //Apply transmission of filter
03086             for(itrans=ilyr-1 ; itrans>0 ; itrans--){ //apply transmission of every layer on top of current one
03087               tempTr0.K_[ll] *= plyrarray[itrans].Trans[tempZ].K_[ll];
03088             }
03089           }
03090         }
03091         //Same for M lines...
03092         if (tempZ > minM) {
03093           for (ll = 1; ll <= 3; ll++) {
03094             tempTr0.M_[ll] *= Filter->Trans[tempZ].M_[ll];
03095             for(itrans=ilyr-1 ; itrans>0 ; itrans--){
03096               tempTr0.M_[ll] *= plyrarray[itrans].Trans[tempZ].M_[ll];
03097             }
03098           }
03099         }
03100         //Same for L lines...
03101         if (tempZ > minL) {
03102           for (ll = 1; ll <= 3; ll++) {
03103             for (mm = 1; mm <= 3; mm++) {
03104               tempTr0.L_[ll][mm] *= Filter->Trans[tempZ].L_[ll][mm];
03105               for(itrans=ilyr-1 ; itrans>0 ; itrans--){
03106                 tempTr0.L_[ll][mm] *= plyrarray[itrans].Trans[tempZ].L_[ll][mm];
03107               }
03108             }
03109           }
03110         }
03111 
03112         PenInteg(tempZ, AbsFac, plyr->ESxArray, pSSYld,
03113                 pSSTrs, &tempTr0, plyr->FESxlen,
03114                 plyr->NeedSFC[ii], psim->AllowXEqCalc, plyr->absolutepos, pexp->cosInc,
03115                 &pResYld->XYld, &pSecRes->SR.SFCr, &pSecRes->SR.Xeq);
03116 
03117         deNormalize(pexp, AbsC ,pFCKTrc, tempZ, tempM, attfraction, pXYld, pResYld, pXYldSum);
03118 
03119       }
03120     }
03121   }
03122 
03123 
03124   return(0);
03125 }
03126 
03140 int Xprod(const AbsCoef *AbsC, const FluorCKCoef *pFCK, atomicnumber Z1, atomicnumber Z2, double M2 , double ener, CalibYld *XYld)
03141 {
03142   int i, j;
03143   SecXL XLaux;
03144   double auxsec;
03145   CalibYld CYldNul = { { 0.0, 0.0, 0.0, 0.0 },
03146                        { { 0.0, 0.0, 0.0, 0.0 },
03147                          { 0.0, 0.0, 0.0, 0.0 },
03148                          { 0.0, 0.0, 0.0, 0.0 },
03149                          { 0.0, 0.0, 0.0, 0.0 }},
03150                        { 0.0, 0.0, 0.0, 0.0 }};
03151   double barn_to_cm21e15;
03152 
03153   barn_to_cm21e15=1e-9;  // 1 barn/at = 1e-24 cm2/at= 1e-9 cm2/(1e15at)
03154 
03155 
03156   if(Z1!=1){fprintf(stderr,"\n Error: Xprod() currently supports only H ions\n");exit(1);}
03157 
03158   *XYld = CYldNul;
03159   switch (Z2) {
03160 
03161   case 10: 
03162   case 11:
03163   case 12:
03164   case 13:
03165   case 14:
03166     auxsec = PaulX(ener, Z2);  // barn
03167     XYld->K_[1] = auxsec * pFCK->k.K_[1] * barn_to_cm21e15;  // cm2/1e15at
03168     break;
03169 
03170   case 54:
03171   case 55:
03172   case 56:
03173   case 57:
03174   case 58:
03175   case 59:
03176     ReisX(AbsC,pFCK, ener, Z2, M2, XLaux);
03177     for (i = 1; i <= 3; i++) {
03178       for (j = 1; j <= 3; j++)
03179         XYld->L_[i][j] = XLaux[4 - i] * pFCK->k.L_[i][j] * barn_to_cm21e15;  // cm2/1e15at
03180     }
03181     break;
03182 
03183   default:
03184     if (Z2 >= 15 && Z2 <minL) { 
03185       auxsec = PaulX(ener, Z2);
03186       XYld->K_[1] = auxsec * pFCK->k.K_[1] * barn_to_cm21e15;  // cm2/1e15at
03187       XYld->K_[2] = auxsec * pFCK->k.K_[2] * barn_to_cm21e15;  // cm2/1e15at
03188     }
03189     else if (Z2 >= minL && Z2 < maxK) {
03190       auxsec = PaulX(ener, Z2);
03191       ReisX(AbsC,pFCK, ener, Z2, M2, XLaux);
03192       for (i = 1; i <= 3; i++) {
03193         XYld->K_[i] = auxsec * pFCK->k.K_[i] * barn_to_cm21e15;  // cm2/1e15at
03194         for (j = 1; j <= 3; j++)
03195           XYld->L_[i][j] = XLaux[4 - i] * pFCK->k.L_[i][j] * barn_to_cm21e15;  // cm2/1e15at
03196       }
03197     }
03198     else if (Z2 >= minM && Z2 <= 99) {
03199       ReisX(AbsC,pFCK, ener, Z2, M2, XLaux);
03200       for (i = 1; i <= 3; i++) {
03201         for (j = 1; j <= 3; j++)
03202           XYld->L_[i][j] = XLaux[4 - i] * pFCK->k.L_[i][j] * barn_to_cm21e15;  // cm2/1e15at
03203       }
03204     }
03205     break;
03206   }
03207   return(0);
03208 }
03209 
03220 double PaulX(double ener, atomicnumber z)
03221 {
03222   static double sc1 = -2.1717, sc2 = 10.8883, sc3 = 9.45875, sc4 = 0.975316,
03223     sc5 = 0.0165458, sc6 = 1.00859, sc7 = 0.0474606;
03224 
03225   static double ylim[4] = { 0., -0.86, -0.582, -0.037  };  //note, index 0 not used
03226 
03227   static double C[8][7] = {//note, indexes 0 not used
03228     { 0.,  0.       ,  0.        , 0.         ,  0.        ,  0.        ,  0.         },
03229     { 0.,  4.97159  , -0.0334597 ,  4.56721e-3, -4.17618e-6, -0.0152467 ,  9.11304e-4 },
03230     { 0.,  -3.89274 , -0.883283  , -0.0177272 ,  1.03168e-4,  0.824937  ,  0.0110194  },
03231     { 0.,  597612.0 ,  597919.0  ,  25220.1   , -37.2554   , -362099.0  , -13942.3    },
03232     { 0.,  0.107444 , -4.47727e-3,  1.30581e-4, -1.9793e-6 ,  1.00964e-8,  0.0        },
03233     { 0.,  0.113657 , -8.4197e-3 ,  2.40606e-4, -2.95528e-6,  1.26726e-8,  0.0        },
03234     { 0.,  0.0105593,  7.4928e-4 , -1.30255e-5,  9.19824e-8,  0.0       ,  0.0        },
03235     { 0., -0.0306492,  1.00377e-3, -1.68953e-5,  8.74937e-8,  0.0       ,  0.0        }};
03236 
03237   long i;
03238   double sc = 0.0;
03239   double MeV,f, pauly, paule, xx, auxpp1, auxpp2, auxpp3;
03240   double auxl[7];
03241   double b[8];
03242 
03243 
03244   MeV = ener*0.001;   // converting keV-->MeV
03245   paule = log10(MeV / (z * z));
03246   xx = paule / 1.15 + 2.22;
03247   pauly = PaulX_y(MeV, z);
03248   if (pauly < ylim[1])   // This correction is not in the PAul's paper
03249     sc = 0.0;
03250   if (pauly >= ylim[1] && pauly <= ylim[2])
03251     sc = sc1 - sc2 * pauly - sc3 * pauly * pauly;
03252   if (pauly > ylim[2] && pauly <= ylim[3])
03253     sc = sc4 - sc5 * cos(13.6 * (pauly + 0.393));
03254   if (pauly > ylim[3])
03255     sc = sc6 + sc7 * cos(6.23 * (pauly - 0.33));
03256   for (i = 1; i <= 7; i++) {
03257     b[i] = C[i][1] + C[i][2] * z + C[i][3] * z * z + C[i][4] * z * z * z;
03258     switch (i) {
03259 
03260     case 1:
03261     case 2:
03262     case 3:
03263       b[i] /= 1 + C[i][5] * z + C[i][6] * z * z;
03264       break;
03265 
03266     case 4:
03267     case 5:
03268       b[i] += C[i][5] * z * z * z * z;
03269       break;
03270     }
03271   }
03272   for (i = 3; i <= 6; i++)
03273     auxl[i] = PaulX_lp(xx, i);
03274   auxpp1 = paule - b[3];
03275   auxpp1 *= auxpp1;
03276   auxpp2 = b[4] * PaulX_lp(xx, 3);
03277   auxpp3 = b[5] * PaulX_lp(xx, 4) + b[6] * PaulX_lp(xx, 5) + b[7] * PaulX_lp(xx, 6);
03278   f = b[1] + b[2] * auxpp1 + auxpp2 + auxpp3;
03279   return (sc * exp(f * log(10.0) - 2.2 * log(z)));
03280 }
03281 
03282 
03283 
03294 double PaulX_y(double MeV, atomicnumber z)
03295 {
03296   static double teta1 = 0.313076, teta2 = 0.149231, teta3 = 5.54982e-5,
03297     teta4 = 3.7093e-6, teta5 = 0.166608;
03298   double auxz = z;
03299   double eta, theta, TEMP;
03300 
03301   TEMP = auxz - 0.3;
03302   eta = 40.0283 * MeV / (TEMP * TEMP);
03303   theta = teta1 + teta2 * auxz - teta3 * auxz * auxz + teta4 * auxz * auxz * auxz;
03304   theta /= 1 + teta5 * auxz;
03305   return (log10(2 * sqrt(eta) / theta));
03306 }
03307 
03316 double PaulX_lp(double x, long p)
03317 {
03318   double prr = 0.0;
03319   double TEMP, TEMP1;
03320 
03321   switch (p) {
03322 
03323   case 3:
03324     prr = 0.5 * (5 * x * x * x - 3 * x);
03325     break;
03326 
03327   case 4:
03328     TEMP = x * x;
03329     prr = 0.125 * (35 * (TEMP * TEMP) - 30 * x * x + 3);
03330     break;
03331 
03332   case 5:
03333     TEMP = x * x;
03334     prr = 0.125 * (63 * x * (TEMP * TEMP) - 70 * x * x * x + 15 * x);
03335     break;
03336 
03337   case 6:
03338     TEMP = x * x;
03339     TEMP1 = x * x;
03340     prr = 0.0625 * (231 * x * x * (TEMP * TEMP) - 315 * (TEMP1 * TEMP1) +
03341         105 * x * x - 5);
03342     break;
03343   }
03344   return (prr);
03345 }
03346 
03347 
03360 int ReisX(const AbsCoef *AbsC, const FluorCKCoef *pFCK, double ener, atomicnumber z, double M2, double *sigmaXL)
03361 {
03362 
03363   SecXL ion, ionuni;
03364   int i;
03365   double xi[4];
03366   int seted = 0;
03367   double TEMP;
03368   double enr;
03369   FwTipo tipo;
03370 
03371   int Ncam, Zpr, nium;
03372   double MeV, Hr, cau, a02, Z2b, z2, z4, miu, EnrSm1, Mpr, MprMeV, MprUAt, a2s, v1,Iabs, q0sb,
03373          theta, ksi, zeta, ys, ys2, d, mRs, ksir, xcb, zcbs, cbe, etam, ratnorm;
03374 
03375   MeV = ener * 1e-3;   //converting from keV to MeV
03376   Zpr = 1;   //Only protons!
03377   Mpr = 1.007;   //Only protons!
03378   Ncam = 2;   //L atomic layer
03379 
03380   Hr = 27.2116;            
03381   cau = 137.03604;         
03382   a02 = 2.800283608e-21;   
03383 
03384   tipo = L;
03385   Z2b = (double)(z) - 4.15;
03386   z2 = Z2b * Z2b;
03387   z4 = z2 * z2;
03388 
03389   MprMeV = Mpr * MEVAMU;   //MEVAMU is defined at the beginning of the file
03390   MprUAt = Mpr / UATMASS ; //UATMASS is defined at the beginning of the file
03391   EnrSm1 = MeV / MprMeV;
03392   miu = Mpr / (1 + Mpr / M2) / UATMASS;   
03393   a2s = (double)(Ncam * Ncam) / Z2b;
03394   TEMP = 1 + EnrSm1;
03395   TEMP = 1 / (TEMP * TEMP);
03396   v1 = cau * sqrt(1 - TEMP);   
03397   d = (double)Zpr * z / (miu * (v1 * v1));
03398   for (i = 1; i <= 3; i++) {
03399     enr=AbsC->enr[i+1];
03400     if (enr > 0) {
03401       seted = 1;
03402       Iabs = enr * 1e3;   // in eV
03403       q0sb = Iabs / (Hr * v1);
03404       theta = (double)(Ncam * Ncam * 2) * Iabs / (z2 * Hr);
03405       ksi = 2 * v1 / (theta * (Z2b / (double)Ncam));
03406       TEMP = ReisX_gs(tipo, i, ksi);
03407       TEMP -= ReisX_hs(tipo, i, ksi, theta);
03408       zeta = 1. + (double)(Zpr * 2) * TEMP / (Z2b * theta);
03410       TEMP=z2/(cau*cau*ksi/zeta);
03411       if (i == 1)  ys = TEMP * 0.40  / (double)Ncam ;
03412       else  ys =  TEMP * 0.15 ;
03413       ys2 = ys * ys;
03414       mRs = sqrt(1. + 1.1 * ys2) + ys;
03415       ksir = sqrt(mRs) * ksi;
03416       xi[i] = 1. / ksir;
03418       xcb = 2. * M_PI * d * q0sb * zeta;
03419       zcbs = sqrt(1. - 4. * zeta / (theta * miu * ksi * ksi * mRs));
03420       switch (i) {
03421         case 1:
03422           nium = 9;
03423           break;
03424         case 2:
03425         case 3:
03426           nium = 11;
03427           break;
03428         case 4:
03429         case 5:
03430           nium = 13;
03431           break;
03432       }
03433       TEMP = xcb / (zcbs * (1 + zcbs));
03434       cbe = (double)nium * ReisX_En(TEMP, nium + 1);
03435       TEMP = theta * ksir / ((double)(Ncam * 2));
03436       etam = TEMP * TEMP;
03437       TEMP = (double)Zpr / Z2b;
03438       ratnorm = 8. * M_PI * (a02 / (etam * theta)) * (TEMP * TEMP) * cbe / BARNTOM2;
03439       ionuni[i] = ReisX_polisec(i, ksir, theta);
03440       ion[i] = ionuni[i] * ratnorm;
03441     }
03442   }
03443   sigmaXL[1] = ReisX_g(1, z, xi[1]) * pFCK->w[2] * ion[1];
03444   sigmaXL[2] = ReisX_g(2, z, xi[2]) * pFCK->w[3] * (pFCK->ck[0] * ion[1] + ion[2]);
03445   sigmaXL[3] = ReisX_g(3, z, xi[3]) * pFCK->w[4] *
03446                ((pFCK->ck[1] + pFCK->ck[0] * pFCK->ck[2]) * ion[1] + pFCK->ck[2] * ion[2] + ion[3]);
03447 
03448   return(0);
03449 }
03450 
03463 double ReisX_gs(FwTipo T, int SS, double ksis)
03464 {
03466   static double gK[9] = {
03467     1.0, 1.0, 9.0, 31.0, 98.0, 12.0, 25.0, 4.2, 0.515
03468   };
03469 
03470   static double gL1[9] = {
03471     1.0, 1.0, 9.0, 31.0, 49.0, 162.0, 63.0, 18.0, 1.97
03472   };
03473 
03474   static double gL23[10] = {
03475     1.0, 1.0, 10.0, 45.0, 102.0, 331.0, 6.7, 58.0, 7.8, 0.888
03476   };
03477 
03478   double ksis2, ksis3, ksis4, ksis5, ksis6, ksis7, ksis8;
03479   double gsaux = 0.0;
03480   double gsaux2;
03481 
03482   ksis2 = ksis * ksis;
03483   ksis3 = ksis * ksis2;
03484   ksis4 = ksis2 * ksis2;
03485   ksis5 = ksis2 * ksis3;
03486   ksis6 = ksis3 * ksis3;
03487   ksis7 = ksis3 * ksis4;
03488   ksis8 = ksis4 * ksis4;
03489   switch (T) {
03490 
03491   case K:
03492     gsaux = gK[1] + gK[2] * ksis + gK[3] * ksis2 + gK[4] * ksis3;
03493     gsaux += gK[5] * ksis4 + gK[6] * ksis5 + gK[7] * ksis6 + gK[8] * ksis7;
03494     gsaux2 = 1 + ksis;
03495     gsaux2 *= gsaux2 * gsaux2;
03496     gsaux2 *= gsaux2 * gsaux2;
03497     gsaux /= gsaux2;
03498     break;
03499 
03500   case L:
03501     if (SS == 1) {
03502       gsaux = gL1[1] + gL1[2] * ksis + gL1[3] * ksis2 + gL1[4] * ksis3;
03503       gsaux += gL1[5] * ksis4 + gL1[6] * ksis5 + gL1[7] * ksis6 + gL1[8] * ksis7;
03504       gsaux2 = 1 + ksis;
03505       gsaux2 *= gsaux2 * gsaux2;
03506       gsaux2 *= gsaux2 * gsaux2;
03507       gsaux /= gsaux2;
03508     } else {
03509       gsaux = gL23[1] + gL23[2] * ksis + gL23[3] * ksis2 + gL23[4] * ksis3;
03510       gsaux += gL23[5] * ksis4 + gL23[6] * ksis5 + gL23[7] * ksis6 +
03511          gL23[8] * ksis7;
03512       gsaux += gL23[9] * ksis8;
03513       gsaux2 = 1 + ksis;
03514       gsaux2 *= gsaux2 * gsaux2;
03515       gsaux2 *= gsaux2 * gsaux2;
03516       gsaux2 *= 1 + ksis;
03517       gsaux /= gsaux2;
03518     }
03519     break;
03520   default:break;
03521   }
03522   return (gsaux);
03523 }
03524 
03525 
03539 double ReisX_hs(FwTipo T, int SS, double ksih, double thet)
03540 {
03541   static double IhsC[6] = { 0.031, 0.031, 0.210, 0.005, -0.069, 0.324  };
03542   double x, x12, ksih3;
03543   double Ihs = 0.0, cs = 0.0;
03544   int n2hs = 0;
03545 
03546   switch (T) {
03547 
03548   case K:
03549     n2hs = 1;
03550     cs = 3.0 / 2.;
03551     break;
03552 
03553   case L:
03554     n2hs = 2;
03555     if (SS == 1) cs = 3.0 / 2.;
03556     else  cs = 5.0 / 4.;
03557     break;
03558 
03559   default:break;
03560   }
03561   ksih3 = ksih * ksih * ksih;
03562   x = cs * n2hs / ksih;
03563   x12 = sqrt(x);
03564   if (x > 0 && x <= 0.035)
03565     Ihs = 3 * M_PI / 4 * log(1 / (x * x) - 1);
03566   if (x > 0.035 && x <= 3.1) {
03567     Ihs = IhsC[1] + IhsC[2] * x12 + IhsC[3] * x + IhsC[4] * x * x12 + IhsC[5] * x * x;
03568     Ihs = exp(-2 * x) / Ihs;
03569   }
03570   if (x > 3.1 && x < 11)
03571     Ihs = 2 * exp(-2 * x) / exp(1.6 * log(x));
03572 
03573   return(n2hs * 2 * Ihs / (thet * ksih3));
03574 }
03575 
03576 
03588 double ReisX_En(double z, int niu)
03589 {
03592   double Eaux, z2, z3, niu2, aux, aux2, aux4, aux6;
03593 
03594   z2 = z * z;
03595   z3 = z2 * z;
03596   niu2 = niu * niu;
03597   aux = z + niu;
03598   aux2 = aux * aux;
03599   aux4 = aux2 * aux2;
03600   aux6 = aux4 * aux2;
03601   Eaux = niu * (6 * z2 - 8 * niu * z + niu2) / aux6;
03602   Eaux+= 1+niu/aux2+niu*(niu-2*z)/aux4; //patch contributed by AT (was: Eaux++)
03603   Eaux = exp(-z) * Eaux / aux;
03604   return(Eaux);
03605 }
03606 
03620 double ReisX_polisec(int ssind, double kz, double tz)
03621 {
03622   double Result = 0.0;
03623 
03624   static double fc1[8] = {
03625      737.658767, -5422.24598, 17070.7835, -29572.7846,
03626      30490.2736, -18719.3387, 6343.25887, -916.108807
03627   };
03628 
03629   static double fc2[8] = {
03630     -1513.63296, 5152.69169, -7347.41315, 5748.20489,
03631     -2665.54100, 733.610039, -111.064039, 7.14045527
03632   };
03633 
03634   static double fc3[8] = {
03635      13.1119073, -41.7263393, 97.1163461, -100.159645,
03636      60.9662790, -21.6315896, 4.12048128, -0.325361134
03637   };
03638 
03639   static double fc4[8] = {
03640      18.9172599, -59.1559460, 126.801210, -127.067875,
03641      74.6217068, -25.5046721, 4.68627281, -0.357639954
03642   };
03643 
03644   double p1;
03645   double x = 0.0;
03646   double coef[8];
03647   int i;
03648 
03649   switch (ssind) {
03650 
03651   case 1:
03652     x = 1 / sqrt(kz * exp(0.3 * log(tz)));
03653     if (x < 1.35)
03654       memcpy(coef, fc1, sizeof(double) * 8);
03655     else
03656       memcpy(coef, fc2, sizeof(double) * 8);
03657     break;
03658 
03659   case 2:
03660     x = 1 / sqrt(kz * exp(0.2 * log(tz)));
03661     memcpy(coef, fc3, sizeof(double) * 8);
03662     break;
03663 
03664   case 3:
03665     x = 1 / sqrt(kz * exp(0.32 * log(tz)));
03666     memcpy(coef, fc4, sizeof(double) * 8);
03667     break;
03668   }
03669 
03670   for (p1 = coef[7], i = 6; i >=0; i--)  p1 = x * p1 + coef[i]; //polynomial calculation
03671 
03672   switch (ssind) {
03673 
03674   case 1:
03675     Result = exp(-p1) / exp(3.8 * log(tz));
03676     break;
03677 
03678   case 2:
03679     Result = exp(-p1) / exp(2.5 * log(tz));
03680     break;
03681 
03682   case 3:
03683     Result = exp(-p1) / exp(6.5 * log(tz));
03684     break;
03685   }
03686   return(Result);
03687 }
03688 
03701 double ReisX_g(int ss, atomicnumber Zg, double xi)
03702 {
03703   static double g3pol[2][8] = {
03704     { 4.980374404, -18.84795179, 37.53135546, -39.83029409, 23.94060788,
03705       -8.048533664, 1.397129084, -0.09706728869 },
03706     { -1.859600742, 12.30009972, -21.67920610, 20.38505540, -11.17032345,
03707       3.604521250, -0.6347055945, 0.04676377726 }
03708   };
03709 
03710   static double g12pol[2][8] = {
03711     { 0.7800031227, 0.5779760376, 0.01209015664, 1.382072250, -2.555731314,
03712       1.534786106, -0.3844825563, 0.03457310793 },
03713     { -4.910259919, 27.43184219, -50.44519949, 48.46725025, -26.40954176,
03714       8.230146858, -1.365807669, 0.09332547710 }
03715   };
03716 
03717   int i;
03718   int polsel = 0;
03719   double gaux = 0.0;
03720 
03721   if (xi < 0.6 || xi > 2.6)
03722     return(1.0);
03723   else {
03724     if (ss == 3) {
03725       if (Zg < 47)  return(1.0);
03726 
03727       if (Zg < 64) polsel = 0;
03728       else polsel = 1;
03729 
03730       for (gaux = g3pol[polsel][7],i = 6; i >= 0; i--)  gaux = gaux * xi + g3pol[polsel][i];
03731       return(gaux);
03732     }
03733     if (ss == 1) {
03734       if (Zg > 61 && Zg < 72)  polsel = 0;
03735       else return(1.0);
03736     }
03737     if (ss == 2) {
03738       if (Zg > 54 && Zg < 75)   polsel = 1;
03739       else return(1.0);
03740     }
03741 
03742     for (gaux = g12pol[polsel][7], i = 6; i >= 0; i--)  gaux = gaux * xi + g12pol[polsel][i];
03743     return(gaux);
03744   }
03745 }
03746 
03747 
03748 
03772 void PenInteg(atomicnumber atnumb, const CalibYld *AbsFac, const ESxType *ESA,
03773         const CalibYld *YldA, const CalibYld *TrsA, const CalibYld *pTrs0,
03774         int FExlen, int NeedSFC, int AllowXEqCalc,
03775         double x0, double CosInc,
03776         CalibYld *XYld, CalibYld *XSFCr, CalibYld *XYldxmed)
03777 {
03778   int i, j, l, limit;
03779   double auxfa, auxfb, auxfi, diffl;
03780   CalibYld auxxmed, auxy2;
03781   const CalibYld *pTrs1, *pYld1, *pSFC1, *pTrs2, *pYld2, *pSFC2, *pTrs3, *pYld3, *pSFC3;
03782 
03783   const ESxType *pEF1, *pEF2, *pEF3;
03784 
03785 /*  static const CalibYld CYldNul = { { 0.0, 0.0, 0.0, 0.0 },
03786                             { { 0.0, 0.0, 0.0, 0.0 },
03787                               { 0.0, 0.0, 0.0, 0.0 },
03788                               { 0.0, 0.0, 0.0, 0.0 },
03789                               { 0.0, 0.0, 0.0, 0.0 }},
03790                             { 0.0, 0.0, 0.0, 0.0 }};*/
03791 
03792   /*These variables need to be 0-initialized because they will be used for sumation*/
03793 
03794   *XYld=CYldNul;
03795 
03796   if(AllowXEqCalc) auxxmed = CYldNul;
03797 
03798 
03799   if (NeedSFC) {
03800     fprintf(stderr,"\n Error: Secondary Fluorescence not implemented yet\n"); exit(1);
03801     /*Note: when implementing Secondary fluorescence correction,
03802     SFC1, SFC2 and SFC3 should be read here*/
03803     auxy2 = CYldNul;
03804     }
03805   else {
03806     pSFC1=&CYldNul;
03807     pSFC2=&CYldNul;
03808     pSFC3=&CYldNul;
03809   }
03810 
03811   pEF1=&ESA[0];
03812   pTrs1=&TrsA[0];
03813   pYld1=&YldA[0];
03814 
03815   /*Note: The following loop starts in 1 and ends 1 before the max to make possible
03816     the definition of Trs1, Trs2,Trs3 and so on. Also note that its step is 2*/
03817   limit=FExlen-1;
03818   for(i=1 ; i<limit ; i+=2){
03819 
03820     pEF2=&ESA[i];
03821     pTrs2=&TrsA[i];
03822     pYld2=&YldA[i];
03823 
03824     pEF3=&ESA[i+1];
03825     pTrs3=&TrsA[i +1];
03826     pYld3=&YldA[i +1];
03827 
03828     if (atnumb < maxK) {
03829       for (j = 1; j <= 3; j++) {
03830         if (AbsFac->K_[j] > 0. && pTrs2->K_[j] > 1e-5) {
03831 
03832           auxfa = (pTrs1->K_[j] * pYld1->K_[j] + pSFC1->K_[j]) / pEF1->stpp;
03833           auxfi = (pTrs2->K_[j] * pYld2->K_[j] + pSFC2->K_[j]) / pEF2->stpp;
03834           auxfb = (pTrs3->K_[j] * pYld3->K_[j] + pSFC3->K_[j]) / pEF3->stpp;
03835           XYld->K_[j] -= pTrs0->K_[j] * Simps(pEF1->ep, pEF3->ep, auxfa, auxfi, auxfb);
03836           #if CPIXEVERBOSITY > 1
03837           if(j==1) printf("\n Z=%d   XYld=%le  (XYld/Dx=%le)   x1=%le    ",
03838                           atnumb, pTrs0->K_[j] *
03839                           Simps(pEF1->ep, pEF3->ep, auxfa, auxfi, auxfb),
03840                           Simps(pEF1->ep, pEF3->ep, auxfa, auxfi, auxfb)/(pEF1->x - pEF3->x),
03841                           pEF1->x);
03842           #endif
03844           if (AllowXEqCalc) {
03845             auxfa = (pTrs1->K_[j] * pYld1->K_[j] + pSFC1->K_[j]) * (pEF1->x + x0) * CosInc / pEF1->stpp;
03846             auxfi = (pTrs2->K_[j] * pYld2->K_[j] + pSFC2->K_[j]) * (pEF2->x + x0) * CosInc / pEF2->stpp;
03847             auxfb = (pTrs3->K_[j] * pYld3->K_[j] + pSFC3->K_[j]) * (pEF3->x + x0) * CosInc / pEF3->stpp;
03848             auxxmed.K_[j] -= pTrs0->K_[j] * Simps(pEF1->ep, pEF3->ep, auxfa, auxfi, auxfb);
03849           }
03850           if (NeedSFC){
03851             auxfa = pSFC1->K_[j] / pEF1->stpp;
03852             auxfi = pSFC2->K_[j] / pEF2->stpp;
03853             auxfb = pSFC3->K_[j] / pEF3->stpp;
03854             auxy2.K_[j] -= pTrs0->K_[j] * Simps(pEF1->ep, pEF3->ep, auxfa, auxfi, auxfb);
03855           }
03856         }
03857       }
03858     }
03859     if (atnumb > minM) {
03860       for (j = 1; j <= 3; j++) {
03861         if (AbsFac->M_[j] > 0. && pTrs2->M_[j] > 1e-5) {
03862           auxfa = (pTrs1->M_[j] * pYld1->M_[j] + pSFC1->M_[j]) / pEF1->stpp;
03863           auxfi = (pTrs2->M_[j] * pYld2->M_[j] + pSFC2->M_[j]) / pEF2->stpp;
03864           auxfb = (pTrs3->M_[j] * pYld3->M_[j] + pSFC3->M_[j]) / pEF3->stpp;
03865           XYld->M_[j] -= pTrs0->M_[j] * Simps(pEF1->ep, pEF3->ep, auxfa, auxfi, auxfb);
03866           if (AllowXEqCalc) {
03867             auxfa = (pTrs1->M_[j] * pYld1->M_[j] + pSFC1->M_[j]) * (pEF1->x + x0) * CosInc / pEF1->stpp;
03868             auxfi = (pTrs2->M_[j] * pYld2->M_[j] + pSFC2->M_[j]) * (pEF2->x + x0) * CosInc / pEF2->stpp;
03869             auxfb = (pTrs3->M_[j] * pYld3->M_[j] + pSFC3->M_[j]) * (pEF3->x + x0) * CosInc / pEF3->stpp;
03870             auxxmed.M_[j] -= pTrs0->M_[j] * Simps(pEF1->ep, pEF3->ep, auxfa, auxfi, auxfb);
03871           }
03872           if (NeedSFC){
03873             auxfa = pSFC1->M_[j] / pEF1->stpp;
03874             auxfb = pSFC2->M_[j] / pEF2->stpp;
03875             auxy2.M_[j] -= pTrs0->M_[j] * Simps(pEF1->ep, pEF3->ep, auxfa, auxfi, auxfb);
03876           }
03877         }
03878       }
03879     }
03880     if (atnumb > minL) {
03881       for (j = 1; j <= 3; j++) {
03882         for (l = 1; l <= 3; l++) {
03883           if (AbsFac->L_[j][l] > 0. && pTrs2->L_[j][l] > 1e-5) {
03884             auxfa = (pTrs1->L_[j][l] * pYld1->L_[j][l] + pSFC1->L_[j][l]) / pEF1->stpp;
03885             auxfi = (pTrs2->L_[j][l] * pYld2->L_[j][l] + pSFC2->L_[j][l]) / pEF2->stpp;
03886             auxfb = (pTrs3->L_[j][l] * pYld3->L_[j][l] + pSFC3->L_[j][l]) / pEF3->stpp;
03887             XYld->L_[j][l] -= pTrs0->L_[j][l] * Simps(pEF1->ep, pEF3->ep, auxfa, auxfi, auxfb);
03888             if (AllowXEqCalc) {
03889               auxfa = (pTrs1->L_[j][l] * pYld1->L_[j][l] + pSFC1->L_[j][l]) * (pEF1->x + x0) * CosInc / pEF1->stpp;
03890               auxfi = (pTrs2->L_[j][l] * pYld2->L_[j][l] + pSFC2->L_[j][l]) * (pEF2->x + x0) * CosInc / pEF2->stpp;
03891               auxfb = (pTrs3->L_[j][l] * pYld3->L_[j][l] + pSFC3->L_[j][l]) * (pEF3->x + x0) * CosInc / pEF3->stpp;
03892               auxxmed.L_[j][l] -= pTrs0->L_[j][l] * Simps(pEF1->ep, pEF3->ep, auxfa, auxfi, auxfb);
03893             }
03894             if (NeedSFC){
03895               auxfa = pSFC1->L_[j][l] / pEF1->stpp;
03896               auxfi = pSFC2->L_[j][l] / pEF2->stpp;
03897               auxfb = pSFC3->L_[j][l] / pEF3->stpp;
03898               diffl = 0.0;
03899               auxy2.L_[j][l] -= pTrs0->L_[j][l] * Simps(pEF1->ep, pEF3->ep, auxfa, auxfi, auxfb);
03900             }
03901           }
03902         }
03903       }
03904     }
03905     pYld1 = pYld3;
03906     pTrs1 = pTrs3;
03907     pEF1 = pEF3;
03908     pSFC1 = pSFC3;
03909   }
03910 
03911   if (NeedSFC) {
03912     for (i = 1; i <= 3; i++) {
03913       if (XYld->K_[i] > 0.)  XSFCr->K_[i] = auxy2.K_[i] / XYld->K_[i];
03914       if (XYld->M_[i] > 0.)  XSFCr->M_[i] = auxy2.M_[i] / XYld->M_[i];
03915       for (j = 1; j <= 3; j++) {
03916         if (XYld->L_[i][j] > 0.)  XSFCr->L_[i][j] = auxy2.L_[i][j] / XYld->L_[i][j];
03917       }
03918     }
03919   }
03920   else  *XSFCr = CYldNul;
03921 
03922   if (AllowXEqCalc) {
03923     for (i = 1; i <= 3; i++) {
03924       if (XYld->K_[i] > 0.)  XYldxmed->K_[i] = auxxmed.K_[i] / XYld->K_[i];
03925       if (XYld->M_[i] > 0.)  XYldxmed->M_[i] = auxxmed.M_[i] / XYld->M_[i];
03926       for (j = 1; j <= 3; j++) {
03927         if (XYld->L_[i][j] > 0.)  XYldxmed->L_[i][j] = auxxmed.L_[i][j] / XYld->L_[i][j];
03928       }
03929     }
03930   }
03931 
03932 
03933 }
03934 
03935 
03954 double Simps(double a, double b, double fa, double fi, double fb)
03955 {
03956   return ((b - a) / 6. * (fa + 4. * fi + fb));
03957 }
03958 
03959 
03960 
03985 void deNormalize(const EXP_PARAM *pexp, const AbsCoef *AbsC, const FluorCKCoef *pFCK, atomicnumber Z2, double M2, double attfraction, const CalibYld *pXYld, XrayYield *ResY, CalibYld *XYldSum)
03986 {
03987   double aux1;
03988   long jj, ll;
03989   CalibYld TransFact, Xaux;
03990   const SIM_PARAM *psim;
03991 
03992   psim=&pexp->simpar;
03993 
03994   /*Set the Transfererence factor of the filter (=1 in case no filter)*/
03995   if (psim->useFilter){
03997     fprintf(stderr,"\n Error: Filters not implemented yet\n"); exit(1);
03998 //     for (jj = 1; jj <= 3; jj++) {
03999 //       if (ResY->ener.K_[jj] > 0) TransFact.K_[jj] = FiltTrs(psim->Filter, ResY->ener.K_[jj]);
04000 //       if (ResY->ener.M_[jj] > 0) TransFact.M_[jj] = FiltTrs(psim->Filter, ResY->ener.M_[jj]);
04001 //     }
04002 //     for (jj = 1; jj <= 3; jj++) {
04003 //       for (ll = 1; ll <= 3; ll++) {
04004 //         if (ResY->ener.L_[jj][ll] > 0) TransFact.L_[jj][ll] = FiltTrs(psim->Filter, ResY->ener.L_[jj][ll]);
04005 //       }
04006 //     }
04007   }
04008   else{
04009     for (jj = 1; jj <= 3; jj++) {
04010       TransFact.K_[jj] = 1.0;
04011       TransFact.M_[jj] = 1.0;
04012     }
04013     for (jj = 1; jj <= 3; jj++) {
04014       for (ll = 1; ll <= 3; ll++) TransFact.L_[jj][ll] = 1.0;
04015     }
04016   }
04017 
04018   Xprod(AbsC, pFCK, pexp->ion.Z, Z2, M2, psim->CalEner, &Xaux); //Calculate cross section at the calibration energy
04019 
04020   switch (ResY->atnum) {
04021 
04022   case 10:
04023   case 11:
04024   case 12:
04025   case 13:
04026   case 14:
04027     if (Xaux.K_[1] > 0) {
04028       aux1 = ResY->XYld.K_[1] / Xaux.K_[1];
04029       ResY->XYld.K_[1] = pXYld->K_[1] * aux1 * psim->ColCharge * pexp->DetColFac *
04030                          TransFact.K_[1] * psim->DTCC * attfraction;
04031       XYldSum->K_[1] +=ResY->XYld.K_[1];
04032     }
04033     break;
04034 
04035   case 54:
04036   case 55:
04037   case 56:
04038   case 57:
04039   case 58:
04040   case 59:
04041     for (jj = 1; jj <= 3; jj++) {
04042       for (ll = 1; ll <= 3; ll++) {
04043         if (Xaux.L_[jj][ll] > 0){
04044           ResY->XYld.L_[jj][ll] = pXYld->L_[jj][ll] * (ResY->XYld.L_[jj][ll] / Xaux.L_[jj][ll]) *
04045                                   psim->ColCharge * pexp->DetColFac * TransFact.L_[jj][ll] *
04046                                   psim->DTCC * attfraction;
04047           XYldSum->L_[jj][ll] += ResY->XYld.L_[jj][ll];
04048         }
04049       }
04050     }
04051     break;
04052 
04053   default:
04054     if (ResY->atnum >= 15 && ResY->atnum <minL) {
04055       for (jj = 1; jj <= 2; jj++) {
04056         if (Xaux.K_[jj] > 0) {
04057           aux1 = ResY->XYld.K_[jj] / Xaux.K_[jj];
04058           ResY->XYld.K_[jj] = pXYld->K_[jj] * aux1 * psim->ColCharge *
04059                               pexp->DetColFac * TransFact.K_[jj] * psim->DTCC * attfraction;
04060           XYldSum->K_[jj] +=ResY->XYld.K_[jj];
04061         }
04062       }
04063     }
04064     else if (ResY->atnum >= minL && ResY->atnum < maxK) {
04065       for (jj = 1; jj <= 3; jj++) {
04066         if (Xaux.K_[jj] > 0) {
04067           aux1 = ResY->XYld.K_[jj] / Xaux.K_[jj];
04068           ResY->XYld.K_[jj] = pXYld->K_[jj] * aux1 * psim->ColCharge *
04069                               pexp->DetColFac * TransFact.K_[jj] * psim->DTCC * attfraction;
04070           XYldSum->K_[jj] +=ResY->XYld.K_[jj];
04071         }
04072       }
04073       for (jj = 1; jj <= 3; jj++) {
04074         for (ll = 1; ll <= 3; ll++) {
04075           if (Xaux.L_[jj][ll] > 0){
04076             ResY->XYld.L_[jj][ll] = pXYld->L_[jj][ll] * (ResY->XYld.L_[jj][ll] / Xaux.L_[jj][ll]) *
04077                                     psim->ColCharge * pexp->DetColFac * TransFact.L_[jj][ll] *
04078                                     psim->DTCC * attfraction;
04079             XYldSum->L_[jj][ll] +=ResY->XYld.L_[jj][ll];
04080           }
04081         }
04082       }
04083     }
04084     else if (ResY->atnum >= minM && ResY->atnum <= 99) {
04085       for (jj = 1; jj <= 3; jj++) {
04086         for (ll = 1; ll <= 3; ll++) {
04087           if (Xaux.L_[jj][ll] > 0){
04088             ResY->XYld.L_[jj][ll] = pXYld->L_[jj][ll] * (ResY->XYld.L_[jj][ll] / Xaux.L_[jj][ll]) *
04089                                     psim->ColCharge * pexp->DetColFac * TransFact.L_[jj][ll] *
04090                                      psim->DTCC * attfraction;
04091             XYldSum->L_[jj][ll] +=ResY->XYld.L_[jj][ll];
04092           }
04093         }
04094       }
04096     }
04097     break;
04098   }
04099 }
04100 
04101 
04102 
04103 
04136 void deNormalize2(const EXP_PARAM *pexp, atomicnumber Z2, double attfraction, const CalibYld *pEff, const CalibYld *PenInteg, CalibYld *XYld, CalibYld *XYldSum)
04137 {
04138   int jj, ll;
04139   const SIM_PARAM *psim;
04140 
04141   psim=&pexp->simpar;
04142   /*K lines*/
04143   if (Z2 >= minK && Z2 <maxK) {
04144     for (jj = 1; jj <= 3; jj++) {
04145       XYld->K_[jj]=pexp->SAngFract * pexp->Fluence * attfraction * pEff->K_[jj] * PenInteg->K_[jj];
04146       XYldSum->K_[jj] +=XYld->K_[jj];
04147     }
04148   }
04149   /*L lines*/
04150   if (Z2 >= minL ) {
04151     for (jj = 1; jj <= 3; jj++) {
04152       for (ll = 1; ll <= 3; ll++) {
04153         XYld->L_[jj][ll]=pexp->SAngFract * pexp->Fluence * attfraction *
04154                           pEff->L_[jj][ll] * PenInteg->L_[jj][ll];
04155         XYldSum->L_[jj][ll] += XYld->L_[jj][ll];
04156       }
04157     }
04158   }
04159   /*M lines*/
04160   if (Z2 >= minM) { 
04161     for (jj = 1; jj <= 3; jj++) {
04162       XYld->M_[jj]=pexp->SAngFract * pexp->Fluence * attfraction * pEff->M_[jj] * PenInteg->M_[jj];
04163       XYldSum->M_[jj] +=XYld->M_[jj];
04164     }
04165   }
04166 }
04167 
04168 
04169 
04170 
04171 
04172 
04173 
04174 
04179 void freeFilter(FILTER *Filter)
04180 {
04181   int i;
04182   foil *pFoil;
04183 
04184   for(i=0 ; i < Filter->nlyr ; i++){
04185     pFoil=&Filter->foil[i];
04186     safefree((void*)(&pFoil->comp.elem));
04187     safefree((void*)(&pFoil->comp.X));
04188     safefree((void*)(&pFoil->comp.xn));
04189     safefree((void*)(&pFoil->comp.w));
04190 
04191   }
04192   safefree((void*)(&Filter->FilterElems));
04193   safefree((void*)(&Filter->foil));
04194   safefree((void*)(&Filter->Trans));
04195 
04196 }
04197 
04202 void freeExtraInfo(EXTRAINFO *extrainfo)
04203 {
04204   safefree((void*)(&extrainfo->SampleFileNm));
04205   safefree((void*)(&extrainfo->FilterFileNm));
04206   safefree((void*)(&extrainfo->DetectorFileNm));
04207   safefree((void*)(&extrainfo->CalibFileNm));
04208   safefree((void*)(&extrainfo->AreasFileNm));
04209   safefree((void*)(&extrainfo->DBpath));
04210   safefree((void*)(&extrainfo->OutputFileNm));
04211 }
04212 
04220 void freeReusable(int NFoils, LYR **plyrarray, foil **MatArray, CalibYld **XYldSums)
04221 {
04222   int i;
04223   LYR *plyr;
04224   foil *pMat;
04225 
04226   /*Clean the layer array and the Sample Array as well as all its members which have been allocated*/
04227   for(i=1;i<=NFoils;i++){
04228     plyr=&(*plyrarray)[i];
04229     safefree((void*)(&plyr->TrcAtnum));
04230     safefree((void*)(&plyr->Trans));
04231 //     safefree((void*)(&plyr->AreasArray));
04232     safefree((void*)(&plyr->ResYldArray));
04233     safefree((void*)(&plyr->SecResArray));
04234     safefree((void*)(&plyr->TrcUse));
04235     safefree((void*)(&plyr->NeedSFC));
04236     safefree((void*)(&plyr->ESxArray));
04237     safefree((void*)(&plyr->SSTrsArray));
04238     safefree((void*)(&plyr->SSYldArray));
04239 
04240 
04241     pMat=&(*MatArray)[i-1];
04242     safefree((void*)(&pMat->comp.elem));
04243     safefree((void*)(&pMat->comp.X));
04244     safefree((void*)(&pMat->comp.xn));
04245     safefree((void*)(&pMat->comp.w));
04246 
04247   }
04248    safefree((void*)plyrarray);
04249 
04250    safefree((void*)MatArray);
04251 
04252    safefree((void*)XYldSums);
04253 }
04254 
04255 
04260 void safefree(void **ptr){
04261   if(*ptr!=NULL){
04262     //printf("\nDEBUG: freing %x ...",*ptr);fflush(stdout);
04263     free(*ptr);
04264     //printf(" done (%x)",*ptr);fflush(stdout);
04265     *ptr=NULL;
04266   }
04267 }
04268 
04269 
04275 void fprintCALIBYLD(FILE *f,const CalibYld *pCYld)
04276 {
04277   int j,l;
04278   for (j = 1; j <= 3; j++) fprintf(f,"\t%le",pCYld->K_[j]);
04279   for (j = 1; j <= 3; j++) {
04280     fprintf(f,"\n");
04281     for (l = 1; l <= 3; l++)fprintf(f,"\t%le",pCYld->L_[j][l]);
04282   }
04283   fprintf(f,"\n");
04284   for (j = 1; j <= 3; j++) fprintf(f,"\t%le",pCYld->M_[j]);
04285 
04286   fprintf(f,"\n");
04287 }
04288 
04294 void fscanCALIBYLD(FILE *f, CalibYld *pCYld)
04295 {
04296   int j,l;
04297   for (j = 1; j <= 3; j++) fscanf(f,"%lf",&pCYld->K_[j]);
04298   for (j = 1; j <= 3; j++) {
04299     for (l = 1; l <= 3; l++)fscanf(f,"%lf",&pCYld->L_[j][l]);
04300   }
04301   for (j = 1; j <= 3; j++) fscanf(f,"%lf",&pCYld->M_[j]);
04302 
04303 }
04304 
04311 int compare_Twocol_x (const TwoCol *a, const TwoCol *b)
04312 {
04313   double temp=a->x - b->x;
04314   if (temp > 0)
04315     return 1;
04316   else if (temp < 0)
04317     return -1;
04318   else
04319     return 0;
04320 }
04321 

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