Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/lowenergy/src/G4VCrossSectionHandler.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 //
 28 // Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
 29 //
 30 // History:
 31 // -----------
 32 // 1  Aug 2001   MGP        Created
 33 // 09 Oct 2001   VI         Add FindValue with 3 parameters 
 34 //                          + NumberOfComponents
 35 // 19 Jul 2002   VI         Create composite data set for material
 36 // 21 Jan 2003   VI         Cut per region
 37 //
 38 // 15 Jul 2009   Nicolas A. Karakatsanis
 39 //
 40 //                           - LoadNonLogData method was created to load only the non-logarithmic data from G4EMLOW
 41 //                             dataset. It is essentially performing the data loading operations as in the past.
 42 //
 43 //                           - LoadData method was revised in order to calculate the logarithmic values of the data
 44 //                             It retrieves the data values from the G4EMLOW data files but, then, calculates the
 45 //                             respective log values and loads them to seperate data structures.
 46 //                             The EM data sets, initialized this way, contain both non-log and log values.
 47 //                             These initialized data sets can enhance the computing performance of data interpolation
 48 //                             operations
 49 //
 50 //                           - BuildMeanFreePathForMaterials method was also revised in order to calculate the 
 51 //                             logarithmic values of the loaded data. 
 52 //                             It generates the data values and, then, calculates the respective log values which 
 53 //                             later load to seperate data structures.
 54 //                             The EM data sets, initialized this way, contain both non-log and log values.
 55 //                             These initialized data sets can enhance the computing performance of data interpolation
 56 //                             operations
 57 //                             
 58 //                           - LoadShellData method was revised in order to eliminate the presence of a potential
 59 //                             memory leak originally identified by Riccardo Capra.
 60 //                             Riccardo Capra Original Comment
 61 //                             Riccardo Capra <capra@ge.infn.it>: PLEASE CHECK THE FOLLOWING PIECE OF CODE
 62 //                             "energies" AND "data" G4DataVector ARE ALLOCATED, FILLED IN AND NEVER USED OR
 63 //                             DELETED. WHATSMORE LOADING FILE OPERATIONS WERE DONE BY G4ShellEMDataSet
 64 //                             EVEN BEFORE THE CHANGES I DID ON THIS FILE. SO THE FOLLOWING CODE IN MY
 65 //                             OPINION SHOULD BE USELESS AND SHOULD PRODUCE A MEMORY LEAK.
 66 //
 67 //
 68 // -------------------------------------------------------------------
 69 
 70 #include "G4VCrossSectionHandler.hh"
 71 #include "G4VDataSetAlgorithm.hh"
 72 #include "G4LogLogInterpolation.hh"
 73 #include "G4VEMDataSet.hh"
 74 #include "G4EMDataSet.hh"
 75 #include "G4CompositeEMDataSet.hh"
 76 #include "G4ShellEMDataSet.hh"
 77 #include "G4ProductionCutsTable.hh"
 78 #include "G4Material.hh"
 79 #include "G4Element.hh"
 80 #include "Randomize.hh"
 81 #include <map>
 82 #include <vector>
 83 #include <fstream>
 84 #include <sstream>
 85 
 86 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 87 
 88 G4VCrossSectionHandler::G4VCrossSectionHandler()
 89 {
 90   crossSections = 0;
 91   interpolation = 0;
 92   Initialise();
 93   ActiveElements();
 94 }
 95 
 96 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
 97 
 98 G4VCrossSectionHandler::G4VCrossSectionHandler(G4VDataSetAlgorithm* algorithm,
 99                  G4double minE,
100                  G4double maxE,
101                  G4int bins,
102                  G4double unitE,
103                  G4double unitData,
104                  G4int minZ, 
105                  G4int maxZ)
106   : interpolation(algorithm), eMin(minE), eMax(maxE), 
107     unit1(unitE), unit2(unitData), zMin(minZ), zMax(maxZ), 
108     nBins(bins)
109 {
110   crossSections = nullptr;
111   ActiveElements();
112 }
113 
114 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
115 
116 G4VCrossSectionHandler::~G4VCrossSectionHandler()
117 {
118   delete interpolation;
119   interpolation = nullptr;
120 
121   for (auto & pos : dataMap)
122     {
123       G4VEMDataSet* dataSet = pos.second;
124       delete dataSet;
125     }
126 
127   if (crossSections != nullptr)
128     {
129       std::size_t n = crossSections->size();
130       for (std::size_t i=0; i<n; i++)
131   {
132     delete (*crossSections)[i];
133   }
134       delete crossSections;
135       crossSections = nullptr;
136     }
137 }
138 
139 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
140 
141 void G4VCrossSectionHandler::Initialise(G4VDataSetAlgorithm* algorithm,
142           G4double minE, G4double maxE, 
143           G4int numberOfBins,
144           G4double unitE, G4double unitData,
145           G4int minZ, G4int maxZ)
146 {
147   if (algorithm != nullptr) 
148     {
149       delete interpolation;
150       interpolation = algorithm;
151     }
152   else
153     {
154       delete interpolation;
155       interpolation = CreateInterpolation();
156     }
157 
158   eMin = minE;
159   eMax = maxE;
160   nBins = numberOfBins;
161   unit1 = unitE;
162   unit2 = unitData;
163   zMin = minZ;
164   zMax = maxZ;
165 }
166 
167 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
168 
169 void G4VCrossSectionHandler::PrintData() const
170 {
171   for (auto & pos : dataMap) 
172     {
173       G4int z = pos.first;
174       G4VEMDataSet* dataSet = pos.second;     
175       G4cout << "---- Data set for Z = "
176        << z
177        << G4endl;
178       dataSet->PrintData();
179       G4cout << "--------------------------------------------------" << G4endl;
180     }
181 }
182 
183 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
184 
185 void G4VCrossSectionHandler::LoadData(const G4String& fileName)
186 {
187   std::size_t nZ = activeZ.size();
188   for (std::size_t i=0; i<nZ; ++i)
189     {
190       G4int Z = G4int(activeZ[i]);
191 
192       // Build the complete string identifying the file with the data set      
193       const char* path = G4FindDataDir("G4LEDATA");
194       if (!path)
195   { 
196           G4Exception("G4VCrossSectionHandler::LoadData",
197         "em0006",FatalException,"G4LEDATA environment variable not set");
198     return;
199   }
200       
201       std::ostringstream ost;
202       ost << path << '/' << fileName << Z << ".dat";
203       std::ifstream file(ost.str().c_str());
204       std::filebuf* lsdp = file.rdbuf();
205        
206       if (! (lsdp->is_open()) )
207   {
208     G4String excep = "data file: " + ost.str() + " not found";
209           G4Exception("G4VCrossSectionHandler::LoadData",
210         "em0003",FatalException,excep);
211   }
212       G4double a = 0;
213       G4int k = 0;
214       G4int nColumns = 2;
215 
216       G4DataVector* orig_reg_energies = new G4DataVector;
217       G4DataVector* orig_reg_data = new G4DataVector;
218       G4DataVector* log_reg_energies = new G4DataVector;
219       G4DataVector* log_reg_data = new G4DataVector;
220 
221       do
222   {
223     file >> a;
224 
225           if (a==0.) a=1e-300;
226 
227     // The file is organized into four columns:
228     // 1st column contains the values of energy
229     // 2nd column contains the corresponding data value
230     // The file terminates with the pattern: -1   -1
231     //                                       -2   -2
232           //
233     if (a != -1 && a != -2)
234       {
235         if (k%nColumns == 0)
236                 {
237      orig_reg_energies->push_back(a*unit1);
238                  log_reg_energies->push_back(std::log10(a)+std::log10(unit1));
239                 }
240         else if (k%nColumns == 1)
241                 {
242      orig_reg_data->push_back(a*unit2);
243                  log_reg_data->push_back(std::log10(a)+std::log10(unit2));
244                 }
245               k++;
246       }
247   } 
248       while (a != -2); // End of File
249       
250       file.close();
251       G4VDataSetAlgorithm* algo = interpolation->Clone();
252       G4VEMDataSet* dataSet = new G4EMDataSet(Z,orig_reg_energies,orig_reg_data,
253                 log_reg_energies,log_reg_data,algo);
254       dataMap[Z] = dataSet;
255     }
256 }
257 
258 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
259 
260 void G4VCrossSectionHandler::LoadNonLogData(const G4String& fileName)
261 {
262   std::size_t nZ = activeZ.size();
263   for (std::size_t i=0; i<nZ; ++i)
264     {
265       G4int Z = G4int(activeZ[i]);
266 
267       // Build the complete string identifying the file with the data set      
268       const char* path = G4FindDataDir("G4LEDATA");
269       if (!path)
270   { 
271           G4Exception("G4VCrossSectionHandler::LoadNonLogData",
272         "em0006",FatalException,"G4LEDATA environment variable not set");
273     return;
274   }
275       
276       std::ostringstream ost;
277       ost << path << '/' << fileName << Z << ".dat";
278       std::ifstream file(ost.str().c_str());
279       std::filebuf* lsdp = file.rdbuf();
280        
281       if (! (lsdp->is_open()) )
282   {
283     G4String excep = "data file: " + ost.str() + " not found";
284           G4Exception("G4VCrossSectionHandler::LoadNonLogData",
285         "em0003",FatalException,excep);
286   }
287       G4double a = 0;
288       G4int k = 0;
289       G4int nColumns = 2;
290 
291       G4DataVector* orig_reg_energies = new G4DataVector;
292       G4DataVector* orig_reg_data = new G4DataVector;
293 
294       do
295   {
296     file >> a;
297 
298     // The file is organized into four columns:
299     // 1st column contains the values of energy
300     // 2nd column contains the corresponding data value
301     // The file terminates with the pattern: -1   -1
302     //                                       -2   -2
303           //
304     if (a != -1 && a != -2)
305       {
306         if (k%nColumns == 0)
307                 {
308      orig_reg_energies->push_back(a*unit1);
309                 }
310         else if (k%nColumns == 1)
311                 {
312      orig_reg_data->push_back(a*unit2);
313                 }
314               k++;
315       }
316   } 
317       while (a != -2); // End of File
318       
319       file.close();
320       G4VDataSetAlgorithm* algo = interpolation->Clone();
321 
322       G4VEMDataSet* dataSet = new G4EMDataSet(Z,orig_reg_energies,orig_reg_data,algo);
323       dataMap[Z] = dataSet;
324     }
325 }
326 
327 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
328 
329 void G4VCrossSectionHandler::LoadShellData(const G4String& fileName)
330 {
331   std::size_t nZ = activeZ.size();
332   for (std::size_t i=0; i<nZ; ++i)
333     {
334       G4int Z = G4int(activeZ[i]);
335       
336       G4VDataSetAlgorithm* algo = interpolation->Clone();
337       G4VEMDataSet* dataSet = new G4ShellEMDataSet(Z, algo);
338       dataSet->LoadData(fileName);      
339       dataMap[Z] = dataSet;
340     }
341 }
342 
343 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
344 
345 void G4VCrossSectionHandler::Clear()
346 {
347   // Reset the map of data sets: remove the data sets from the map 
348   if(! dataMap.empty())
349     {
350       for (auto & pos : dataMap)
351   {
352     G4VEMDataSet* dataSet = pos.second;
353     delete dataSet;
354     dataSet = nullptr;
355     G4int i = pos.first;
356     dataMap[i] = nullptr;
357   }
358   dataMap.clear();
359     }
360   activeZ.clear();
361   ActiveElements();
362 }
363 
364 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
365 
366 G4double G4VCrossSectionHandler::FindValue(G4int Z, G4double energy) const
367 {
368   G4double value = 0.;
369  
370   auto pos = dataMap.find(Z);
371   if (pos!= dataMap.end())
372     {
373       G4VEMDataSet* dataSet = (*pos).second;
374       value = dataSet->FindValue(energy);
375     }
376   else
377     {
378       G4cout << "WARNING: G4VCrossSectionHandler::FindValue did not find Z = "
379        << Z << G4endl;
380     }
381   return value;
382 }
383 
384 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
385 
386 G4double G4VCrossSectionHandler::FindValue(G4int Z, G4double energy, 
387                                            G4int shellIndex) const
388 {
389   G4double value = 0.;
390   auto pos = dataMap.find(Z);
391   if (pos!= dataMap.cend())
392     {
393       G4VEMDataSet* dataSet = (*pos).second;
394       if (shellIndex >= 0) 
395   {
396     G4int nComponents = (G4int)dataSet->NumberOfComponents();
397     if(shellIndex < nComponents)    
398       value = dataSet->GetComponent(shellIndex)->FindValue(energy);
399     else 
400       {
401         G4cout << "WARNING: G4VCrossSectionHandler::FindValue did not find"
402          << " shellIndex= " << shellIndex
403          << " for  Z= "
404          << Z << G4endl;
405       }
406   } else {
407     value = dataSet->FindValue(energy);
408   }
409     }
410   else
411     {
412       G4cout << "WARNING: G4VCrossSectionHandler::FindValue did not find Z = "
413        << Z << G4endl;
414     }
415   return value;
416 }
417 
418 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
419 
420 G4double G4VCrossSectionHandler::ValueForMaterial(const G4Material* material,
421               G4double energy) const
422 {
423   G4double value = 0.;
424   const G4ElementVector* elementVector = material->GetElementVector();
425   const G4double* nAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
426   std::size_t nElements = material->GetNumberOfElements();
427 
428   for (std::size_t i=0 ; i<nElements ; ++i)
429     {
430       G4int Z = (G4int) (*elementVector)[i]->GetZ();
431       G4double elementValue = FindValue(Z,energy);
432       G4double nAtomsVol = nAtomsPerVolume[i];
433       value += nAtomsVol * elementValue;
434     }
435 
436   return value;
437 }
438 
439 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
440 
441 G4VEMDataSet* G4VCrossSectionHandler::BuildMeanFreePathForMaterials(const G4DataVector* energyCuts)
442 {
443   // Builds a CompositeDataSet containing the mean free path for each material
444   // in the material table
445   G4DataVector energyVector;
446   G4double dBin = std::log10(eMax/eMin) / nBins;
447 
448   for (G4int i=0; i<nBins+1; i++)
449     {
450       energyVector.push_back(std::pow(10., std::log10(eMin)+i*dBin));
451     }
452 
453   // Factory method to build cross sections in derived classes,
454   // related to the type of physics process
455 
456   if (crossSections != nullptr)
457     {  // Reset the list of cross sections
458       if (! crossSections->empty())
459   {
460     for (auto mat=crossSections->begin(); mat != crossSections->end(); ++mat)
461       {
462         G4VEMDataSet* set = *mat;
463         delete set;
464         set = nullptr;
465       }
466     crossSections->clear();
467     delete crossSections;
468     crossSections = nullptr;
469   }
470     }
471 
472   crossSections = BuildCrossSectionsForMaterials(energyVector,energyCuts);
473 
474   if (crossSections == nullptr)
475     {
476       G4Exception("G4VCrossSectionHandler::BuildMeanFreePathForMaterials",
477         "em1010",FatalException,"crossSections = 0");
478       return 0;
479     }
480 
481   G4VDataSetAlgorithm* algo = CreateInterpolation();
482   G4VEMDataSet* materialSet = new G4CompositeEMDataSet(algo);
483 
484   G4DataVector* energies;
485   G4DataVector* data;
486   G4DataVector* log_energies;
487   G4DataVector* log_data;
488   
489   const G4ProductionCutsTable* theCoupleTable=
490         G4ProductionCutsTable::GetProductionCutsTable();
491   G4int numOfCouples = (G4int)theCoupleTable->GetTableSize();
492 
493   for (G4int mLocal=0; mLocal<numOfCouples; ++mLocal)
494     {
495       energies = new G4DataVector;
496       data = new G4DataVector;
497       log_energies = new G4DataVector;
498       log_data = new G4DataVector;
499       for (G4int bin=0; bin<nBins; bin++)
500   {
501     G4double energy = energyVector[bin];
502     energies->push_back(energy);
503           log_energies->push_back(std::log10(energy));
504     G4VEMDataSet* matCrossSet = (*crossSections)[mLocal];
505     G4double materialCrossSection = 0.0;
506           G4int nElm = (G4int)matCrossSet->NumberOfComponents();
507           for(G4int j=0; j<nElm; ++j) {
508             materialCrossSection += matCrossSet->GetComponent(j)->FindValue(energy);
509     }
510 
511     if (materialCrossSection > 0.)
512       {
513         data->push_back(1./materialCrossSection);
514               log_data->push_back(std::log10(1./materialCrossSection));
515       }
516     else
517       {
518         data->push_back(DBL_MAX);
519               log_data->push_back(std::log10(DBL_MAX));
520       }
521   }
522       G4VDataSetAlgorithm* algoLocal = CreateInterpolation();
523       G4VEMDataSet* dataSet = new G4EMDataSet(mLocal,energies,data,log_energies,log_data,algoLocal,1.,1.);
524       materialSet->AddComponent(dataSet);
525     }
526   return materialSet;
527 }
528 
529 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
530 
531 G4int G4VCrossSectionHandler::SelectRandomAtom(const G4MaterialCutsCouple* couple,
532                                                      G4double e) const
533 {
534   // Select randomly an element within the material, according to the weight
535   // determined by the cross sections in the data set
536   const G4Material* material = couple->GetMaterial();
537   G4int nElements = (G4int)material->GetNumberOfElements();
538 
539   // Special case: the material consists of one element
540   if (nElements == 1)
541     {
542       G4int Z = (G4int) material->GetZ();
543       return Z;
544     }
545 
546   // Composite material
547   const G4ElementVector* elementVector = material->GetElementVector();
548   std::size_t materialIndex = couple->GetIndex();
549 
550   G4VEMDataSet* materialSet = (*crossSections)[materialIndex];
551   G4double materialCrossSection0 = 0.0;
552   G4DataVector cross;
553   cross.clear();
554   for ( G4int i=0; i < nElements; i++ )
555     {
556       G4double cr = materialSet->GetComponent(i)->FindValue(e);
557       materialCrossSection0 += cr;
558       cross.push_back(materialCrossSection0);
559     }
560 
561   G4double random = G4UniformRand() * materialCrossSection0;
562   for (G4int k=0 ; k < nElements ; k++ )
563     {
564       if (random <= cross[k]) return (G4int) (*elementVector)[k]->GetZ();
565     }
566   // It should never get here
567   return 0;
568 }
569 
570 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
571 
572 const G4Element* G4VCrossSectionHandler::SelectRandomElement(const G4MaterialCutsCouple* couple,
573                    G4double e) const
574 {
575   // Select randomly an element within the material, according to the weight determined
576   // by the cross sections in the data set
577   const G4Material* material = couple->GetMaterial();
578   G4Element* nullElement = 0;
579   G4int nElements = (G4int)material->GetNumberOfElements();
580   const G4ElementVector* elementVector = material->GetElementVector();
581 
582   // Special case: the material consists of one element
583   if (nElements == 1)
584     {
585       return (*elementVector)[0];
586     }
587   else
588     {
589       // Composite material
590 
591       std::size_t materialIndex = couple->GetIndex();
592 
593       G4VEMDataSet* materialSet = (*crossSections)[materialIndex];
594       G4double materialCrossSection0 = 0.0;
595       G4DataVector cross;
596       cross.clear();
597       for (G4int i=0; i<nElements; ++i)
598         {
599           G4double cr = materialSet->GetComponent(i)->FindValue(e);
600           materialCrossSection0 += cr;
601           cross.push_back(materialCrossSection0);
602         }
603 
604       G4double random = G4UniformRand() * materialCrossSection0;
605 
606       for (G4int k=0 ; k < nElements ; ++k )
607         {
608           if (random <= cross[k]) return (*elementVector)[k];
609         }
610       // It should never end up here
611       G4cout << "G4VCrossSectionHandler::SelectRandomElement - no element found" << G4endl;
612       return nullElement;
613     }
614 }
615 
616 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
617 
618 G4int G4VCrossSectionHandler::SelectRandomShell(G4int Z, G4double e) const
619 {
620   // Select randomly a shell, according to the weight determined by the cross sections
621   // in the data set
622   // Note for later improvement: it would be useful to add a cache mechanism for already
623   // used shells to improve performance
624   G4int shell = 0;
625 
626   G4double totCrossSection = FindValue(Z,e);
627   G4double random = G4UniformRand() * totCrossSection;
628   G4double partialSum = 0.;
629 
630   G4VEMDataSet* dataSet = nullptr;
631   auto pos = dataMap.find(Z);
632   if (pos != dataMap.end()) 
633     dataSet = (*pos).second;
634   else
635     {
636       G4Exception("G4VCrossSectionHandler::SelectRandomShell",
637         "em1011",FatalException,"unable to load the dataSet");
638       return 0;
639     }
640 
641   G4int nShells = (G4int)dataSet->NumberOfComponents();
642   for (G4int i=0; i<nShells; ++i)
643     {
644       const G4VEMDataSet* shellDataSet = dataSet->GetComponent(i);
645       if (shellDataSet != nullptr)
646   {
647     G4double value = shellDataSet->FindValue(e);
648     partialSum += value;
649     if (random <= partialSum) return i;
650   }
651     }
652   // It should never get here
653   return shell;
654 }
655 
656 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
657 
658 void G4VCrossSectionHandler::ActiveElements()
659 {
660   const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
661   if (materialTable == nullptr)
662       G4Exception("G4VCrossSectionHandler::ActiveElements",
663         "em1001",FatalException,"no MaterialTable found");
664 
665   std::size_t nMaterials = G4Material::GetNumberOfMaterials();
666 
667   for (std::size_t mLocal2=0; mLocal2<nMaterials; ++mLocal2)
668     {
669       const G4Material* material= (*materialTable)[mLocal2];
670       const G4ElementVector* elementVector = material->GetElementVector();
671       const std::size_t nElements = material->GetNumberOfElements();
672 
673       for (std::size_t iEl=0; iEl<nElements; ++iEl)
674   {
675     G4double Z = (*elementVector)[iEl]->GetZ();
676     if (!(activeZ.contains(Z)) && Z >= zMin && Z <= zMax)
677       {
678         activeZ.push_back(Z);
679       }
680   }
681     }
682 }
683 
684 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
685 
686 G4VDataSetAlgorithm* G4VCrossSectionHandler::CreateInterpolation()
687 {
688   G4VDataSetAlgorithm* algorithm = new G4LogLogInterpolation;
689   return algorithm;
690 }
691 
692 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
693 
694 G4int G4VCrossSectionHandler::NumberOfComponents(G4int Z) const
695 {
696   G4int n = 0;
697 
698   auto pos = dataMap.find(Z);
699   if (pos!= dataMap.end())
700     {
701       G4VEMDataSet* dataSet = (*pos).second;
702       n = (G4int)dataSet->NumberOfComponents();
703     }
704   else
705     {
706       G4cout << "WARNING: G4VCrossSectionHandler::NumberOfComponents did not "
707              << "find Z = "
708              << Z << G4endl;
709     }
710   return n;
711 }
712 
713 
714