Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
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$
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"
51#include "G4SystemOfUnits.hh"
52
53G4int G4SandiaTable::fCumulInterval[101] = {0};
54G4double G4SandiaTable::fSandiaCofPerAtom[4] = {0.0};
55G4double 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
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
169void 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
292void 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
516////////////////////////////////////////////////////////////////////////
517////////////////////////////////////////////////////////////////////////
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();
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
553///////////////////////////////////////////////////////////////////////
554//
555// Bubble sorting of left energy interval in SandiaTable in ascening order
556//
557
558void
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
571////////////////////////////////////////////////////////////////////////////
572//
573// SandiaIntervals
574//
575
576G4int
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
660///////////////////////////////////////////////////////////////////////
661//
662// SandiaMixing
663//
664
665G4int
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
752G4int G4SandiaTable::GetNbOfIntervals(G4int Z)
753{
754 assert (Z>0 && Z<101);
755 return fNbOfIntervals[Z];
756}
757
758//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
759
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
778{
779 assert (interval>=0 && interval<fMatNbOfIntervals && j>=0 && j<5);
780 return ((*(*fMatSandiaMatrix)[interval])[j]);
781}
782
783//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... ....oooOO0OOooo....
784
785G4double*
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
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
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
820G4double*
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
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
848G4SandiaTable::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
863////////////////////////////////////////////////////////////////////////////
864//
865// Sandia interval and mixing calculations for materialCutsCouple constructor
866//
867
868void 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//
1066////////////////////////////////////////////////////////////////////////////
1067
1068
std::vector< G4Element * > G4ElementVector
@ FatalException
std::vector< G4Material * > G4MaterialTable
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
G4double GetDensity() const
Definition: G4Material.hh:179
static const G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:562
const G4ElementVector * GetElementVector() const
Definition: G4Material.hh:189
static size_t GetNumberOfMaterials()
Definition: G4Material.cc:569
const G4double * GetFractionVector() const
Definition: G4Material.hh:193
size_t GetNumberOfElements() const
Definition: G4Material.hh:185
const G4double * GetVecNbOfAtomsPerVolume() const
Definition: G4Material.hh:205
const G4String & GetName() const
Definition: G4Material.hh:177
void clearAndDestroy()
G4double GetSandiaMatTablePAI(G4int, G4int)
void SandiaSwap(G4double **da, G4int i, G4int j)
static G4double GetZtoA(G4int Z)
G4double GetSandiaCofForMaterialPAI(G4int, G4int)
G4SandiaTable(G4Material *)
static G4double * GetSandiaCofPerAtom(G4int Z, G4double energy)
G4int GetMatNbOfIntervals()
G4int SandiaMixing(G4int Z[], const G4double *fractionW, G4int el, G4int mi)
G4double GetSandiaMatTable(G4int, G4int)
G4double GetSandiaCofForMaterial(G4int, G4int)
void SandiaSort(G4double **da, G4int sz)
G4OrderedTable * GetSandiaMatrixPAI()
G4int SandiaIntervals(G4int Z[], G4int el)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
#define DBL_MAX
Definition: templates.hh:83