Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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