00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "G4VCrossSectionHandler.hh"
00043 #include "G4VDataSetAlgorithm.hh"
00044 #include "G4LogLogInterpolation.hh"
00045 #include "G4VEMDataSet.hh"
00046 #include "G4EMDataSet.hh"
00047 #include "G4CompositeEMDataSet.hh"
00048 #include "G4ShellEMDataSet.hh"
00049 #include "G4ProductionCutsTable.hh"
00050 #include "G4Material.hh"
00051 #include "G4Element.hh"
00052 #include "Randomize.hh"
00053 #include <map>
00054 #include <vector>
00055 #include <fstream>
00056 #include <sstream>
00057
00058
00059 G4VCrossSectionHandler::G4VCrossSectionHandler()
00060 {
00061 crossSections = 0;
00062 interpolation = 0;
00063 Initialise();
00064 ActiveElements();
00065 }
00066
00067
00068 G4VCrossSectionHandler::G4VCrossSectionHandler(G4VDataSetAlgorithm* algorithm,
00069 G4double minE,
00070 G4double maxE,
00071 G4int bins,
00072 G4double unitE,
00073 G4double unitData,
00074 G4int minZ,
00075 G4int maxZ)
00076 : interpolation(algorithm), eMin(minE), eMax(maxE), nBins(bins),
00077 unit1(unitE), unit2(unitData), zMin(minZ), zMax(maxZ)
00078 {
00079 crossSections = 0;
00080 ActiveElements();
00081 }
00082
00083 G4VCrossSectionHandler::~G4VCrossSectionHandler()
00084 {
00085 delete interpolation;
00086 interpolation = 0;
00087 std::map<G4int,G4VEMDataSet*,std::less<G4int> >::iterator pos;
00088
00089 for (pos = dataMap.begin(); pos != dataMap.end(); ++pos)
00090 {
00091
00092
00093
00094
00095 G4VEMDataSet* dataSet = (*pos).second;
00096 delete dataSet;
00097 }
00098
00099 if (crossSections != 0)
00100 {
00101 size_t n = crossSections->size();
00102 for (size_t i=0; i<n; i++)
00103 {
00104 delete (*crossSections)[i];
00105 }
00106 delete crossSections;
00107 crossSections = 0;
00108 }
00109 }
00110
00111 void G4VCrossSectionHandler::Initialise(G4VDataSetAlgorithm* algorithm,
00112 G4double minE, G4double maxE,
00113 G4int numberOfBins,
00114 G4double unitE, G4double unitData,
00115 G4int minZ, G4int maxZ)
00116 {
00117 if (algorithm != 0)
00118 {
00119 delete interpolation;
00120 interpolation = algorithm;
00121 }
00122 else
00123 {
00124 interpolation = CreateInterpolation();
00125 }
00126
00127 eMin = minE;
00128 eMax = maxE;
00129 nBins = numberOfBins;
00130 unit1 = unitE;
00131 unit2 = unitData;
00132 zMin = minZ;
00133 zMax = maxZ;
00134 }
00135
00136 void G4VCrossSectionHandler::PrintData() const
00137 {
00138 std::map<G4int,G4VEMDataSet*,std::less<G4int> >::const_iterator pos;
00139
00140 for (pos = dataMap.begin(); pos != dataMap.end(); pos++)
00141 {
00142
00143
00144
00145
00146
00147 G4int z = (*pos).first;
00148 G4VEMDataSet* dataSet = (*pos).second;
00149 G4cout << "---- Data set for Z = "
00150 << z
00151 << G4endl;
00152 dataSet->PrintData();
00153 G4cout << "--------------------------------------------------" << G4endl;
00154 }
00155 }
00156
00157 void G4VCrossSectionHandler::LoadData(const G4String& fileName)
00158 {
00159 size_t nZ = activeZ.size();
00160 for (size_t i=0; i<nZ; i++)
00161 {
00162 G4int Z = (G4int) activeZ[i];
00163
00164
00165
00166 char* path = getenv("G4LEDATA");
00167 if (!path)
00168 {
00169 G4String excep = "G4VCrossSectionHandler - G4LEDATA environment variable not set";
00170 G4Exception(excep);
00171 }
00172
00173 std::ostringstream ost;
00174 ost << path << '/' << fileName << Z << ".dat";
00175 std::ifstream file(ost.str().c_str());
00176 std::filebuf* lsdp = file.rdbuf();
00177
00178 if (! (lsdp->is_open()) )
00179 {
00180 G4String excep = "G4VCrossSectionHandler - data file: " + ost.str() + " not found";
00181 G4Exception(excep);
00182 }
00183 G4double a = 0;
00184 G4int k = 1;
00185 G4DataVector* energies = new G4DataVector;
00186 G4DataVector* data = new G4DataVector;
00187 do
00188 {
00189 file >> a;
00190 G4int nColumns = 2;
00191
00192
00193
00194
00195
00196 if (a == -1 || a == -2)
00197 {
00198 }
00199 else
00200 {
00201 if (k%nColumns != 0)
00202 {
00203 G4double e = a * unit1;
00204 energies->push_back(e);
00205 k++;
00206 }
00207 else if (k%nColumns == 0)
00208 {
00209 G4double value = a * unit2;
00210 data->push_back(value);
00211 k = 1;
00212 }
00213 }
00214 } while (a != -2);
00215
00216 file.close();
00217 G4VDataSetAlgorithm* algo = interpolation->Clone();
00218 G4VEMDataSet* dataSet = new G4EMDataSet(Z,energies,data,algo);
00219 dataMap[Z] = dataSet;
00220 }
00221 }
00222
00223 void G4VCrossSectionHandler::LoadShellData(const G4String& fileName)
00224 {
00225 size_t nZ = activeZ.size();
00226 for (size_t i=0; i<nZ; i++)
00227 {
00228 G4int Z = (G4int) activeZ[i];
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 char* path = getenv("G4LEDATA");
00239 if (!path)
00240 {
00241 G4String excep = "G4VCrossSectionHandler - G4LEDATA environment variable not set";
00242 G4Exception(excep);
00243 }
00244
00245 std::ostringstream ost;
00246
00247 ost << path << '/' << fileName << Z << ".dat";
00248
00249 std::ifstream file(ost.str().c_str());
00250 std::filebuf* lsdp = file.rdbuf();
00251
00252 if (! (lsdp->is_open()) )
00253 {
00254 G4String excep = "G4VCrossSectionHandler - data file: " + ost.str() + " not found";
00255 G4Exception(excep);
00256 }
00257 G4double a = 0;
00258 G4int k = 1;
00259 G4DataVector* energies = new G4DataVector;
00260 G4DataVector* data = new G4DataVector;
00261 do
00262 {
00263 file >> a;
00264 G4int nColumns = 2;
00265
00266
00267
00268
00269
00270 if (a == -1 || a == -2)
00271 {
00272 }
00273 else
00274 {
00275 if (k%nColumns != 0)
00276 {
00277 G4double e = a * unit1;
00278 energies->push_back(e);
00279 k++;
00280 }
00281 else if (k%nColumns == 0)
00282 {
00283 G4double value = a * unit2;
00284 data->push_back(value);
00285 k = 1;
00286 }
00287 }
00288 } while (a != -2);
00289
00290 file.close();
00291
00292
00293
00294
00295 G4VDataSetAlgorithm* algo = interpolation->Clone();
00296 G4VEMDataSet* dataSet = new G4ShellEMDataSet(Z, algo);
00297 dataSet->LoadData(fileName);
00298 dataMap[Z] = dataSet;
00299 }
00300 }
00301
00302 void G4VCrossSectionHandler::Clear()
00303 {
00304
00305 std::map<G4int,G4VEMDataSet*,std::less<G4int> >::iterator pos;
00306
00307 if(! dataMap.empty())
00308 {
00309 for (pos = dataMap.begin(); pos != dataMap.end(); ++pos)
00310 {
00311
00312
00313
00314
00315 G4VEMDataSet* dataSet = (*pos).second;
00316 delete dataSet;
00317 dataSet = 0;
00318 G4int i = (*pos).first;
00319 dataMap[i] = 0;
00320 }
00321 dataMap.clear();
00322 }
00323
00324 activeZ.clear();
00325 ActiveElements();
00326 }
00327
00328 G4double G4VCrossSectionHandler::FindValue(G4int Z, G4double energy) const
00329 {
00330 G4double value = 0.;
00331
00332 std::map<G4int,G4VEMDataSet*,std::less<G4int> >::const_iterator pos;
00333 pos = dataMap.find(Z);
00334 if (pos!= dataMap.end())
00335 {
00336
00337
00338
00339
00340 G4VEMDataSet* dataSet = (*pos).second;
00341 value = dataSet->FindValue(energy);
00342 }
00343 else
00344 {
00345 G4cout << "WARNING: G4VCrossSectionHandler::FindValue did not find Z = "
00346 << Z << G4endl;
00347 }
00348 return value;
00349 }
00350
00351 G4double G4VCrossSectionHandler::FindValue(G4int Z, G4double energy,
00352 G4int shellIndex) const
00353 {
00354 G4double value = 0.;
00355
00356 std::map<G4int,G4VEMDataSet*,std::less<G4int> >::const_iterator pos;
00357 pos = dataMap.find(Z);
00358 if (pos!= dataMap.end())
00359 {
00360
00361
00362
00363
00364 G4VEMDataSet* dataSet = (*pos).second;
00365 if (shellIndex >= 0)
00366 {
00367 G4int nComponents = dataSet->NumberOfComponents();
00368 if(shellIndex < nComponents)
00369
00370 value = dataSet->GetComponent(shellIndex)->FindValue(energy);
00371 else
00372 {
00373 G4cout << "WARNING: G4VCrossSectionHandler::FindValue did not find"
00374 << " shellIndex= " << shellIndex
00375 << " for Z= "
00376 << Z << G4endl;
00377 }
00378 } else {
00379 value = dataSet->FindValue(energy);
00380 }
00381 }
00382 else
00383 {
00384 G4cout << "WARNING: G4VCrossSectionHandler::FindValue did not find Z = "
00385 << Z << G4endl;
00386 }
00387 return value;
00388 }
00389
00390
00391 G4double G4VCrossSectionHandler::ValueForMaterial(const G4Material* material,
00392 G4double energy) const
00393 {
00394 G4double value = 0.;
00395
00396 const G4ElementVector* elementVector = material->GetElementVector();
00397 const G4double* nAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
00398 G4int nElements = material->GetNumberOfElements();
00399
00400 for (G4int i=0 ; i<nElements ; i++)
00401 {
00402 G4int Z = (G4int) (*elementVector)[i]->GetZ();
00403 G4double elementValue = FindValue(Z,energy);
00404 G4double nAtomsVol = nAtomsPerVolume[i];
00405 value += nAtomsVol * elementValue;
00406 }
00407
00408 return value;
00409 }
00410
00411
00412 G4VEMDataSet* G4VCrossSectionHandler::BuildMeanFreePathForMaterials(const G4DataVector* energyCuts)
00413 {
00414
00415
00416
00417 G4DataVector energyVector;
00418 G4double dBin = std::log10(eMax/eMin) / nBins;
00419
00420 for (G4int i=0; i<nBins+1; i++)
00421 {
00422 energyVector.push_back(std::pow(10., std::log10(eMin)+i*dBin));
00423 }
00424
00425
00426
00427
00428 if (crossSections != 0)
00429 {
00430 std::vector<G4VEMDataSet*>::iterator mat;
00431 if (! crossSections->empty())
00432 {
00433 for (mat = crossSections->begin(); mat!= crossSections->end(); ++mat)
00434 {
00435 G4VEMDataSet* set = *mat;
00436 delete set;
00437 set = 0;
00438 }
00439 crossSections->clear();
00440 delete crossSections;
00441 crossSections = 0;
00442 }
00443 }
00444
00445 crossSections = BuildCrossSectionsForMaterials(energyVector,energyCuts);
00446
00447 if (crossSections == 0)
00448 G4Exception("G4VCrossSectionHandler::BuildMeanFreePathForMaterials, crossSections = 0");
00449
00450 G4VDataSetAlgorithm* algo = CreateInterpolation();
00451 G4VEMDataSet* materialSet = new G4CompositeEMDataSet(algo);
00452
00453 G4DataVector* energies;
00454 G4DataVector* data;
00455
00456 const G4ProductionCutsTable* theCoupleTable=
00457 G4ProductionCutsTable::GetProductionCutsTable();
00458 size_t numOfCouples = theCoupleTable->GetTableSize();
00459
00460
00461 for (size_t m=0; m<numOfCouples; m++)
00462 {
00463 energies = new G4DataVector;
00464 data = new G4DataVector;
00465 for (G4int bin=0; bin<nBins; bin++)
00466 {
00467 G4double energy = energyVector[bin];
00468 energies->push_back(energy);
00469 G4VEMDataSet* matCrossSet = (*crossSections)[m];
00470 G4double materialCrossSection = 0.0;
00471 G4int nElm = matCrossSet->NumberOfComponents();
00472 for(G4int j=0; j<nElm; j++) {
00473 materialCrossSection += matCrossSet->GetComponent(j)->FindValue(energy);
00474 }
00475
00476 if (materialCrossSection > 0.)
00477 {
00478 data->push_back(1./materialCrossSection);
00479 }
00480 else
00481 {
00482 data->push_back(DBL_MAX);
00483 }
00484 }
00485 G4VDataSetAlgorithm* algo = CreateInterpolation();
00486 G4VEMDataSet* dataSet = new G4EMDataSet(m,energies,data,algo,1.,1.);
00487 materialSet->AddComponent(dataSet);
00488 }
00489
00490 return materialSet;
00491 }
00492
00493 G4int G4VCrossSectionHandler::SelectRandomAtom(const G4MaterialCutsCouple* couple,
00494 G4double e) const
00495 {
00496
00497
00498
00499 const G4Material* material = couple->GetMaterial();
00500 G4int nElements = material->GetNumberOfElements();
00501
00502
00503 if (nElements == 1)
00504 {
00505 G4int Z = (G4int) material->GetZ();
00506 return Z;
00507 }
00508
00509
00510
00511 const G4ElementVector* elementVector = material->GetElementVector();
00512 size_t materialIndex = couple->GetIndex();
00513
00514 G4VEMDataSet* materialSet = (*crossSections)[materialIndex];
00515 G4double materialCrossSection0 = 0.0;
00516 G4DataVector cross;
00517 cross.clear();
00518 for ( G4int i=0; i < nElements; i++ )
00519 {
00520 G4double cr = materialSet->GetComponent(i)->FindValue(e);
00521 materialCrossSection0 += cr;
00522 cross.push_back(materialCrossSection0);
00523 }
00524
00525 G4double random = G4UniformRand() * materialCrossSection0;
00526
00527 for (G4int k=0 ; k < nElements ; k++ )
00528 {
00529 if (random <= cross[k]) return (G4int) (*elementVector)[k]->GetZ();
00530 }
00531
00532 return 0;
00533 }
00534
00535 const G4Element* G4VCrossSectionHandler::SelectRandomElement(const G4MaterialCutsCouple* couple,
00536 G4double e) const
00537 {
00538
00539
00540
00541 const G4Material* material = couple->GetMaterial();
00542 G4Element* nullElement = 0;
00543 G4int nElements = material->GetNumberOfElements();
00544 const G4ElementVector* elementVector = material->GetElementVector();
00545
00546
00547 if (nElements == 1)
00548 {
00549 G4Element* element = (*elementVector)[0];
00550 return element;
00551 }
00552 else
00553 {
00554
00555
00556 size_t materialIndex = couple->GetIndex();
00557
00558 G4VEMDataSet* materialSet = (*crossSections)[materialIndex];
00559 G4double materialCrossSection0 = 0.0;
00560 G4DataVector cross;
00561 cross.clear();
00562 for (G4int i=0; i<nElements; i++)
00563 {
00564 G4double cr = materialSet->GetComponent(i)->FindValue(e);
00565 materialCrossSection0 += cr;
00566 cross.push_back(materialCrossSection0);
00567 }
00568
00569 G4double random = G4UniformRand() * materialCrossSection0;
00570
00571 for (G4int k=0 ; k < nElements ; k++ )
00572 {
00573 if (random <= cross[k]) return (*elementVector)[k];
00574 }
00575
00576 G4cout << "G4VCrossSectionHandler::SelectRandomElement - no element found" << G4endl;
00577 return nullElement;
00578 }
00579 }
00580
00581 G4int G4VCrossSectionHandler::SelectRandomShell(G4int Z, G4double e) const
00582 {
00583
00584
00585
00586
00587
00588
00589 G4int shell = 0;
00590
00591 G4double totCrossSection = FindValue(Z,e);
00592 G4double random = G4UniformRand() * totCrossSection;
00593 G4double partialSum = 0.;
00594
00595 G4VEMDataSet* dataSet = 0;
00596 std::map<G4int,G4VEMDataSet*,std::less<G4int> >::const_iterator pos;
00597 pos = dataMap.find(Z);
00598
00599
00600
00601
00602 if (pos != dataMap.end()) dataSet = (*pos).second;
00603
00604 size_t nShells = dataSet->NumberOfComponents();
00605 for (size_t i=0; i<nShells; i++)
00606 {
00607 const G4VEMDataSet* shellDataSet = dataSet->GetComponent(i);
00608 if (shellDataSet != 0)
00609 {
00610 G4double value = shellDataSet->FindValue(e);
00611 partialSum += value;
00612 if (random <= partialSum) return i;
00613 }
00614 }
00615
00616 return shell;
00617 }
00618
00619 void G4VCrossSectionHandler::ActiveElements()
00620 {
00621 const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
00622 if (materialTable == 0)
00623 G4Exception("G4VCrossSectionHandler::ActiveElements - no MaterialTable found)");
00624
00625 G4int nMaterials = G4Material::GetNumberOfMaterials();
00626
00627 for (G4int m=0; m<nMaterials; m++)
00628 {
00629 const G4Material* material= (*materialTable)[m];
00630 const G4ElementVector* elementVector = material->GetElementVector();
00631 const G4int nElements = material->GetNumberOfElements();
00632
00633 for (G4int iEl=0; iEl<nElements; iEl++)
00634 {
00635 G4Element* element = (*elementVector)[iEl];
00636 G4double Z = element->GetZ();
00637 if (!(activeZ.contains(Z)) && Z >= zMin && Z <= zMax)
00638 {
00639 activeZ.push_back(Z);
00640 }
00641 }
00642 }
00643 }
00644
00645 G4VDataSetAlgorithm* G4VCrossSectionHandler::CreateInterpolation()
00646 {
00647 G4VDataSetAlgorithm* algorithm = new G4LogLogInterpolation;
00648 return algorithm;
00649 }
00650
00651 G4int G4VCrossSectionHandler::NumberOfComponents(G4int Z) const
00652 {
00653 G4int n = 0;
00654
00655 std::map<G4int,G4VEMDataSet*,std::less<G4int> >::const_iterator pos;
00656 pos = dataMap.find(Z);
00657 if (pos!= dataMap.end())
00658 {
00659 G4VEMDataSet* dataSet = (*pos).second;
00660 n = dataSet->NumberOfComponents();
00661 }
00662 else
00663 {
00664 G4cout << "WARNING: G4VCrossSectionHandler::NumberOfComponents did not "
00665 << "find Z = "
00666 << Z << G4endl;
00667 }
00668 return n;
00669 }
00670
00671