// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // #include "G4FastPathHadronicCrossSection.hh" #include "G4ios.hh" #include "G4DynamicParticle.hh" #include "G4Material.hh" #include "G4CrossSectionDataStore.hh" #include #if defined(WIN32) //Needed for M_LN10 #define _USE_MATH_DEFINES // for C++ #include #endif #include #include #ifdef FPDEBUG #define DBG( msg ) G4cout<< msg < & raw_data, std::vector & simplified_data); void RemoveBias( std::vector &, std::vector &, std::vector &); } fastPathEntry::fastPathEntry(const G4ParticleDefinition* part, const G4Material* mat, G4double min) : particle(part),material(mat),min_cutoff(min),physicsVector(nullptr) { DBG("Initializing a fastPathEntry"); #ifdef FPDEBUG count = 0; slowpath_sum=0.; max_delta=0.; min_delta=0.; sum_delta=0.; sum_delta_square=0.; #endif } fastPathEntry::~fastPathEntry() { DBG("Deleting fastPathEntry"); DBG("Dumping status for: "<<(particle?particle->GetParticleName():"PART_NONE")<<" "\ <<(material?material->GetName():"MAT_NONE")<<" min_cutoff:"<GetFastPathControlFlags().useFastPathIfAvailable && xsds->GetFastPathControlFlags().initializationPhase ); using std::log10; std::vector data_in; const fastPathParameters& params = xsds->GetFastPathParameters(); G4double xs; //G4double max_query = params.queryMax; //G4int count = sampleCount; //G4double tol = dpTol; //Shift so max and min are >= 1. //Don't forget to shift back before computing XS G4double min = params.sampleMin; G4double max = params.sampleMax; G4double shift = 0.0; if(min < 1.0){ shift = 1.0 - min; } min += shift; max += shift; G4double log_max = std::log10(params.sampleMax); G4double log_min = std::log10(params.sampleMin); G4double log_step = (log_max-log_min)/(1.0*params.sampleCount); G4double max_xs = 0.0; //Utility particle to calculate XS, with 0 kin energy by default static const G4ThreeVector constDirection(0.,0.,1.); G4DynamicParticle* probingParticle = new G4DynamicParticle( particle , constDirection , 0 ); //add the cutoff energy probingParticle->SetKineticEnergy(min_cutoff); //Sample cross-section xs = xsds->GetCrossSection(probingParticle,material); data_in.push_back({min_cutoff,xs}); G4double currEnergy = 0.0; //log results auto exp10 = [](G4double x){ return std::exp( M_LN10*x); }; for(G4double log_currEnergy = log_min; log_currEnergy < log_max; log_currEnergy += log_step){ currEnergy = exp10(log_currEnergy) - shift; if (currEnergy < min_cutoff) continue; probingParticle->SetKineticEnergy(currEnergy); xs=xsds->GetCrossSection(probingParticle,material); //G4cout << "PRUTH: energy value " << currEnergy << ", XS value " << xs << G4endl; if (xs > max_xs) max_xs = xs; data_in.push_back({currEnergy,xs}); } // --- end of loop i probingParticle->SetKineticEnergy(max-shift); xs = xsds->GetCrossSection(probingParticle,material); data_in.push_back({max-shift,xs}); G4double tol = max_xs * 0.01; std::vector decimated_data; simplify_function(tol, data_in, decimated_data); std::vector debiased_data; RemoveBias( data_in, decimated_data, debiased_data); if ( physicsVector != nullptr ) delete physicsVector; physicsVector = new XSParam(decimated_data.size()); G4int physicsVectorIndex = 0; for(size_t i = 0; i < decimated_data.size(); i++){ physicsVector->PutValue(physicsVectorIndex++, decimated_data[i].e, decimated_data[i].xs); } //xsds->DumpFastPath(particle,material,G4cout); } cycleCountEntry::cycleCountEntry(const G4String& pname , const G4Material* mat) : particle(pname),material(mat),fastPath(nullptr), energy(-1.),crossSection(-1.) { DBG("Initializing cache entry"); #ifdef FPDEBUG cacheHitCount = 0; initCyclesFastPath=0; invocationCountSlowPath=0; totalCyclesSlowPath=0; invocationCountFastPath=0; totalCyclesFastPath=0; invocationCountTriedOneLineCache=0; invocationCountOneLineCache=0; #endif } cycleCountEntry::~cycleCountEntry() { DBG("Deleting cache entry"); DBG(particle<<" "<GetName():"MAT_NONE")<<") "<<" "\ <<"fast path pointer:"< & raw_data, std::vector & simplified_data) { int gap_left, gap_right; // indices of the current region G4double tolsq = tolerance*tolerance; // Alternative to working with absolute values. std::vector working_stack; //A stack of the points to the right of the current interval that // are known to be selected. gap_right = raw_data.size() - 1; // index of the last element. gap_left = 0; DBG("First and last elements " << gap_left <<" " < deltasq_max){ deltasq_max = delta * delta; i_max = i; } } } else { DBG(" Less than 3 point interval at [ "<< gap_left <<", " < & original, std::vector & simplified, std::vector & result){ const size_t originalSize = original.size(); const size_t simplifiedSize = simplified.size(); //Create index mapping array std::vector xindex(simplifiedSize,0); //G4int xindex[simplifiedSize]; G4int lastmatch = 0; G4int j = 0; DBG(" original and simplified vector sizes " << originalSize <<" "< GArea(m-1,0); //G4double GArea [m-1]; G4double GAreatotal = 0; //Area of original simplified curve for(int i = 0; i < m-1; i++){ G4double GAreatemp = 0; for(j = xindex[i]; j< xindex[i+1]; j++){ G4double trap = (original[j+1].xs + original[j].xs) * (original[j+1].e - original[j].e)/2.0; GAreatemp = GAreatemp + trap; } GArea[i] = GAreatemp; GAreatotal = GAreatotal + GAreatemp; } DBG(" Area under the original curve " << GAreatotal); //aleph Why is this not alpha? std::vector aleph(m-1,0); //G4double aleph [m-1]; for(int i = 0; i< m-1; i++){ aleph[i] = (simplified[i+1].e - simplified[i].e)/2.0; } //solve for f std::vector adjustedy(m-1,0); //G4double adjustedy [m]; adjustedy[m-1] = simplified[m-1].xs; for(int i = 2; i < m+1; i++) { adjustedy[m-i] = (GArea[m-i]/aleph[m-i]) - adjustedy[m-i+1]; if (adjustedy[m-i] <0.0) { adjustedy[m-i] = 0.0; DBG(" Fixing negative cross section at index " << (m-i)); } } //error and difference tracking std::vector difference(m,0.); //G4double difference [m]; G4double maxdiff = 0; G4double adjustedarea = 0; G4double simplifiedarea = 0; for(int i = 0; i < m-1; i++){ G4double trap; trap = (adjustedy[i+1]+adjustedy[i])*(simplified[i+1].e-simplified[i].e)/2.0; adjustedarea = adjustedarea+trap; trap = (simplified[i+1].xs+simplified[i].xs)*(simplified[i+1].e-simplified[i].e)/2.0; simplifiedarea = simplifiedarea + trap; } DBG(" Area: Simplified curve = " <