Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 09:22:08

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 //
0027 //
0028 // Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
0029 //
0030 // History:
0031 // -----------
0032 // 1  Aug 2001   MGP        Created
0033 // 09 Oct 2001   VI         Add FindValue with 3 parameters 
0034 //                          + NumberOfComponents
0035 // 19 Jul 2002   VI         Create composite data set for material
0036 // 21 Jan 2003   VI         Cut per region
0037 //
0038 // -------------------------------------------------------------------
0039 
0040 #include "G4RDVCrossSectionHandler.hh"
0041 #include "G4RDVDataSetAlgorithm.hh"
0042 #include "G4RDLogLogInterpolation.hh"
0043 #include "G4RDVEMDataSet.hh"
0044 #include "G4RDEMDataSet.hh"
0045 #include "G4RDCompositeEMDataSet.hh"
0046 #include "G4RDShellEMDataSet.hh"
0047 #include "G4ProductionCutsTable.hh"
0048 #include "G4Material.hh"
0049 #include "G4Element.hh"
0050 #include "Randomize.hh"
0051 #include <map>
0052 #include <vector>
0053 #include <fstream>
0054 #include <sstream>
0055 
0056 
0057 G4RDVCrossSectionHandler::G4RDVCrossSectionHandler()
0058 {
0059   crossSections = 0;
0060   interpolation = 0;
0061   Initialise();
0062   ActiveElements();
0063 }
0064 
0065 
0066 G4RDVCrossSectionHandler::G4RDVCrossSectionHandler(G4RDVDataSetAlgorithm* algorithm,
0067                            G4double minE,
0068                            G4double maxE,
0069                            G4int bins,
0070                            G4double unitE,
0071                            G4double unitData,
0072                            G4int minZ, 
0073                            G4int maxZ)
0074   : interpolation(algorithm), eMin(minE), eMax(maxE), nBins(bins),
0075     unit1(unitE), unit2(unitData), zMin(minZ), zMax(maxZ)
0076 {
0077   crossSections = 0;
0078   ActiveElements();
0079 }
0080 
0081 G4RDVCrossSectionHandler::~G4RDVCrossSectionHandler()
0082 {
0083   delete interpolation;
0084   interpolation = 0;
0085   std::map<G4int,G4RDVEMDataSet*,std::less<G4int> >::iterator pos;
0086 
0087   for (pos = dataMap.begin(); pos != dataMap.end(); ++pos)
0088     {
0089       // The following is a workaround for STL ObjectSpace implementation, 
0090       // which does not support the standard and does not accept 
0091       // the syntax pos->second
0092       // G4RDVEMDataSet* dataSet = pos->second;
0093       G4RDVEMDataSet* dataSet = (*pos).second;
0094       delete dataSet;
0095     }
0096 
0097   if (crossSections != 0)
0098     {
0099       size_t n = crossSections->size();
0100       for (size_t i=0; i<n; i++)
0101     {
0102       delete (*crossSections)[i];
0103     }
0104       delete crossSections;
0105       crossSections = 0;
0106     }
0107 }
0108 
0109 void G4RDVCrossSectionHandler::Initialise(G4RDVDataSetAlgorithm* algorithm,
0110                     G4double minE, G4double maxE, 
0111                     G4int numberOfBins,
0112                     G4double unitE, G4double unitData,
0113                     G4int minZ, G4int maxZ)
0114 {
0115   if (algorithm != 0) 
0116     {
0117       delete interpolation;
0118       interpolation = algorithm;
0119     }
0120   else
0121     {
0122       interpolation = CreateInterpolation();
0123     }
0124 
0125   eMin = minE;
0126   eMax = maxE;
0127   nBins = numberOfBins;
0128   unit1 = unitE;
0129   unit2 = unitData;
0130   zMin = minZ;
0131   zMax = maxZ;
0132 }
0133 
0134 void G4RDVCrossSectionHandler::PrintData() const
0135 {
0136   std::map<G4int,G4RDVEMDataSet*,std::less<G4int> >::const_iterator pos;
0137 
0138   for (pos = dataMap.begin(); pos != dataMap.end(); pos++)
0139     {
0140       // The following is a workaround for STL ObjectSpace implementation, 
0141       // which does not support the standard and does not accept 
0142       // the syntax pos->first or pos->second
0143       // G4int z = pos->first;
0144       // G4RDVEMDataSet* dataSet = pos->second;
0145       G4int z = (*pos).first;
0146       G4RDVEMDataSet* dataSet = (*pos).second;     
0147       G4cout << "---- Data set for Z = "
0148          << z
0149          << G4endl;
0150       dataSet->PrintData();
0151       G4cout << "--------------------------------------------------" << G4endl;
0152     }
0153 }
0154 
0155 void G4RDVCrossSectionHandler::LoadData(const G4String& fileName)
0156 {
0157   size_t nZ = activeZ.size();
0158   for (size_t i=0; i<nZ; i++)
0159     {
0160       G4int Z = (G4int) activeZ[i];
0161 
0162       // Build the complete string identifying the file with the data set
0163       
0164       const char* path = G4FindDataDir("G4LEDATA");
0165       if (!path)
0166     { 
0167       G4String excep = "G4LEDATA environment variable not set!";
0168       G4Exception("G4RDVCrossSectionHandler::LoadData()",
0169                       "InvalidSetup", FatalException, excep);
0170     }
0171       
0172       std::ostringstream ost;
0173       ost << path << '/' << fileName << Z << ".dat";
0174       std::ifstream file(ost.str().c_str());
0175       std::filebuf* lsdp = file.rdbuf();
0176       
0177       if (! (lsdp->is_open()) )
0178     {
0179       G4String excep = "Data file: " + ost.str() + " not found!";
0180       G4Exception("G4RDVCrossSectionHandler::LoadData()",
0181                       "DataNotFound", FatalException, excep);
0182     }
0183       G4double a = 0;
0184       G4int k = 1;
0185       G4DataVector* energies = new G4DataVector;
0186       G4DataVector* data = new G4DataVector;
0187       do
0188     {
0189       file >> a;
0190       G4int nColumns = 2;
0191       // The file is organized into two columns:
0192       // 1st column is the energy
0193       // 2nd column is the corresponding value
0194       // The file terminates with the pattern: -1   -1
0195       //                                       -2   -2
0196       if (a == -1 || a == -2)
0197         {
0198         }
0199       else
0200         {
0201           if (k%nColumns != 0)
0202         {   
0203           G4double e = a * unit1;
0204           energies->push_back(e);
0205           k++;
0206         }
0207           else if (k%nColumns == 0)
0208         {
0209           G4double value = a * unit2;
0210           data->push_back(value);
0211           k = 1;
0212         }
0213         }
0214     } while (a != -2); // end of file
0215       
0216       file.close();
0217       G4RDVDataSetAlgorithm* algo = interpolation->Clone();
0218       G4RDVEMDataSet* dataSet = new G4RDEMDataSet(Z,energies,data,algo);
0219       dataMap[Z] = dataSet;
0220     }
0221 }
0222 
0223 void G4RDVCrossSectionHandler::LoadShellData(const G4String& fileName)
0224 {
0225   size_t nZ = activeZ.size();
0226   for (size_t i=0; i<nZ; i++)
0227     {
0228       G4int Z = (G4int) activeZ[i];
0229       
0230       // Riccardo Capra <capra@ge.infn.it>: PLEASE CHECK THE FOLLOWING PIECE OF CODE
0231       // "energies" AND "data" G4DataVector ARE ALLOCATED, FILLED IN AND NEVER USED OR
0232       // DELETED. WHATSMORE LOADING FILE OPERATIONS WERE DONE BY G4RDShellEMDataSet
0233       // EVEN BEFORE THE CHANGES I DID ON THIS FILE. SO THE FOLLOWING CODE IN MY
0234       // OPINION SHOULD BE USELESS AND SHOULD PRODUCE A MEMORY LEAK. 
0235 
0236       // Build the complete string identifying the file with the data set
0237       
0238       const char* path = G4FindDataDir("G4LEDATA");
0239       if (!path)
0240     { 
0241       G4String excep = "G4LEDATA environment variable not set!";
0242       G4Exception("G4RDVCrossSectionHandler::LoadShellData()",
0243                       "InvalidSetup", FatalException, excep);
0244     }
0245       
0246       std::ostringstream ost;
0247 
0248       ost << path << '/' << fileName << Z << ".dat";
0249       
0250       std::ifstream file(ost.str().c_str());
0251       std::filebuf* lsdp = file.rdbuf();
0252       
0253       if (! (lsdp->is_open()) )
0254     {
0255       G4String excep = "Data file: " + ost.str() + " not found!";
0256       G4Exception("G4RDVCrossSectionHandler::LoadShellData()",
0257                       "DataNotFound", FatalException, excep);
0258     }
0259       G4double a = 0;
0260       G4int k = 1;
0261       G4DataVector* energies = new G4DataVector;
0262       G4DataVector* data = new G4DataVector;
0263       do
0264     {
0265       file >> a;
0266       G4int nColumns = 2;
0267       // The file is organized into two columns:
0268       // 1st column is the energy
0269       // 2nd column is the corresponding value
0270       // The file terminates with the pattern: -1   -1
0271       //                                       -2   -2
0272       if (a == -1 || a == -2)
0273         {
0274         }
0275       else
0276         {
0277           if (k%nColumns != 0)
0278         {   
0279           G4double e = a * unit1;
0280           energies->push_back(e);
0281           k++;
0282         }
0283           else if (k%nColumns == 0)
0284         {
0285           G4double value = a * unit2;
0286           data->push_back(value);
0287           k = 1;
0288         }
0289         }
0290     } while (a != -2); // end of file
0291       
0292       file.close();
0293       
0294       // Riccardo Capra <capra@ge.infn.it>: END OF CODE THAT IN MY OPINION SHOULD BE
0295       // REMOVED.
0296       
0297       G4RDVDataSetAlgorithm* algo = interpolation->Clone();
0298       G4RDVEMDataSet* dataSet = new G4RDShellEMDataSet(Z, algo);
0299       dataSet->LoadData(fileName);
0300       dataMap[Z] = dataSet;
0301     }
0302 }
0303 
0304 void G4RDVCrossSectionHandler::Clear()
0305 {
0306   // Reset the map of data sets: remove the data sets from the map 
0307   std::map<G4int,G4RDVEMDataSet*,std::less<G4int> >::iterator pos;
0308 
0309   if(! dataMap.empty())
0310     {
0311         for (pos = dataMap.begin(); pos != dataMap.end(); ++pos)
0312     {
0313       // The following is a workaround for STL ObjectSpace implementation, 
0314       // which does not support the standard and does not accept
0315       // the syntax pos->first or pos->second
0316       // G4RDVEMDataSet* dataSet = pos->second;
0317       G4RDVEMDataSet* dataSet = (*pos).second;
0318       delete dataSet;
0319       dataSet = 0;
0320       G4int i = (*pos).first;
0321       dataMap[i] = 0;
0322     }
0323     dataMap.clear();
0324     }
0325 
0326   activeZ.clear();
0327   ActiveElements();
0328 }
0329 
0330 G4double G4RDVCrossSectionHandler::FindValue(G4int Z, G4double energy) const
0331 {
0332   G4double value = 0.;
0333   
0334   std::map<G4int,G4RDVEMDataSet*,std::less<G4int> >::const_iterator pos;
0335   pos = dataMap.find(Z);
0336   if (pos!= dataMap.end())
0337     {
0338       // The following is a workaround for STL ObjectSpace implementation, 
0339       // which does not support the standard and does not accept 
0340       // the syntax pos->first or pos->second
0341       // G4RDVEMDataSet* dataSet = pos->second;
0342       G4RDVEMDataSet* dataSet = (*pos).second;
0343       value = dataSet->FindValue(energy);
0344     }
0345   else
0346     {
0347       G4cout << "WARNING: G4RDVCrossSectionHandler::FindValue did not find Z = "
0348          << Z << G4endl;
0349     }
0350   return value;
0351 }
0352 
0353 G4double G4RDVCrossSectionHandler::FindValue(G4int Z, G4double energy, 
0354                                            G4int shellIndex) const
0355 {
0356   G4double value = 0.;
0357 
0358   std::map<G4int,G4RDVEMDataSet*,std::less<G4int> >::const_iterator pos;
0359   pos = dataMap.find(Z);
0360   if (pos!= dataMap.end())
0361     {
0362       // The following is a workaround for STL ObjectSpace implementation, 
0363       // which does not support the standard and does not accept 
0364       // the syntax pos->first or pos->second
0365       // G4RDVEMDataSet* dataSet = pos->second;
0366       G4RDVEMDataSet* dataSet = (*pos).second;
0367       if (shellIndex >= 0) 
0368     {
0369       G4int nComponents = dataSet->NumberOfComponents();
0370       if(shellIndex < nComponents)    
0371         // - MGP - Why doesn't it use G4RDVEMDataSet::FindValue directly?
0372         value = dataSet->GetComponent(shellIndex)->FindValue(energy);
0373       else 
0374         {
0375           G4cout << "WARNING: G4RDVCrossSectionHandler::FindValue did not find"
0376              << " shellIndex= " << shellIndex
0377              << " for  Z= "
0378              << Z << G4endl;
0379         }
0380     } else {
0381       value = dataSet->FindValue(energy);
0382     }
0383     }
0384   else
0385     {
0386       G4cout << "WARNING: G4RDVCrossSectionHandler::FindValue did not find Z = "
0387          << Z << G4endl;
0388     }
0389   return value;
0390 }
0391 
0392 
0393 G4double G4RDVCrossSectionHandler::ValueForMaterial(const G4Material* material,
0394                           G4double energy) const
0395 {
0396   G4double value = 0.;
0397 
0398   const G4ElementVector* elementVector = material->GetElementVector();
0399   const G4double* nAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
0400   G4int nElements = material->GetNumberOfElements();
0401 
0402   for (G4int i=0 ; i<nElements ; i++)
0403     {
0404       G4int Z = (G4int) (*elementVector)[i]->GetZ();
0405       G4double elementValue = FindValue(Z,energy);
0406       G4double nAtomsVol = nAtomsPerVolume[i];
0407       value += nAtomsVol * elementValue;
0408     }
0409 
0410   return value;
0411 }
0412 
0413 
0414 G4RDVEMDataSet* G4RDVCrossSectionHandler::BuildMeanFreePathForMaterials(const G4DataVector* energyCuts)
0415 {
0416   // Builds a CompositeDataSet containing the mean free path for each material
0417   // in the material table
0418 
0419   G4DataVector energyVector;
0420   G4double dBin = std::log10(eMax/eMin) / nBins;
0421 
0422   for (G4int i=0; i<nBins+1; i++)
0423     {
0424       energyVector.push_back(std::pow(10., std::log10(eMin)+i*dBin));
0425     }
0426 
0427   // Factory method to build cross sections in derived classes,
0428   // related to the type of physics process
0429 
0430   if (crossSections != 0)
0431     {  // Reset the list of cross sections
0432       std::vector<G4RDVEMDataSet*>::iterator mat;
0433       if (! crossSections->empty())
0434     {
0435       for (mat = crossSections->begin(); mat!= crossSections->end(); ++mat)
0436         {
0437           G4RDVEMDataSet* set = *mat;
0438           delete set;
0439           set = 0;
0440         }
0441       crossSections->clear();
0442       delete crossSections;
0443       crossSections = 0;
0444     }
0445     }
0446 
0447   crossSections = BuildCrossSectionsForMaterials(energyVector,energyCuts);
0448 
0449   if (crossSections == 0)
0450     G4Exception("G4RDVCrossSectionHandler::BuildMeanFreePathForMaterials()",
0451                 "InvalidCondition", FatalException, "CrossSections = 0!");
0452 
0453   G4RDVDataSetAlgorithm* algo = CreateInterpolation();
0454   G4RDVEMDataSet* materialSet = new G4RDCompositeEMDataSet(algo);
0455 
0456   G4DataVector* energies;
0457   G4DataVector* data;
0458   
0459   const G4ProductionCutsTable* theCoupleTable=
0460         G4ProductionCutsTable::GetProductionCutsTable();
0461   size_t numOfCouples = theCoupleTable->GetTableSize();
0462 
0463 
0464   for (size_t m=0; m<numOfCouples; m++)
0465     {
0466       energies = new G4DataVector;
0467       data = new G4DataVector;
0468       for (G4int bin=0; bin<nBins; bin++)
0469     {
0470       G4double energy = energyVector[bin];
0471       energies->push_back(energy);
0472       G4RDVEMDataSet* matCrossSet = (*crossSections)[m];
0473       G4double materialCrossSection = 0.0;
0474           G4int nElm = matCrossSet->NumberOfComponents();
0475           for(G4int j=0; j<nElm; j++) {
0476             materialCrossSection += matCrossSet->GetComponent(j)->FindValue(energy);
0477       }
0478 
0479       if (materialCrossSection > 0.)
0480         {
0481           data->push_back(1./materialCrossSection);
0482         }
0483       else
0484         {
0485           data->push_back(DBL_MAX);
0486         }
0487     }
0488       G4RDVDataSetAlgorithm* algo = CreateInterpolation();
0489       G4RDVEMDataSet* dataSet = new G4RDEMDataSet(m,energies,data,algo,1.,1.);
0490       materialSet->AddComponent(dataSet);
0491     }
0492 
0493   return materialSet;
0494 }
0495 
0496 G4int G4RDVCrossSectionHandler::SelectRandomAtom(const G4MaterialCutsCouple* couple,
0497                                                      G4double e) const
0498 {
0499   // Select randomly an element within the material, according to the weight
0500   // determined by the cross sections in the data set
0501 
0502   const G4Material* material = couple->GetMaterial();
0503   G4int nElements = material->GetNumberOfElements();
0504 
0505   // Special case: the material consists of one element
0506   if (nElements == 1)
0507     {
0508       G4int Z = (G4int) material->GetZ();
0509       return Z;
0510     }
0511 
0512   // Composite material
0513 
0514   const G4ElementVector* elementVector = material->GetElementVector();
0515   size_t materialIndex = couple->GetIndex();
0516 
0517   G4RDVEMDataSet* materialSet = (*crossSections)[materialIndex];
0518   G4double materialCrossSection0 = 0.0;
0519   G4DataVector cross;
0520   cross.clear();
0521   for ( G4int i=0; i < nElements; i++ )
0522     {
0523       G4double cr = materialSet->GetComponent(i)->FindValue(e);
0524       materialCrossSection0 += cr;
0525       cross.push_back(materialCrossSection0);
0526     }
0527 
0528   G4double random = G4UniformRand() * materialCrossSection0;
0529 
0530   for (G4int k=0 ; k < nElements ; k++ )
0531     {
0532       if (random <= cross[k]) return (G4int) (*elementVector)[k]->GetZ();
0533     }
0534   // It should never get here
0535   return 0;
0536 }
0537 
0538 const G4Element* G4RDVCrossSectionHandler::SelectRandomElement(const G4MaterialCutsCouple* couple,
0539                                  G4double e) const
0540 {
0541   // Select randomly an element within the material, according to the weight determined
0542   // by the cross sections in the data set
0543 
0544   const G4Material* material = couple->GetMaterial();
0545   G4Element* nullElement = 0;
0546   G4int nElements = material->GetNumberOfElements();
0547   const G4ElementVector* elementVector = material->GetElementVector();
0548 
0549   // Special case: the material consists of one element
0550   if (nElements == 1)
0551     {
0552       G4Element* element = (*elementVector)[0];
0553       return element;
0554     }
0555   else
0556     {
0557       // Composite material
0558 
0559       size_t materialIndex = couple->GetIndex();
0560 
0561       G4RDVEMDataSet* materialSet = (*crossSections)[materialIndex];
0562       G4double materialCrossSection0 = 0.0;
0563       G4DataVector cross;
0564       cross.clear();
0565       for (G4int i=0; i<nElements; i++)
0566         {
0567           G4double cr = materialSet->GetComponent(i)->FindValue(e);
0568           materialCrossSection0 += cr;
0569           cross.push_back(materialCrossSection0);
0570         }
0571 
0572       G4double random = G4UniformRand() * materialCrossSection0;
0573 
0574       for (G4int k=0 ; k < nElements ; k++ )
0575         {
0576           if (random <= cross[k]) return (*elementVector)[k];
0577         }
0578       // It should never end up here
0579       G4cout << "G4RDVCrossSectionHandler::SelectRandomElement - no element found" << G4endl;
0580       return nullElement;
0581     }
0582 }
0583 
0584 G4int G4RDVCrossSectionHandler::SelectRandomShell(G4int Z, G4double e) const
0585 {
0586   // Select randomly a shell, according to the weight determined by the cross sections
0587   // in the data set
0588 
0589   // Note for later improvement: it would be useful to add a cache mechanism for already
0590   // used shells to improve performance
0591 
0592   G4int shell = 0;
0593 
0594   G4double totCrossSection = FindValue(Z,e);
0595   G4double random = G4UniformRand() * totCrossSection;
0596   G4double partialSum = 0.;
0597 
0598   G4RDVEMDataSet* dataSet = 0;
0599   std::map<G4int,G4RDVEMDataSet*,std::less<G4int> >::const_iterator pos;
0600   pos = dataMap.find(Z);
0601   // The following is a workaround for STL ObjectSpace implementation,
0602   // which does not support the standard and does not accept
0603   // the syntax pos->first or pos->second
0604   // if (pos != dataMap.end()) dataSet = pos->second;
0605   if (pos != dataMap.end()) dataSet = (*pos).second;
0606 
0607   size_t nShells = dataSet->NumberOfComponents();
0608   for (size_t i=0; i<nShells; i++)
0609     {
0610       const G4RDVEMDataSet* shellDataSet = dataSet->GetComponent(i);
0611       if (shellDataSet != 0)
0612     {
0613       G4double value = shellDataSet->FindValue(e);
0614       partialSum += value;
0615       if (random <= partialSum) return i;
0616     }
0617     }
0618   // It should never get here
0619   return shell;
0620 }
0621 
0622 void G4RDVCrossSectionHandler::ActiveElements()
0623 {
0624   const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
0625   if (materialTable == 0)
0626     G4Exception("G4RDVCrossSectionHandler::ActiveElements",
0627                 "InvalidSetup", FatalException, "No MaterialTable found!");
0628 
0629   G4int nMaterials = G4Material::GetNumberOfMaterials();
0630 
0631   for (G4int m=0; m<nMaterials; m++)
0632     {
0633       const G4Material* material= (*materialTable)[m];
0634       const G4ElementVector* elementVector = material->GetElementVector();
0635       const G4int nElements = material->GetNumberOfElements();
0636 
0637       for (G4int iEl=0; iEl<nElements; iEl++)
0638     {
0639       G4Element* element = (*elementVector)[iEl];
0640       G4double Z = element->GetZ();
0641       if (!(activeZ.contains(Z)) && Z >= zMin && Z <= zMax)
0642         {
0643           activeZ.push_back(Z);
0644         }
0645     }
0646     }
0647 }
0648 
0649 G4RDVDataSetAlgorithm* G4RDVCrossSectionHandler::CreateInterpolation()
0650 {
0651   G4RDVDataSetAlgorithm* algorithm = new G4RDLogLogInterpolation;
0652   return algorithm;
0653 }
0654 
0655 G4int G4RDVCrossSectionHandler::NumberOfComponents(G4int Z) const
0656 {
0657   G4int n = 0;
0658 
0659   std::map<G4int,G4RDVEMDataSet*,std::less<G4int> >::const_iterator pos;
0660   pos = dataMap.find(Z);
0661   if (pos!= dataMap.end())
0662     {
0663       G4RDVEMDataSet* dataSet = (*pos).second;
0664       n = dataSet->NumberOfComponents();
0665     }
0666   else
0667     {
0668       G4cout << "WARNING: G4RDVCrossSectionHandler::NumberOfComponents did not "
0669              << "find Z = "
0670              << Z << G4endl;
0671     }
0672   return n;
0673 }
0674 
0675