Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4SandiaTable.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 
27 // $Id: G4SandiaTable.cc 67044 2013-01-30 08:50:06Z gcosmo $
28 
29 //
30 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
31 //
32 // 10.06.97 created. V. Grichine
33 // 18.11.98 simplified public interface; new methods for materials. mma
34 // 31.01.01 redesign of ComputeMatSandiaMatrix(). mma
35 // 16.02.01 adapted for STL. mma
36 // 22.02.01 GetsandiaCofForMaterial(energy) return 0 below lowest interval mma
37 // 03.04.01 fnulcof returned if energy < emin
38 // 10.07.01 Migration to STL. M. Verderi.
39 // 03.02.04 Update distructor V.Ivanchenko
40 // 05.03.04 New methods for old sorting algorithm for PAI model. V.Grichine
41 // 26.10.11 new scheme for G4Exception (mma)
42 //
43 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
44 
45 
46 #include "G4SandiaTable.hh"
47 #include "G4StaticSandiaData.hh"
48 #include "G4Material.hh"
49 #include "G4MaterialTable.hh"
50 #include "G4PhysicalConstants.hh"
51 #include "G4SystemOfUnits.hh"
52 
53 G4int G4SandiaTable::fCumulInterval[101] = {0};
54 G4double G4SandiaTable::fSandiaCofPerAtom[4] = {0.0};
55 G4double const G4SandiaTable::funitc[5] = {keV,
56  cm2*keV/g,
57  cm2*keV*keV/g,
58  cm2*keV*keV*keV/g,
59  cm2*keV*keV*keV*keV/g};
60 
61 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
62 
64  : fMaterial(material)
65 {
66  fMatSandiaMatrix = 0;
67  fMatSandiaMatrixPAI = 0;
68  fPhotoAbsorptionCof = 0;
69 
70  fMatNbOfIntervals = 0;
71 
72 
73  fMaxInterval = 0;
74  fVerbose = 0;
75 
76  //build the CumulInterval array
77 
78  fCumulInterval[0] = 1;
79 
80  for (G4int Z=1; Z<101; ++Z) {
81  fCumulInterval[Z] = fCumulInterval[Z-1] + fNbOfIntervals[Z];
82  }
83 
84  //initialisation of fnulcof
85  fnulcof[0] = fnulcof[1] = fnulcof[2] = fnulcof[3] = 0.;
86 
87  fMaxInterval = 0;
88 
89  //compute macroscopic Sandia coefs for a material
90  ComputeMatSandiaMatrix(); // mma
91 
92  // ComputeMatTable(); // vmg
93 }
94 
95 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
96 
97 // Fake default constructor - sets only member data and allocates memory
98 // for usage restricted to object persistency
99 
101  : fMaterial(0),fMatSandiaMatrix(0),fMatSandiaMatrixPAI(0),fPhotoAbsorptionCof(0)
102 {
103  fnulcof[0] = fnulcof[1] = fnulcof[2] = fnulcof[3] = 0.;
104  fMaxInterval = 0;
105  fMatNbOfIntervals = 0;
106  fVerbose = 0;
107 }
108 
109 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
110 
112 {
113  if(fMatSandiaMatrix) {
114  fMatSandiaMatrix->clearAndDestroy();
115  delete fMatSandiaMatrix;
116  }
117  if(fMatSandiaMatrixPAI) {
118  fMatSandiaMatrixPAI->clearAndDestroy();
119  delete fMatSandiaMatrixPAI;
120  }
121  if(fPhotoAbsorptionCof)
122  {
123  delete [] fPhotoAbsorptionCof;
124  }
125 }
126 
127 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
128 
129 G4double*
131 {
132  G4double Emin = fSandiaTable[fCumulInterval[Z-1]][0]*keV;
133  G4double Iopot = fIonizationPotentials[Z]*eV;
134  if (Iopot > Emin) Emin = Iopot;
135 
136  G4int interval = fNbOfIntervals[Z] - 1;
137  G4int row = fCumulInterval[Z-1] + interval;
138  while ((interval>0) && (energy<fSandiaTable[row][0]*keV)) {
139  --interval;
140  row = fCumulInterval[Z-1] + interval;
141  }
142  if (energy >= Emin)
143  {
144  G4double AoverAvo = Z*amu/fZtoAratio[Z];
145 
146  fSandiaCofPerAtom[0]=AoverAvo*funitc[1]*fSandiaTable[row][1];
147  fSandiaCofPerAtom[1]=AoverAvo*funitc[2]*fSandiaTable[row][2];
148  fSandiaCofPerAtom[2]=AoverAvo*funitc[3]*fSandiaTable[row][3];
149  fSandiaCofPerAtom[3]=AoverAvo*funitc[4]*fSandiaTable[row][4];
150  }
151  else
152  {
153  fSandiaCofPerAtom[0] = fSandiaCofPerAtom[1] = fSandiaCofPerAtom[2] =
154  fSandiaCofPerAtom[3] = 0.;
155  }
156  return fSandiaCofPerAtom;
157 }
158 
159 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
160 
162 {
163  assert (Z>0 && Z<101);
164  return fZtoAratio[Z];
165 }
166 
167 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
168 
169 void G4SandiaTable::ComputeMatSandiaMatrix()
170 {
171  //get list of elements
172  const G4int NbElm = fMaterial->GetNumberOfElements();
173  const G4ElementVector* ElementVector = fMaterial->GetElementVector();
174 
175  G4int* Z = new G4int[NbElm]; //Atomic number
176 
177  //determine the maximum number of energy-intervals for this material
178 
179  G4int MaxIntervals = 0;
180  G4int elm;
181 
182  for ( elm = 0; elm < NbElm; elm++ )
183  {
184  Z[elm] = (G4int)(*ElementVector)[elm]->GetZ();
185  MaxIntervals += fNbOfIntervals[Z[elm]];
186  }
187 
188  //copy the Energy bins in a tmp1 array
189  //(take care of the Ionization Potential of each element)
190 
191  G4double* tmp1 = new G4double[MaxIntervals];
192  G4double IonizationPot;
193  G4int interval1 = 0;
194 
195  for ( elm = 0; elm < NbElm; elm++ )
196  {
197  IonizationPot = GetIonizationPot(Z[elm]);
198 
199  for (G4int row = fCumulInterval[ Z[elm]-1 ]; row < fCumulInterval[Z[elm]]; row++ )
200  {
201  tmp1[interval1++] = std::max(fSandiaTable[row][0]*keV,IonizationPot);
202  }
203  }
204 
205  //sort the energies in strickly increasing values in a tmp2 array
206  //(eliminate redondances)
207 
208  G4double* tmp2 = new G4double[MaxIntervals];
209  G4double Emin;
210  G4int interval2 = 0;
211 
212  do
213  {
214  Emin = DBL_MAX;
215 
216  for ( G4int i1 = 0; i1 < MaxIntervals; i1++ )
217  {
218  if (tmp1[i1] < Emin) Emin = tmp1[i1]; //find the minimum
219  }
220  if (Emin < DBL_MAX) tmp2[interval2++] = Emin;
221  //copy Emin in tmp2
222  for ( G4int j1 = 0; j1 < MaxIntervals; j1++ )
223  {
224  if (tmp1[j1] <= Emin) tmp1[j1] = DBL_MAX; //eliminate from tmp1
225  }
226  } while (Emin < DBL_MAX);
227 
228  //create the sandia matrix for this material
229 
230  fMatSandiaMatrix = new G4OrderedTable();
231  G4int interval;
232 
233  for (interval = 0; interval < interval2; interval++ )
234  {
235  fMatSandiaMatrix->push_back( new G4DataVector(5,0.) );
236  }
237 
238  //ready to compute the Sandia coefs for the material
239 
240  const G4double* NbOfAtomsPerVolume = fMaterial->GetVecNbOfAtomsPerVolume();
241 
242  const G4double prec = 1.e-03*eV;
243  G4double coef, oldsum(0.), newsum(0.);
244  fMatNbOfIntervals = 0;
245 
246  for ( interval = 0; interval < interval2; interval++ )
247  {
248  Emin = (*(*fMatSandiaMatrix)[fMatNbOfIntervals])[0] = tmp2[interval];
249 
250  for ( G4int k = 1; k < 5; k++ ) {
251  (*(*fMatSandiaMatrix)[fMatNbOfIntervals])[k] = 0.;
252  }
253  newsum = 0.;
254 
255  for ( elm = 0; elm < NbElm; elm++ )
256  {
257  GetSandiaCofPerAtom(Z[elm], Emin+prec);
258 
259  for ( G4int j = 1; j < 5; j++ )
260  {
261  coef = NbOfAtomsPerVolume[elm]*fSandiaCofPerAtom[j-1];
262  (*(*fMatSandiaMatrix)[fMatNbOfIntervals])[j] += coef;
263  newsum += std::fabs(coef);
264  }
265  }
266  //check for null or redondant intervals
267 
268  if (newsum != oldsum) { oldsum = newsum; fMatNbOfIntervals++;}
269  }
270  delete [] Z;
271  delete [] tmp1;
272  delete [] tmp2;
273 
274  if ( fVerbose > 0 && fMaterial->GetName() == "G4_Ar" )
275  {
276  G4cout<<"mma, G4SandiaTable::ComputeMatSandiaMatrix(), mat = "
277  <<fMaterial->GetName()<<G4endl;
278 
279  for( G4int i = 0; i < fMatNbOfIntervals; i++)
280  {
281  G4cout<<i<<"\t"<<GetSandiaCofForMaterial(i,0)/keV<<" keV \t"
282  <<this->GetSandiaCofForMaterial(i,1)
283  <<"\t"<<this->GetSandiaCofForMaterial(i,2)
284  <<"\t"<<this->GetSandiaCofForMaterial(i,3)
285  <<"\t"<<this->GetSandiaCofForMaterial(i,4)<<G4endl;
286  }
287  }
288 }
289 
290 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
291 
292 void G4SandiaTable::ComputeMatSandiaMatrixPAI()
293 {
294  G4int MaxIntervals = 0;
295  G4int elm, c, i, j, jj, k, k1, k2, c1, n1;
296 
297  const G4int noElm = fMaterial->GetNumberOfElements();
298  const G4ElementVector* ElementVector = fMaterial->GetElementVector();
299  G4int* Z = new G4int[noElm]; //Atomic number
300 
301  for ( elm = 0; elm < noElm; elm++ )
302  {
303  Z[elm] = (G4int)(*ElementVector)[elm]->GetZ();
304  MaxIntervals += fNbOfIntervals[Z[elm]];
305  }
306  fMaxInterval = MaxIntervals + 2;
307 
308  if ( fVerbose > 0 && fMaterial->GetName() == "G4_Ar" )
309  {
310  G4cout<<"fMaxInterval = "<<fMaxInterval<<G4endl;
311  }
312  G4double* fPhotoAbsorptionCof0 = new G4double[fMaxInterval];
313  G4double* fPhotoAbsorptionCof1 = new G4double[fMaxInterval];
314  G4double* fPhotoAbsorptionCof2 = new G4double[fMaxInterval];
315  G4double* fPhotoAbsorptionCof3 = new G4double[fMaxInterval];
316  G4double* fPhotoAbsorptionCof4 = new G4double[fMaxInterval];
317 
318  for( c = 0; c < fMaxInterval; c++ ) // just in case
319  {
320  fPhotoAbsorptionCof0[c] = 0.;
321  fPhotoAbsorptionCof1[c] = 0.;
322  fPhotoAbsorptionCof2[c] = 0.;
323  fPhotoAbsorptionCof3[c] = 0.;
324  fPhotoAbsorptionCof4[c] = 0.;
325  }
326  c = 1;
327 
328  for(i = 0; i < noElm; i++)
329  {
330  G4double I1 = fIonizationPotentials[Z[i]]*keV; // I1 in keV
331  n1 = 1;
332 
333  for( j = 1; j < Z[i]; j++ ) n1 += fNbOfIntervals[j];
334 
335  G4int n2 = n1 + fNbOfIntervals[Z[i]];
336 
337  for( k1 = n1; k1 < n2; k1++ )
338  {
339  if( I1 > fSandiaTable[k1][0] )
340  {
341  continue; // no ionization for energies smaller than I1 (first
342  } // ionisation potential)
343  break;
344  }
345  G4int flag = 0;
346 
347  for( c1 = 1; c1 < c; c1++ )
348  {
349  if( fPhotoAbsorptionCof0[c1] == I1 ) // this value already has existed
350  {
351  flag = 1;
352  break;
353  }
354  }
355  if(flag == 0)
356  {
357  fPhotoAbsorptionCof0[c] = I1;
358  c++;
359  }
360  for( k2 = k1; k2 < n2; k2++ )
361  {
362  flag = 0;
363 
364  for( c1 = 1; c1 < c; c1++ )
365  {
366  if( fPhotoAbsorptionCof0[c1] == fSandiaTable[k2][0] )
367  {
368  flag = 1;
369  break;
370  }
371  }
372  if(flag == 0)
373  {
374  fPhotoAbsorptionCof0[c] = fSandiaTable[k2][0];
375  c++;
376  }
377  }
378  } // end for(i)
379  // sort out
380 
381  for( i = 1; i < c; i++ )
382  {
383  for( j = i + 1; j < c; j++ )
384  {
385  if( fPhotoAbsorptionCof0[i] > fPhotoAbsorptionCof0[j] )
386  {
387  G4double tmp = fPhotoAbsorptionCof0[i];
388  fPhotoAbsorptionCof0[i] = fPhotoAbsorptionCof0[j];
389  fPhotoAbsorptionCof0[j] = tmp;
390  }
391  }
392  if ( fVerbose > 0 && fMaterial->GetName() == "G4_Ar" )
393  {
394  G4cout<<i<<"\t energy = "<<fPhotoAbsorptionCof0[i]<<G4endl;
395  }
396  }
397  fMaxInterval = c;
398 
399  const G4double* fractionW = fMaterial->GetFractionVector();
400 
401  if ( fVerbose > 0 && fMaterial->GetName() == "G4_Ar" )
402  {
403  for( i = 0; i < noElm; i++ ) G4cout<<i<<" = elN, fraction = "<<fractionW[i]<<G4endl;
404  }
405 
406  for( i = 0; i < noElm; i++ )
407  {
408  n1 = 1;
409  G4double I1 = fIonizationPotentials[Z[i]]*keV;
410 
411  for( j = 1; j < Z[i]; j++ ) n1 += fNbOfIntervals[j];
412 
413  G4int n2 = n1 + fNbOfIntervals[Z[i]] - 1;
414 
415  for(k = n1; k < n2; k++)
416  {
417  G4double B1 = fSandiaTable[k][0];
418  G4double B2 = fSandiaTable[k+1][0];
419 
420  for(G4int q = 1; q < fMaxInterval-1; q++)
421  {
422  G4double E1 = fPhotoAbsorptionCof0[q];
423  G4double E2 = fPhotoAbsorptionCof0[q+1];
424 
425  if ( fVerbose > 0 && fMaterial->GetName() == "G4_Ar" )
426  {
427  G4cout<<"k = "<<k<<", q = "<<q<<", B1 = "<<B1<<", B2 = "<<B2<<", E1 = "<<E1<<", E2 = "<<E2<<G4endl;
428  }
429  if( B1 > E1 || B2 < E2 || E1 < I1 )
430  {
431  if ( fVerbose > 0 && fMaterial->GetName() == "G4_Ar" )
432  {
433  G4cout<<"continue for: B1 = "<<B1<<", B2 = "<<B2<<", E1 = "<<E1<<", E2 = "<<E2<<G4endl;
434  }
435  continue;
436  }
437  fPhotoAbsorptionCof1[q] += fSandiaTable[k][1]*fractionW[i];
438  fPhotoAbsorptionCof2[q] += fSandiaTable[k][2]*fractionW[i];
439  fPhotoAbsorptionCof3[q] += fSandiaTable[k][3]*fractionW[i];
440  fPhotoAbsorptionCof4[q] += fSandiaTable[k][4]*fractionW[i];
441  }
442  }
443  // Last interval
444 
445  fPhotoAbsorptionCof1[fMaxInterval-1] += fSandiaTable[k][1]*fractionW[i];
446  fPhotoAbsorptionCof2[fMaxInterval-1] += fSandiaTable[k][2]*fractionW[i];
447  fPhotoAbsorptionCof3[fMaxInterval-1] += fSandiaTable[k][3]*fractionW[i];
448  fPhotoAbsorptionCof4[fMaxInterval-1] += fSandiaTable[k][4]*fractionW[i];
449  } // for(i)
450  c = 0; // Deleting of first intervals where all coefficients = 0
451 
452  do
453  {
454  c++;
455 
456  if( fPhotoAbsorptionCof1[c] != 0.0 ||
457  fPhotoAbsorptionCof2[c] != 0.0 ||
458  fPhotoAbsorptionCof3[c] != 0.0 ||
459  fPhotoAbsorptionCof4[c] != 0.0 ) continue;
460 
461  if ( fVerbose > 0 && fMaterial->GetName() == "G4_Ar" )
462  {
463  G4cout<<c<<" = number with zero cofs"<<G4endl;
464  }
465  for( jj = 2; jj < fMaxInterval; jj++ )
466  {
467  fPhotoAbsorptionCof0[jj-1] = fPhotoAbsorptionCof0[jj];
468  fPhotoAbsorptionCof1[jj-1] = fPhotoAbsorptionCof1[jj];
469  fPhotoAbsorptionCof2[jj-1] = fPhotoAbsorptionCof2[jj];
470  fPhotoAbsorptionCof3[jj-1] = fPhotoAbsorptionCof3[jj];
471  fPhotoAbsorptionCof4[jj-1] = fPhotoAbsorptionCof4[jj];
472  }
473  fMaxInterval--;
474  c--;
475  }
476  while( c < fMaxInterval - 1 );
477 
478  // create the sandia matrix for this material
479 
480  fMatSandiaMatrixPAI = new G4OrderedTable();
481  G4double density = fMaterial->GetDensity();
482 
483  for (i = 0; i < fMaxInterval; i++) fMatSandiaMatrixPAI->push_back(new G4DataVector(5,0.));
484 
485  for (i = 0; i < fMaxInterval; i++)
486  {
487  (*(*fMatSandiaMatrixPAI)[i])[0] = fPhotoAbsorptionCof0[i+1];
488  (*(*fMatSandiaMatrixPAI)[i])[1] = fPhotoAbsorptionCof1[i+1]*density;
489  (*(*fMatSandiaMatrixPAI)[i])[2] = fPhotoAbsorptionCof2[i+1]*density;
490  (*(*fMatSandiaMatrixPAI)[i])[3] = fPhotoAbsorptionCof3[i+1]*density;
491  (*(*fMatSandiaMatrixPAI)[i])[4] = fPhotoAbsorptionCof4[i+1]*density;
492  }
493  if ( fVerbose > 0 && fMaterial->GetName() == "G4_Ar" )
494  {
495  G4cout<<"mma, G4SandiaTable::ComputeMatSandiaMatrixPAI(), mat = "<<fMaterial->GetName()<<G4endl;
496 
497  for( i = 0; i < fMaxInterval; i++)
498  {
499  G4cout<<i<<"\t"<<GetSandiaMatTablePAI(i,0)/keV<<" keV \t"<<this->GetSandiaMatTablePAI(i,1)
500  <<"\t"<<this->GetSandiaMatTablePAI(i,2)<<"\t"<<this->GetSandiaMatTablePAI(i,3)
501  <<"\t"<<this->GetSandiaMatTablePAI(i,4)<<G4endl;
502  }
503  }
504 
505  delete [] Z;
506  delete [] fPhotoAbsorptionCof0;
507  delete [] fPhotoAbsorptionCof1;
508  delete [] fPhotoAbsorptionCof2;
509  delete [] fPhotoAbsorptionCof3;
510  delete [] fPhotoAbsorptionCof4;
511  return;
512 }
513 
514 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
515 
518 //
519 // Methods for PAI model
520 
521 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
522 
524 {
525  fMaterial = 0;
526  fMatNbOfIntervals = 0;
527  fMatSandiaMatrix = 0;
528  fMatSandiaMatrixPAI = 0;
529  fPhotoAbsorptionCof = 0;
530 
531 
532  fMaxInterval = 0;
533  fVerbose = 0;
534 
535  //initialisation of fnulcof
536  fnulcof[0] = fnulcof[1] = fnulcof[2] = fnulcof[3] = 0.;
537 
538  const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
539  G4int numberOfMat = G4Material::GetNumberOfMaterials();
540 
541  if ( matIndex >= 0 && matIndex < numberOfMat)
542  {
543  fMaterial = (*theMaterialTable)[matIndex];
544  ComputeMatTable();
545  }
546  else
547  {
548  G4Exception("G4SandiaTable::G4SandiaTable(G4int matIndex)", "mat401",
549  FatalException, "wrong matIndex");
550  }
551 }
552 
554 //
555 // Bubble sorting of left energy interval in SandiaTable in ascening order
556 //
557 
558 void
560  G4int sz )
561 {
562  for(G4int i = 1;i < sz; i++ )
563  {
564  for(G4int j = i + 1;j < sz; j++ )
565  {
566  if(da[i][0] > da[j][0]) SandiaSwap(da,i,j);
567  }
568  }
569 }
570 
572 //
573 // SandiaIntervals
574 //
575 
576 G4int
578  G4int el )
579 {
580  G4int c, i, flag = 0, n1 = 1;
581  G4int j, c1, k1, k2;
582  G4double I1;
583  fMaxInterval = 0;
584 
585  for( i = 0; i < el; i++ ) fMaxInterval += fNbOfIntervals[ Z[i] ];
586 
587  fMaxInterval += 2;
588 
589  if( fVerbose > 0 ) G4cout<<"begin sanInt, fMaxInterval = "<<fMaxInterval<<G4endl;
590 
591  fPhotoAbsorptionCof = new G4double* [fMaxInterval];
592 
593  for( i = 0; i < fMaxInterval; i++ ) fPhotoAbsorptionCof[i] = new G4double[5];
594 
595  // for(c = 0; c < fIntervalLimit; c++) // just in case
596 
597  for( c = 0; c < fMaxInterval; c++ ) fPhotoAbsorptionCof[c][0] = 0.;
598 
599  c = 1;
600 
601  for( i = 0; i < el; i++ )
602  {
603  I1 = fIonizationPotentials[ Z[i] ]*keV; // First ionization
604  n1 = 1; // potential in keV
605 
606  for( j = 1; j < Z[i]; j++ ) n1 += fNbOfIntervals[j];
607 
608  G4int n2 = n1 + fNbOfIntervals[Z[i]];
609 
610  for( k1 = n1; k1 < n2; k1++ )
611  {
612  if( I1 > fSandiaTable[k1][0] )
613  {
614  continue; // no ionization for energies smaller than I1 (first
615  } // ionisation potential)
616  break;
617  }
618  flag = 0;
619 
620  for( c1 = 1; c1 < c; c1++ )
621  {
622  if( fPhotoAbsorptionCof[c1][0] == I1 ) // this value already has existed
623  {
624  flag = 1;
625  break;
626  }
627  }
628  if( flag == 0 )
629  {
630  fPhotoAbsorptionCof[c][0] = I1;
631  c++;
632  }
633  for( k2 = k1; k2 < n2; k2++ )
634  {
635  flag = 0;
636 
637  for( c1 = 1; c1 < c; c1++ )
638  {
639  if( fPhotoAbsorptionCof[c1][0] == fSandiaTable[k2][0] )
640  {
641  flag = 1;
642  break;
643  }
644  }
645  if( flag == 0 )
646  {
647  fPhotoAbsorptionCof[c][0] = fSandiaTable[k2][0];
648  if( fVerbose > 0 ) G4cout<<"sanInt, c = "<<c<<", E_c = "<<fPhotoAbsorptionCof[c][0]<<G4endl;
649  c++;
650  }
651  }
652  } // end for(i)
653 
654  SandiaSort(fPhotoAbsorptionCof,c);
655  fMaxInterval = c;
656  if( fVerbose > 0 ) G4cout<<"end SanInt, fMaxInterval = "<<fMaxInterval<<G4endl;
657  return c;
658 }
659 
661 //
662 // SandiaMixing
663 //
664 
665 G4int
667  const G4double fractionW[],
668  G4int el,
669  G4int mi )
670 {
671  G4int i, j, n1, k, c=1, jj, kk;
672  G4double I1, B1, B2, E1, E2;
673 
674  for( i = 0; i < mi; i++ )
675  {
676  for( j = 1; j < 5; j++ ) fPhotoAbsorptionCof[i][j] = 0.;
677  }
678  for( i = 0; i < el; i++ )
679  {
680  n1 = 1;
681  I1 = fIonizationPotentials[Z[i]]*keV;
682 
683  for( j = 1; j < Z[i]; j++ ) n1 += fNbOfIntervals[j];
684 
685  G4int n2 = n1 + fNbOfIntervals[Z[i]] - 1;
686 
687  for( k = n1; k < n2; k++ )
688  {
689  B1 = fSandiaTable[k][0];
690  B2 = fSandiaTable[k+1][0];
691 
692  for( c = 1; c < mi-1; c++ )
693  {
694  E1 = fPhotoAbsorptionCof[c][0];
695  E2 = fPhotoAbsorptionCof[c+1][0];
696 
697  if( B1 > E1 || B2 < E2 || E1 < I1 ) continue;
698 
699  for( j = 1; j < 5; j++ )
700  {
701  fPhotoAbsorptionCof[c][j] += fSandiaTable[k][j]*fractionW[i];
702  if( fVerbose > 0 )
703  {
704  G4cout<<"c="<<c<<"; j="<<j<<"; fST="<<fSandiaTable[k][j]<<"; frW="<<fractionW[i]<<G4endl;
705  }
706  }
707  }
708  }
709  for( j = 1; j < 5; j++ ) // Last interval
710  {
711  fPhotoAbsorptionCof[mi-1][j] += fSandiaTable[k][j]*fractionW[i];
712  if( fVerbose > 0 )
713  {
714  G4cout<<"mi-1="<<mi-1<<"; j="<<j<<"; fST="<<fSandiaTable[k][j]<<"; frW="<<fractionW[i]<<G4endl;
715  }
716  }
717  } // for(i)
718  c = 0; // Deleting of first intervals where all coefficients = 0
719 
720  do
721  {
722  c++;
723 
724  if( fPhotoAbsorptionCof[c][1] != 0.0 ||
725  fPhotoAbsorptionCof[c][2] != 0.0 ||
726  fPhotoAbsorptionCof[c][3] != 0.0 ||
727  fPhotoAbsorptionCof[c][4] != 0.0 ) continue;
728 
729  for( jj = 2; jj < mi; jj++ )
730  {
731  for( kk = 0; kk < 5; kk++ ) fPhotoAbsorptionCof[jj-1][kk] = fPhotoAbsorptionCof[jj][kk];
732  }
733  mi--;
734  c--;
735  }
736  while( c < mi - 1 );
737 
738  if( fVerbose > 0 ) G4cout<<"end SanMix, mi = "<<mi<<G4endl;
739 
740  return mi;
741 }
742 
743 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
744 
746 {
747  return fMatNbOfIntervals;
748 }
749 
750 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
751 
752 G4int G4SandiaTable::GetNbOfIntervals(G4int Z)
753 {
754  assert (Z>0 && Z<101);
755  return fNbOfIntervals[Z];
756 }
757 
758 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
759 
760 G4double
762 {
763  assert (Z>0 && Z<101 && interval>=0 && interval<fNbOfIntervals[Z]
764  && j>=0 && j<5);
765 
766  G4int row = fCumulInterval[Z-1] + interval;
767  G4double x = fSandiaTable[row][0]*CLHEP::keV;
768  if (j > 0) {
769  x = Z*CLHEP::amu/fZtoAratio[Z]*fSandiaTable[row][j]*funitc[j];
770  }
771  return x;
772 }
773 
774 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
775 
776 G4double
778 {
779  assert (interval>=0 && interval<fMatNbOfIntervals && j>=0 && j<5);
780  return ((*(*fMatSandiaMatrix)[interval])[j]);
781 }
782 
783 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
784 
785 G4double*
787 {
788  G4double* x = fnulcof;
789  if (energy >= (*(*fMatSandiaMatrix)[0])[0]) {
790 
791  G4int interval = fMatNbOfIntervals - 1;
792  while ((interval>0)&&(energy<(*(*fMatSandiaMatrix)[interval])[0]))
793  {interval--;}
794  x = &((*(*fMatSandiaMatrix)[interval])[1]);
795  }
796  return x;
797 }
798 
799 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
800 
801 G4double
803 {
804  assert (interval >= 0 && interval < fMaxInterval && j >= 0 && j < 5 );
805  return ((*(*fMatSandiaMatrix)[interval])[j])*funitc[j];
806 }
807 
808 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
809 
810 G4double
812 {
813  assert (interval>=0 && interval<fMatNbOfIntervals && j>=0 && j<5);
814  if(!fMatSandiaMatrixPAI) ComputeMatSandiaMatrixPAI();
815  return ((*(*fMatSandiaMatrixPAI)[interval])[j]);
816 }
817 
818 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
819 
820 G4double*
822 {
823  if(!fMatSandiaMatrixPAI) ComputeMatSandiaMatrixPAI();
824  G4double* x = fnulcof;
825  if (energy >= (*(*fMatSandiaMatrixPAI)[0])[0]) {
826 
827  G4int interval = fMatNbOfIntervals - 1;
828  while ((interval>0)&&(energy<(*(*fMatSandiaMatrixPAI)[interval])[0]))
829  {interval--;}
830  x = &((*(*fMatSandiaMatrixPAI)[interval])[1]);
831  }
832  return x;
833 }
834 
835 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
836 
837 G4double
839 {
840  assert (interval >= 0 && interval < fMaxInterval && j >= 0 && j < 5 );
841  if(!fMatSandiaMatrixPAI) { ComputeMatSandiaMatrixPAI(); }
842  return ((*(*fMatSandiaMatrixPAI)[interval])[j])*funitc[j];
843 }
844 
845 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
846 
847 G4double
848 G4SandiaTable::GetIonizationPot(G4int Z)
849 {
850  assert (Z>0 && Z<101);
851  return fIonizationPotentials[Z]*CLHEP::eV;
852 }
853 
854 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
855 
858 {
859  if(!fMatSandiaMatrixPAI) { ComputeMatSandiaMatrixPAI(); }
860  return fMatSandiaMatrixPAI;
861 }
862 
864 //
865 // Sandia interval and mixing calculations for materialCutsCouple constructor
866 //
867 
868 void G4SandiaTable::ComputeMatTable()
869 {
870  G4int MaxIntervals = 0;
871  G4int elm, c, i, j, jj, k, kk, k1, k2, c1, n1;
872 
873  const G4int noElm = fMaterial->GetNumberOfElements();
874  const G4ElementVector* ElementVector = fMaterial->GetElementVector();
875  G4int* Z = new G4int[noElm]; //Atomic number
876 
877  for (elm = 0; elm<noElm; elm++)
878  {
879  Z[elm] = (G4int)(*ElementVector)[elm]->GetZ();
880  MaxIntervals += fNbOfIntervals[Z[elm]];
881  }
882  fMaxInterval = 0;
883 
884  for(i = 0; i < noElm; i++) fMaxInterval += fNbOfIntervals[Z[i]];
885 
886  fMaxInterval += 2;
887 
888 // G4cout<<"fMaxInterval = "<<fMaxInterval<<G4endl;
889 
890  fPhotoAbsorptionCof = new G4double* [fMaxInterval];
891 
892  for(i = 0; i < fMaxInterval; i++)
893  {
894  fPhotoAbsorptionCof[i] = new G4double[5];
895  }
896 
897  // for(c = 0; c < fIntervalLimit; c++) // just in case
898 
899  for(c = 0; c < fMaxInterval; c++) // just in case
900  {
901  fPhotoAbsorptionCof[c][0] = 0.;
902  }
903  c = 1;
904 
905  for(i = 0; i < noElm; i++)
906  {
907  G4double I1 = fIonizationPotentials[Z[i]]*keV; // First ionization
908  n1 = 1; // potential in keV
909 
910  for(j = 1; j < Z[i]; j++)
911  {
912  n1 += fNbOfIntervals[j];
913  }
914  G4int n2 = n1 + fNbOfIntervals[Z[i]];
915 
916  for(k1 = n1; k1 < n2; k1++)
917  {
918  if(I1 > fSandiaTable[k1][0])
919  {
920  continue; // no ionization for energies smaller than I1 (first
921  } // ionisation potential)
922  break;
923  }
924  G4int flag = 0;
925 
926  for(c1 = 1; c1 < c; c1++)
927  {
928  if(fPhotoAbsorptionCof[c1][0] == I1) // this value already has existed
929  {
930  flag = 1;
931  break;
932  }
933  }
934  if(flag == 0)
935  {
936  fPhotoAbsorptionCof[c][0] = I1;
937  c++;
938  }
939  for(k2 = k1; k2 < n2; k2++)
940  {
941  flag = 0;
942 
943  for(c1 = 1; c1 < c; c1++)
944  {
945  if(fPhotoAbsorptionCof[c1][0] == fSandiaTable[k2][0])
946  {
947  flag = 1;
948  break;
949  }
950  }
951  if(flag == 0)
952  {
953  fPhotoAbsorptionCof[c][0] = fSandiaTable[k2][0];
954  c++;
955  }
956  }
957  } // end for(i)
958 
959  SandiaSort(fPhotoAbsorptionCof,c);
960  fMaxInterval = c;
961 
962  const G4double* fractionW = fMaterial->GetFractionVector();
963 
964  for(i = 0; i < fMaxInterval; i++)
965  {
966  for(j = 1; j < 5; j++) fPhotoAbsorptionCof[i][j] = 0.;
967  }
968  for(i = 0; i < noElm; i++)
969  {
970  n1 = 1;
971  G4double I1 = fIonizationPotentials[Z[i]]*keV;
972 
973  for(j = 1; j < Z[i]; j++)
974  {
975  n1 += fNbOfIntervals[j];
976  }
977  G4int n2 = n1 + fNbOfIntervals[Z[i]] - 1;
978 
979  for(k = n1; k < n2; k++)
980  {
981  G4double B1 = fSandiaTable[k][0];
982  G4double B2 = fSandiaTable[k+1][0];
983  for(G4int q = 1; q < fMaxInterval-1; q++)
984  {
985  G4double E1 = fPhotoAbsorptionCof[q][0];
986  G4double E2 = fPhotoAbsorptionCof[q+1][0];
987  if(B1 > E1 || B2 < E2 || E1 < I1)
988  {
989  continue;
990  }
991  for(j = 1; j < 5; j++)
992  {
993  fPhotoAbsorptionCof[q][j] += fSandiaTable[k][j]*fractionW[i];
994  }
995  }
996  }
997  for(j = 1; j < 5; j++) // Last interval
998  {
999  fPhotoAbsorptionCof[fMaxInterval-1][j] += fSandiaTable[k][j]*fractionW[i];
1000  }
1001  } // for(i)
1002 
1003  c = 0; // Deleting of first intervals where all coefficients = 0
1004 
1005  do
1006  {
1007  c++;
1008 
1009  if( fPhotoAbsorptionCof[c][1] != 0.0 ||
1010  fPhotoAbsorptionCof[c][2] != 0.0 ||
1011  fPhotoAbsorptionCof[c][3] != 0.0 ||
1012  fPhotoAbsorptionCof[c][4] != 0.0 ) continue;
1013 
1014  for(jj = 2; jj < fMaxInterval; jj++)
1015  {
1016  for(kk = 0; kk < 5; kk++)
1017  {
1018  fPhotoAbsorptionCof[jj-1][kk]= fPhotoAbsorptionCof[jj][kk];
1019  }
1020  }
1021  fMaxInterval--;
1022  c--;
1023  }
1024  while(c < fMaxInterval - 1);
1025 
1026  // create the sandia matrix for this material
1027 
1028  fMaxInterval--; // vmg 20.11.10
1029 
1030  fMatSandiaMatrix = new G4OrderedTable();
1031 
1032  for (i = 0; i < fMaxInterval; i++)
1033  {
1034  fMatSandiaMatrix->push_back(new G4DataVector(5,0.));
1035  }
1036  for ( i = 0; i < fMaxInterval; i++ )
1037  {
1038  for( j = 0; j < 5; j++ )
1039  {
1040  (*(*fMatSandiaMatrix)[i])[j] = fPhotoAbsorptionCof[i+1][j];
1041  }
1042  }
1043  fMatNbOfIntervals = fMaxInterval;
1044 
1045  if ( fVerbose > 0 )
1046  {
1047  G4cout<<"vmg, G4SandiaTable::ComputeMatTable(), mat = "<<fMaterial->GetName()<<G4endl;
1048 
1049  for ( i = 0; i < fMaxInterval; i++ )
1050  {
1051  // G4cout<<i<<"\t"<<(*(*fMatSandiaMatrix)[i])[0]<<" keV \t"<<(*(*fMatSandiaMatrix)[i])[1]
1052  // <<"\t"<<(*(*fMatSandiaMatrix)[i])[2]<<"\t"<<(*(*fMatSandiaMatrix)[i])[3]
1053  // <<"\t"<<(*(*fMatSandiaMatrix)[i])[4]<<G4endl;
1054 
1055  G4cout<<i<<"\t"<<GetSandiaCofForMaterial(i,0)/keV<<" keV \t"<<this->GetSandiaCofForMaterial(i,1)
1056  <<"\t"<<this->GetSandiaCofForMaterial(i,2)<<"\t"<<this->GetSandiaCofForMaterial(i,3)
1057  <<"\t"<<this->GetSandiaCofForMaterial(i,4)<<G4endl;
1058  }
1059  }
1060  delete [] Z;
1061  return;
1062 }
1063 
1064 // G4SandiaTable class -- end of implementation file
1065 //
1067 
1068