Import Geant4 11.4.0 source tree
This commit is contained in:
@@ -6,6 +6,46 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2025-11-06 Gabriele Cosmo (xrays-V11-03-06)
|
||||
- Fixed compilation warning for implicit type conversion on macOS/XCode
|
||||
in G4GeneralCherenkov::BuildPhysicsTable().
|
||||
|
||||
## 2025-11-03 Vladimir Ivanchenko (xrays-V11-03-05)
|
||||
- G4GeneralCerenkov, G4StandardCerenkovModel - fixed Coverity warnings.
|
||||
|
||||
## 2025-10-29 Vladimir Ivanchenko (xrays-V11-03-04)
|
||||
- Added new classes G4GeneralCerenkov and G4StandardCerenkovModel with the
|
||||
first implementation of the model approach for X-Ray processes
|
||||
- G4Cerenkov, G4Scintillation, G4GeneralCerenkov - fixed IsApplicable(..)
|
||||
method for UnknownParticle type - use dynamic charge and kinematics for these
|
||||
processes
|
||||
- G4Cerenkov, G4GeneralCerenkov - use inheritance from G4VDiscreteProcess
|
||||
|
||||
##2025-07-24 Soon Yung Jun (xrays-V11-03-03)
|
||||
- Add physics model catalog IDs and class descriptions for G4QuasiCerenkov and
|
||||
G4QuasiScintillation
|
||||
|
||||
##2025-07-21 Soon Yung Jun (xrays-V11-03-02)
|
||||
1) Add G4ScintillationQuasiTrackInfo: Concrete implementation of
|
||||
G4VAuxiliaryTrackInformation used to store metadata associated with a
|
||||
quasi-scintillation track generated during the scintillation process
|
||||
2) Add G4QuasiScintillation: Add offloading capability for scintillation
|
||||
photon generation
|
||||
3) G4Scintillation: Relocate loop-invariant variables outside the photon
|
||||
generation loop
|
||||
4) G4CerenkovQuasiTrackInfo: Add the use of G4Allocator
|
||||
|
||||
##2025-07-16 Soon Yung Jun (xrays-V11-03-01)
|
||||
- 1) Add G4QuasiOpticalData: Common data structure used for Cerenkov and
|
||||
Scintillation photon sampling
|
||||
2) Add G4CerenkovQuasiTrackInfo: Concrete implementation of
|
||||
G4VAuxiliaryTrackInformation used to store metadata associated with a
|
||||
quasi-Cerenkov track generated during the Cerenkov process
|
||||
3) Add G4QuasiCerenkov: Add offloading capability for Cerenkov photon
|
||||
generation
|
||||
4) G4Cerenkov: Relocated loop-invariant variables outside the photon
|
||||
generation loop
|
||||
|
||||
##2025-05-07 Soon Yung Jun (xrays-V11-03-00)
|
||||
- 1) G4Scintillation: Build the scintillation integral tables for materials
|
||||
that have non-empty material property tables and add BuildInverseCdfTable.
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#include "G4ForceCondition.hh"
|
||||
#include "G4GPILSelection.hh"
|
||||
#include "G4MaterialPropertyVector.hh"
|
||||
#include "G4VProcess.hh"
|
||||
#include "G4VDiscreteProcess.hh"
|
||||
|
||||
#include <map>
|
||||
|
||||
@@ -59,15 +59,14 @@ class G4Step;
|
||||
class G4Track;
|
||||
class G4VParticleChange;
|
||||
|
||||
class G4Cerenkov : public G4VProcess
|
||||
class G4Cerenkov : public G4VDiscreteProcess
|
||||
{
|
||||
public:
|
||||
explicit G4Cerenkov(const G4String& processName = "Cerenkov",
|
||||
G4ProcessType type = fElectromagnetic);
|
||||
~G4Cerenkov();
|
||||
|
||||
explicit G4Cerenkov(const G4Cerenkov& right);
|
||||
G4ProcessType type = fElectromagnetic);
|
||||
~G4Cerenkov() override;
|
||||
|
||||
G4Cerenkov(const G4Cerenkov& right) = delete;
|
||||
G4Cerenkov& operator=(const G4Cerenkov& right) = delete;
|
||||
|
||||
G4bool IsApplicable(const G4ParticleDefinition& aParticleType) override;
|
||||
@@ -78,9 +77,8 @@ class G4Cerenkov : public G4VProcess
|
||||
// Build table at a right time
|
||||
|
||||
void PreparePhysicsTable(const G4ParticleDefinition& part) override;
|
||||
void Initialise();
|
||||
|
||||
G4double GetMeanFreePath(const G4Track& aTrack, G4double, G4ForceCondition*);
|
||||
G4double GetMeanFreePath(const G4Track& aTrack, G4double, G4ForceCondition*) override;
|
||||
// Returns the discrete step limit and sets the 'StronglyForced'
|
||||
// condition for the DoIt to be invoked at every step.
|
||||
|
||||
@@ -93,31 +91,6 @@ class G4Cerenkov : public G4VProcess
|
||||
const G4Step& aStep) override;
|
||||
// This is the method implementing the Cerenkov process.
|
||||
|
||||
// no operation in AtRestDoIt and AlongStepDoIt
|
||||
virtual G4double AlongStepGetPhysicalInteractionLength(
|
||||
const G4Track&, G4double, G4double, G4double&, G4GPILSelection*) override
|
||||
{
|
||||
return -1.0;
|
||||
};
|
||||
|
||||
virtual G4double AtRestGetPhysicalInteractionLength(
|
||||
const G4Track&, G4ForceCondition*) override
|
||||
{
|
||||
return -1.0;
|
||||
};
|
||||
|
||||
// no operation in AtRestDoIt and AlongStepDoIt
|
||||
virtual G4VParticleChange* AtRestDoIt(const G4Track&, const G4Step&) override
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
virtual G4VParticleChange* AlongStepDoIt(const G4Track&,
|
||||
const G4Step&) override
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
void SetTrackSecondariesFirst(const G4bool state);
|
||||
// If set, the primary particle tracking is interrupted and any
|
||||
// produced Cerenkov photons are tracked next. When all have
|
||||
@@ -144,10 +117,10 @@ class G4Cerenkov : public G4VProcess
|
||||
// generated during a tracking step.
|
||||
|
||||
void SetStackPhotons(const G4bool);
|
||||
// Call by the user to set the flag for stacking the scint. photons
|
||||
// Call by the user to set the flag for stacking the Cerenkov photons
|
||||
|
||||
G4bool GetStackPhotons() const;
|
||||
// Return the boolean for whether or not the scint. photons are stacked
|
||||
// Return the boolean for whether or not the Cerenkov photons are stacked
|
||||
|
||||
G4int GetNumPhotons() const;
|
||||
// Returns the current number of scint. photons (after PostStepDoIt)
|
||||
@@ -162,7 +135,7 @@ class G4Cerenkov : public G4VProcess
|
||||
const G4Material* aMaterial,
|
||||
G4MaterialPropertyVector* Rindex) const;
|
||||
|
||||
void DumpInfo() const override {ProcessDescription(G4cout);};
|
||||
void DumpInfo() const override;
|
||||
void ProcessDescription(std::ostream& out) const override;
|
||||
|
||||
void SetVerboseLevel(G4int);
|
||||
@@ -173,6 +146,8 @@ class G4Cerenkov : public G4VProcess
|
||||
std::map<std::size_t, std::size_t> fIndexMPT;
|
||||
|
||||
private:
|
||||
void Initialise();
|
||||
|
||||
G4double fMaxBetaChange;
|
||||
|
||||
G4int fMaxPhotons;
|
||||
@@ -182,7 +157,6 @@ class G4Cerenkov : public G4VProcess
|
||||
G4bool fTrackSecondariesFirst;
|
||||
|
||||
G4int secID = -1; // creator modelID
|
||||
|
||||
};
|
||||
|
||||
inline G4bool G4Cerenkov::GetTrackSecondariesFirst() const
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
// Class Description:
|
||||
//
|
||||
// Concrete implementation of G4VAuxiliaryTrackInformation used to store
|
||||
// metadata associated with a quasi-Cerenkov track generated during the
|
||||
// Cerenkov process.
|
||||
//
|
||||
// This class is intended to be attached to a G4Track of G4QuasiOpticalPhoton
|
||||
// via G4Track::SetAuxiliaryTrackInformation(modelId, this) where
|
||||
// modelId is obtained by G4PhysicsModelCatalog::GetModelID("model_Cerenkov")
|
||||
// The stored information can later be retrieved using:
|
||||
// G4Track::GetAuxiliaryTrackInformation(modelId).
|
||||
//
|
||||
#ifndef G4CerenkovQuasiTrackInfo_h
|
||||
#define G4CerenkovQuasiTrackInfo_h
|
||||
|
||||
#include "G4Allocator.hh"
|
||||
#include "G4QuasiOpticalData.hh"
|
||||
#include "G4VAuxiliaryTrackInformation.hh"
|
||||
|
||||
class G4CerenkovQuasiTrackInfo : public G4VAuxiliaryTrackInformation
|
||||
{
|
||||
public:
|
||||
explicit G4CerenkovQuasiTrackInfo(const G4QuasiOpticalData& data,
|
||||
G4double pre_num_photons,
|
||||
G4double post_num_photons);
|
||||
|
||||
~G4CerenkovQuasiTrackInfo() override = default;
|
||||
|
||||
// Required by G4VAuxiliaryTrackInformation
|
||||
void* operator new(size_t);
|
||||
void operator delete(void* aCerenkovATI);
|
||||
|
||||
// Copy Constructor/instruction
|
||||
G4CerenkovQuasiTrackInfo(const G4CerenkovQuasiTrackInfo&) = default;
|
||||
G4CerenkovQuasiTrackInfo& operator=(const G4CerenkovQuasiTrackInfo&) = default;
|
||||
|
||||
void Print() const override;
|
||||
|
||||
G4QuasiOpticalData GetQuasiOpticalData() const { return fQuasiOpticalData; }
|
||||
G4double GetPreNumPhotons() const { return fPreNumPhotons; }
|
||||
G4double GetPostNumPhotons() const { return fPostNumPhotons; }
|
||||
|
||||
// Static class allowing to check if a G4VAuxiliaryTrackInformation is a
|
||||
// G4CerenkovQuasiTrackInfo and cast it without changing the pointer of the
|
||||
// pointed data.
|
||||
static G4CerenkovQuasiTrackInfo* Cast(
|
||||
const G4VAuxiliaryTrackInformation* const);
|
||||
|
||||
private:
|
||||
G4QuasiOpticalData fQuasiOpticalData; // Common optical data
|
||||
G4double fPreNumPhotons{}; // Average number of photons at the pre-step
|
||||
G4double fPostNumPhotons{}; // Average number of photons at the post-step
|
||||
};
|
||||
|
||||
///
|
||||
// Inline methods:
|
||||
// Implementation adapted from G4ScintillationTrackInformation
|
||||
///
|
||||
|
||||
#if defined G4EM_ALLOC_EXPORT
|
||||
extern G4DLLEXPORT G4Allocator<G4CerenkovQuasiTrackInfo>*&
|
||||
aCerenkovATIAllocator();
|
||||
#else
|
||||
extern G4DLLIMPORT G4Allocator<G4CerenkovQuasiTrackInfo>*&
|
||||
aCerenkovATIAllocator();
|
||||
#endif
|
||||
|
||||
inline void* G4CerenkovQuasiTrackInfo::operator new(size_t)
|
||||
{
|
||||
if(aCerenkovATIAllocator() == nullptr)
|
||||
{
|
||||
aCerenkovATIAllocator() = new G4Allocator<G4CerenkovQuasiTrackInfo>;
|
||||
}
|
||||
return (void*) aCerenkovATIAllocator()->MallocSingle();
|
||||
}
|
||||
|
||||
inline void G4CerenkovQuasiTrackInfo::operator delete(void* aCerenkovATI)
|
||||
{
|
||||
aCerenkovATIAllocator()->FreeSingle((G4CerenkovQuasiTrackInfo*) aCerenkovATI);
|
||||
}
|
||||
|
||||
#endif // G4CerenkovQuasiTrackInfo_h
|
||||
@@ -0,0 +1,154 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// G4GeneralCerenkov
|
||||
//
|
||||
// Class description:
|
||||
// The Cerenkov process using model approach when an object G4VXRayModel
|
||||
// is assign to G4LogicalVolume. A model is fully responsible for
|
||||
// Cerenkov gamma production. This process class performing only tecnical
|
||||
// operation and interaction with Geant4 kernel.
|
||||
//
|
||||
// Created 25.05.2025 V.Ivanchenko on base of G4Cerenkov class
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef G4GeneralCerenkov_h
|
||||
#define G4GeneralCerenkov_h 1
|
||||
|
||||
#include "globals.hh"
|
||||
#include "G4ForceCondition.hh"
|
||||
#include "G4LogicalVolume.hh"
|
||||
#include "G4VXRayModel.hh"
|
||||
#include "G4VDiscreteProcess.hh"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class G4Material;
|
||||
class G4ParticleDefinition;
|
||||
class G4PhysicsTable;
|
||||
class G4Step;
|
||||
class G4Track;
|
||||
class G4VParticleChange;
|
||||
|
||||
class G4GeneralCerenkov : public G4VDiscreteProcess
|
||||
{
|
||||
public:
|
||||
explicit G4GeneralCerenkov(const G4String& processName = "Cerenkov",
|
||||
G4ProcessType type = fElectromagnetic);
|
||||
~G4GeneralCerenkov() override;
|
||||
|
||||
G4GeneralCerenkov(const G4GeneralCerenkov& right) = delete;
|
||||
G4GeneralCerenkov& operator=(const G4GeneralCerenkov& right) = delete;
|
||||
|
||||
G4bool IsApplicable(const G4ParticleDefinition& aParticleType) override;
|
||||
|
||||
void PreparePhysicsTable(const G4ParticleDefinition& part) override;
|
||||
|
||||
void BuildPhysicsTable(const G4ParticleDefinition& aParticleType) override;
|
||||
|
||||
G4double PostStepGetPhysicalInteractionLength(const G4Track& aTrack, G4double,
|
||||
G4ForceCondition*) override;
|
||||
// Returns the discrete step limit and sets the 'StronglyForced'
|
||||
// condition for the DoIt to be invoked at every step.
|
||||
|
||||
G4VParticleChange* PostStepDoIt(const G4Track& aTrack,
|
||||
const G4Step& aStep) override;
|
||||
// This is the method implementing the Cerenkov process.
|
||||
|
||||
void AddModelForVolume(G4VXRayModel*, const G4String& nameLogVolume);
|
||||
// explicit addition of a custom Cerenkov model to a logical volume
|
||||
|
||||
void DumpInfo() const override { ProcessDescription(G4cout); };
|
||||
void ProcessDescription(std::ostream& out) const override;
|
||||
|
||||
G4double GetMeanFreePath(const G4Track&, G4double,
|
||||
G4ForceCondition*) override;
|
||||
|
||||
// Obsolete methods to be removed for the next major release
|
||||
|
||||
void SetTrackSecondariesFirst(const G4bool state);
|
||||
// If set, the primary particle tracking is interrupted and any
|
||||
// produced Cerenkov photons are tracked next. When all have
|
||||
// been tracked, the tracking of the primary resumes.
|
||||
|
||||
void SetMaxBetaChangePerStep(const G4double d);
|
||||
// Set the maximum allowed change in beta = v/c in % (perCent) per step.
|
||||
|
||||
void SetMaxNumPhotonsPerStep(const G4int NumPhotons);
|
||||
// Set the maximum number of Cerenkov photons allowed to be generated during
|
||||
// a tracking step. This is an average ONLY; the actual number will vary
|
||||
// around this average. If invoked, the maximum photon stack will roughly be
|
||||
// of the size set. If not called, the step is not limited by the number of
|
||||
// photons generated.
|
||||
|
||||
void SetStackPhotons(const G4bool);
|
||||
// Call by the user to set the flag for stacking the Cerenkov photons
|
||||
|
||||
void SetVerboseLevel(G4int);
|
||||
|
||||
private:
|
||||
|
||||
const G4LogicalVolume* fCurrentLV{nullptr};
|
||||
G4VXRayModel* fCurrentModel{nullptr};
|
||||
|
||||
G4double fMaxBetaChange{0.1};
|
||||
G4double fBetaMin{1.0};
|
||||
G4double fPreStepBeta{0.0};
|
||||
|
||||
G4int fMaxPhotons{100};
|
||||
|
||||
G4bool fStackingFlag{true};
|
||||
G4bool fTrackSecondariesFirst{true};
|
||||
G4bool isInitializer{false};
|
||||
G4bool isPrepared{false};
|
||||
G4bool isBuilt{false};
|
||||
|
||||
G4int secID{-1}; // creator modelID
|
||||
G4int nModels{0};
|
||||
|
||||
// map includes logical volume pointer and index of the model
|
||||
static std::vector<std::vector<const G4LogicalVolume*>* >* fLV;
|
||||
|
||||
// vector is used only at initialisation
|
||||
// these models are destructed by G4LossTableManager
|
||||
static std::vector<G4VXRayModel*>* fSharedModels;
|
||||
|
||||
// vector of names of logical volumes for master used for initilisation
|
||||
// not filled for a worker thread
|
||||
std::vector<G4String>* fLVNames{nullptr};
|
||||
|
||||
// models used in run time - they are thread local, are
|
||||
// instantiated in worker thread, and are cloned from fSharedModels
|
||||
// these models are destructed by G4LossTableManager
|
||||
std::vector<G4VXRayModel*> fModels;
|
||||
|
||||
// buffer for X-Rays
|
||||
std::vector<G4Track*> fSecondaries;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,223 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
// Class Description:
|
||||
//
|
||||
// This class is a modified clone of G4Cerenkov, extended to support
|
||||
// offloading optical photon generation. Offloading can be enabled either
|
||||
// via the G4OpticalParameters::Instance()->SetCerenkovOffloadPhotons(true)
|
||||
// method or the UI command:
|
||||
//
|
||||
// /process/optical/cerenkov/setOffloadPhotons true
|
||||
//
|
||||
// When offloading is enabled, the process generates a single secondary track
|
||||
// of type G4QuasiOpticalPhoton, along with associated metadata encapsulated
|
||||
// in G4CerenkovQuasiTrackInfo. This auxiliary track information is used
|
||||
// to generate optical photons at a later stage—typically during offloading.
|
||||
//
|
||||
// The intended workflow leverages G4VTrackingManager, which delegates these
|
||||
// secondary tracks to a dedicated G4ProcessManager for G4QuasiOpticalPhoton.
|
||||
// These tracks are then handled by a user-defined custom tracking manager,
|
||||
// independent of the default process managers used for other particles.
|
||||
//
|
||||
// The primary purpose of this class is to facilitate the transfer of essential
|
||||
// data for offloaded optical photon generation in heterogeneous computing
|
||||
// models
|
||||
|
||||
#ifndef G4QuasiCerenkov_h
|
||||
#define G4QuasiCerenkov_h 1
|
||||
|
||||
#include "globals.hh"
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "G4ForceCondition.hh"
|
||||
#include "G4GPILSelection.hh"
|
||||
#include "G4MaterialPropertyVector.hh"
|
||||
#include "G4VProcess.hh"
|
||||
|
||||
#include <map>
|
||||
|
||||
class G4Material;
|
||||
class G4ParticleDefinition;
|
||||
class G4PhysicsTable;
|
||||
class G4Step;
|
||||
class G4Track;
|
||||
class G4VParticleChange;
|
||||
|
||||
class G4QuasiCerenkov : public G4VProcess
|
||||
{
|
||||
public:
|
||||
explicit G4QuasiCerenkov(const G4String& processName = "QuasiCerenkov",
|
||||
G4ProcessType type = fElectromagnetic);
|
||||
~G4QuasiCerenkov();
|
||||
|
||||
explicit G4QuasiCerenkov(const G4QuasiCerenkov& right);
|
||||
|
||||
G4QuasiCerenkov& operator=(const G4QuasiCerenkov& right) = delete;
|
||||
|
||||
G4bool IsApplicable(const G4ParticleDefinition& aParticleType) override;
|
||||
// Returns true -> 'is applicable', for all charged particles
|
||||
// except short-lived particles.
|
||||
|
||||
void BuildPhysicsTable(const G4ParticleDefinition& aParticleType) override;
|
||||
// Build table at a right time
|
||||
|
||||
void PreparePhysicsTable(const G4ParticleDefinition& part) override;
|
||||
void Initialise();
|
||||
|
||||
G4double GetMeanFreePath(const G4Track& aTrack, G4double, G4ForceCondition*);
|
||||
// Returns the discrete step limit and sets the 'StronglyForced'
|
||||
// condition for the DoIt to be invoked at every step.
|
||||
|
||||
G4double PostStepGetPhysicalInteractionLength(const G4Track& aTrack, G4double,
|
||||
G4ForceCondition*) override;
|
||||
// Returns the discrete step limit and sets the 'StronglyForced'
|
||||
// condition for the DoIt to be invoked at every step.
|
||||
|
||||
G4VParticleChange* PostStepDoIt(const G4Track& aTrack,
|
||||
const G4Step& aStep) override;
|
||||
// This is the method implementing the Cerenkov process.
|
||||
|
||||
// no operation in AtRestDoIt and AlongStepDoIt
|
||||
virtual G4double AlongStepGetPhysicalInteractionLength(
|
||||
const G4Track&, G4double, G4double, G4double&, G4GPILSelection*) override
|
||||
{
|
||||
return -1.0;
|
||||
};
|
||||
|
||||
virtual G4double AtRestGetPhysicalInteractionLength(
|
||||
const G4Track&, G4ForceCondition*) override
|
||||
{
|
||||
return -1.0;
|
||||
};
|
||||
|
||||
// no operation in AtRestDoIt and AlongStepDoIt
|
||||
virtual G4VParticleChange* AtRestDoIt(const G4Track&, const G4Step&) override
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
virtual G4VParticleChange* AlongStepDoIt(const G4Track&,
|
||||
const G4Step&) override
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
void SetTrackSecondariesFirst(const G4bool state);
|
||||
// If set, the primary particle tracking is interrupted and any
|
||||
// produced Cerenkov photons are tracked next. When all have
|
||||
// been tracked, the tracking of the primary resumes.
|
||||
|
||||
G4bool GetTrackSecondariesFirst() const;
|
||||
// Returns the boolean flag for tracking secondaries first.
|
||||
|
||||
void SetMaxBetaChangePerStep(const G4double d);
|
||||
// Set the maximum allowed change in beta = v/c in % (perCent) per step.
|
||||
|
||||
G4double GetMaxBetaChangePerStep() const;
|
||||
// Returns the maximum allowed change in beta = v/c in % (perCent)
|
||||
|
||||
void SetMaxNumPhotonsPerStep(const G4int NumPhotons);
|
||||
// Set the maximum number of Cerenkov photons allowed to be generated during
|
||||
// a tracking step. This is an average ONLY; the actual number will vary
|
||||
// around this average. If invoked, the maximum photon stack will roughly be
|
||||
// of the size set. If not called, the step is not limited by the number of
|
||||
// photons generated.
|
||||
|
||||
G4int GetMaxNumPhotonsPerStep() const;
|
||||
// Returns the maximum number of Cerenkov photons allowed to be
|
||||
// generated during a tracking step.
|
||||
|
||||
void SetStackPhotons(const G4bool);
|
||||
// Call by the user to set the flag for stacking the Cerenkov photons
|
||||
|
||||
G4bool GetStackPhotons() const;
|
||||
// Return the boolean for whether or not the Cerenkov photons are stacked
|
||||
|
||||
void SetOffloadPhotons(const G4bool);
|
||||
// Call by the user to set the flag for offloading the Cerenkov photons
|
||||
|
||||
G4bool GetOffloadPhotons() const;
|
||||
// Return the boolean for whether or not the Cerenkov photons are offloaded
|
||||
|
||||
G4int GetNumPhotons() const;
|
||||
// Returns the current number of scint. photons (after PostStepDoIt)
|
||||
|
||||
G4PhysicsTable* GetPhysicsTable() const;
|
||||
// Returns the address of the physics table.
|
||||
|
||||
void DumpPhysicsTable() const;
|
||||
// Prints the physics table.
|
||||
|
||||
G4double GetAverageNumberOfPhotons(const G4double charge, const G4double beta,
|
||||
const G4Material* aMaterial,
|
||||
G4MaterialPropertyVector* Rindex) const;
|
||||
|
||||
void DumpInfo() const override {ProcessDescription(G4cout);};
|
||||
void ProcessDescription(std::ostream& out) const override;
|
||||
|
||||
void SetVerboseLevel(G4int);
|
||||
// sets verbosity
|
||||
|
||||
protected:
|
||||
G4PhysicsTable* thePhysicsTable;
|
||||
std::map<std::size_t, std::size_t> fIndexMPT;
|
||||
|
||||
private:
|
||||
G4double fMaxBetaChange;
|
||||
|
||||
G4int fMaxPhotons;
|
||||
G4int fNumPhotons;
|
||||
|
||||
G4bool fStackingFlag;
|
||||
G4bool fOffloadingFlag;
|
||||
G4bool fTrackSecondariesFirst;
|
||||
|
||||
G4int secID = -1; // creator modelID
|
||||
|
||||
};
|
||||
|
||||
inline G4bool G4QuasiCerenkov::GetTrackSecondariesFirst() const
|
||||
{
|
||||
return fTrackSecondariesFirst;
|
||||
}
|
||||
|
||||
inline G4double G4QuasiCerenkov::GetMaxBetaChangePerStep() const
|
||||
{
|
||||
return fMaxBetaChange;
|
||||
}
|
||||
|
||||
inline G4int G4QuasiCerenkov::GetMaxNumPhotonsPerStep() const { return fMaxPhotons; }
|
||||
|
||||
inline G4bool G4QuasiCerenkov::GetStackPhotons() const { return fStackingFlag; }
|
||||
|
||||
inline G4bool G4QuasiCerenkov::GetOffloadPhotons() const { return fOffloadingFlag; }
|
||||
|
||||
inline G4int G4QuasiCerenkov::GetNumPhotons() const { return fNumPhotons; }
|
||||
|
||||
inline G4PhysicsTable* G4QuasiCerenkov::GetPhysicsTable() const
|
||||
{
|
||||
return thePhysicsTable;
|
||||
}
|
||||
|
||||
#endif /* G4QuasiCerenkov_h */
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
#ifndef G4QuasiOpticalData_h
|
||||
#define G4QuasiOpticalData_h
|
||||
|
||||
#include "G4ThreeVector.hh"
|
||||
|
||||
// Common data structure used for Cerenkov and Scintillation photon sampling
|
||||
struct G4QuasiOpticalData
|
||||
{
|
||||
std::size_t mat_index{}; // Index of material in the material table
|
||||
G4int num_photons{}; // Number of optical photons to generate
|
||||
G4double charge{}; // Charge of the parent particle
|
||||
G4double step_length{}; // Step length of the parent track
|
||||
G4double pre_velocity{}; // Velocity at the pre-step point
|
||||
G4double delta_velocity{}; // Change in velocity between pre- and post-step
|
||||
G4ThreeVector delta_position{}; // Displacement vector over the step
|
||||
};
|
||||
|
||||
#endif // G4QuasiOpticalData_h
|
||||
@@ -0,0 +1,295 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
// Class Description:
|
||||
//
|
||||
// This class is a modified clone of G4Scintillation, extended to support
|
||||
// offloading optical photon generation. Offloading can be enabled either
|
||||
// via the G4OpticalParameters::Instance()->SetScintOffloadPhotons(true)
|
||||
// method or the UI command:
|
||||
//
|
||||
// /process/optical/scintillation/setOffloadPhotons true
|
||||
//
|
||||
// When offloading is enabled, the process generates a single secondary track
|
||||
// of type G4QuasiOpticalPhoton, along with associated metadata encapsulated
|
||||
// in G4ScintillationQuasiTrackInfo. This auxiliary track information is used
|
||||
// to generate optical photons at a later stage—typically during offloading.
|
||||
//
|
||||
// The intended workflow leverages G4VTrackingManager, which delegates these
|
||||
// secondary tracks to a dedicated G4ProcessManager for G4QuasiOpticalPhoton.
|
||||
// These tracks are then handled by a user-defined custom tracking manager,
|
||||
// independent of the default process managers used for other particles.
|
||||
//
|
||||
// The primary purpose of this class is to facilitate the transfer of essential
|
||||
// data for offloaded optical photon generation in heterogeneous computing
|
||||
// models
|
||||
|
||||
#ifndef G4QuasiScintillation_h
|
||||
#define G4QuasiScintillation_h 1
|
||||
|
||||
#include "globals.hh"
|
||||
#include "G4EmSaturation.hh"
|
||||
#include "G4OpticalPhoton.hh"
|
||||
#include "G4VRestDiscreteProcess.hh"
|
||||
|
||||
#include <map>
|
||||
|
||||
class G4PhysicsTable;
|
||||
class G4Step;
|
||||
class G4Track;
|
||||
|
||||
class G4QuasiScintillation : public G4VRestDiscreteProcess
|
||||
{
|
||||
public:
|
||||
explicit G4QuasiScintillation(const G4String& procName = "QausiScintillation",
|
||||
G4ProcessType type = fElectromagnetic);
|
||||
~G4QuasiScintillation();
|
||||
|
||||
G4QuasiScintillation(const G4QuasiScintillation& right) = delete;
|
||||
G4QuasiScintillation& operator=(const G4QuasiScintillation& right) = delete;
|
||||
|
||||
// G4QuasiScintillation Process has both PostStepDoIt (for energy
|
||||
// deposition of particles in flight) and AtRestDoIt (for energy
|
||||
// given to the medium by particles at rest)
|
||||
|
||||
G4bool IsApplicable(const G4ParticleDefinition& aParticleType) override;
|
||||
// Returns true -> 'is applicable', for any particle type except
|
||||
// for an 'opticalphoton' and for short-lived particles
|
||||
|
||||
void ProcessDescription(std::ostream&) const override;
|
||||
void DumpInfo() const override {ProcessDescription(G4cout);};
|
||||
|
||||
void BuildPhysicsTable(const G4ParticleDefinition& aParticleType) override;
|
||||
// Build table at the right time
|
||||
|
||||
void PreparePhysicsTable(const G4ParticleDefinition& part) override;
|
||||
void Initialise();
|
||||
|
||||
G4double GetMeanFreePath(const G4Track& aTrack, G4double,
|
||||
G4ForceCondition*) override;
|
||||
// Returns infinity; i. e. the process does not limit the step,
|
||||
// but sets the 'StronglyForced' condition for the DoIt to be
|
||||
// invoked at every step.
|
||||
|
||||
G4double GetMeanLifeTime(const G4Track& aTrack, G4ForceCondition*) override;
|
||||
// Returns infinity; i. e. the process does not limit the time,
|
||||
// but sets the 'StronglyForced' condition for the DoIt to be
|
||||
// invoked at every step.
|
||||
|
||||
G4VParticleChange* PostStepDoIt(const G4Track& aTrack,
|
||||
const G4Step& aStep) override;
|
||||
G4VParticleChange* AtRestDoIt(const G4Track& aTrack,
|
||||
const G4Step& aStep) override;
|
||||
|
||||
G4double GetScintillationYieldByParticleType(const G4Track& aTrack,
|
||||
const G4Step& aStep,
|
||||
G4double& yield1,
|
||||
G4double& yield2,
|
||||
G4double& yield3,
|
||||
G4double& timeconstant1,
|
||||
G4double& timeconstant2,
|
||||
G4double& timeconstant3);
|
||||
// allow multiple time constants with scint by particle type
|
||||
// Returns the number of scintillation photons calculated when
|
||||
// scintillation depends on the particle type and energy
|
||||
// deposited (includes nonlinear dependendency) and updates the
|
||||
// yields for each channel
|
||||
|
||||
void SetTrackSecondariesFirst(const G4bool state);
|
||||
// If set, the primary particle tracking is interrupted and any
|
||||
// produced scintillation photons are tracked next. When all
|
||||
// have been tracked, the tracking of the primary resumes.
|
||||
|
||||
G4bool GetTrackSecondariesFirst() const;
|
||||
// Returns the boolean flag for tracking secondaries first.
|
||||
|
||||
void SetFiniteRiseTime(const G4bool state);
|
||||
// If set, the G4QuasiScintillation process expects the user to have
|
||||
// set the constant material property SCINTILLATIONRISETIME{1,2,3}.
|
||||
|
||||
G4bool GetFiniteRiseTime() const;
|
||||
// Returns the boolean flag for a finite scintillation rise time.
|
||||
|
||||
G4PhysicsTable* GetIntegralTable1() const;
|
||||
// Returns the address of scintillation integral table #1.
|
||||
|
||||
G4PhysicsTable* GetIntegralTable2() const;
|
||||
// Returns the address of scintillation integral table #2.
|
||||
|
||||
G4PhysicsTable* GetIntegralTable3() const;
|
||||
// Returns the address of scintillation integral table #3.
|
||||
|
||||
void AddSaturation(G4EmSaturation* sat);
|
||||
// Adds Birks Saturation to the process.
|
||||
|
||||
void RemoveSaturation();
|
||||
// Removes the Birks Saturation from the process.
|
||||
|
||||
G4EmSaturation* GetSaturation() const;
|
||||
// Returns the Birks Saturation.
|
||||
|
||||
void SetScintillationByParticleType(const G4bool);
|
||||
// Called by the user to set the scintillation yield as a function
|
||||
// of energy deposited by particle type
|
||||
|
||||
G4bool GetScintillationByParticleType() const;
|
||||
// Return the boolean that determines the method of scintillation
|
||||
// production
|
||||
|
||||
void SetScintillationTrackInfo(const G4bool trackType);
|
||||
// Call by the user to set the G4ScintillationTrackInformation
|
||||
// to scintillation photon track
|
||||
|
||||
G4bool GetScintillationTrackInfo() const;
|
||||
// Return the boolean for whether or not the
|
||||
// G4QuasiScintillationTrackInformation is set to the scint. photon track
|
||||
|
||||
void SetStackPhotons(const G4bool);
|
||||
// Call by the user to set the flag for stacking the scint. photons
|
||||
|
||||
G4bool GetStackPhotons() const;
|
||||
// Return the boolean for whether or not the scint. photons are stacked
|
||||
|
||||
void SetOffloadPhotons(const G4bool);
|
||||
// Call by the user to set the flag for offloading the scint. photons
|
||||
|
||||
G4bool GetOffloadPhotons() const;
|
||||
// Return the boolean for whether or not the scint. photons are offloaded
|
||||
|
||||
G4int GetNumPhotons() const;
|
||||
// Returns the current number of scint. photons (after PostStepDoIt)
|
||||
|
||||
void DumpPhysicsTable() const;
|
||||
// Prints the fast and slow scintillation integral tables.
|
||||
|
||||
void SetVerboseLevel(G4int);
|
||||
// sets verbosity
|
||||
|
||||
private:
|
||||
void BuildInverseCdfTable(const G4MaterialPropertyVector* MPV,
|
||||
G4PhysicsFreeVector* vec) const;
|
||||
// Build the inverse cumulative distribution function (C.D.F.) table
|
||||
// for the scintillation photon energy spectrum
|
||||
|
||||
private:
|
||||
|
||||
G4PhysicsTable* fIntegralTable1;
|
||||
G4PhysicsTable* fIntegralTable2;
|
||||
G4PhysicsTable* fIntegralTable3;
|
||||
std::map<std::size_t, std::size_t> fIndexMPT;
|
||||
|
||||
G4EmSaturation* fEmSaturation;
|
||||
const G4ParticleDefinition* opticalphoton =
|
||||
G4OpticalPhoton::OpticalPhotonDefinition();
|
||||
|
||||
G4int fNumPhotons;
|
||||
|
||||
G4bool fScintillationByParticleType;
|
||||
G4bool fScintillationTrackInfo;
|
||||
G4bool fStackingFlag;
|
||||
G4bool fOffloadingFlag;
|
||||
G4bool fTrackSecondariesFirst;
|
||||
G4bool fFiniteRiseTime;
|
||||
|
||||
#ifdef G4DEBUG_SCINTILLATION
|
||||
G4double ScintTrackEDep, ScintTrackYield;
|
||||
#endif
|
||||
// emission time distribution when there is a finite rise time
|
||||
G4double sample_time(G4double tau1, G4double tau2);
|
||||
|
||||
G4int secID = -1; // creator modelID
|
||||
G4int fNumEnergyWarnings = 0;
|
||||
|
||||
};
|
||||
|
||||
////////////////////
|
||||
// Inline methods
|
||||
////////////////////
|
||||
|
||||
inline G4bool G4QuasiScintillation::GetTrackSecondariesFirst() const
|
||||
{
|
||||
return fTrackSecondariesFirst;
|
||||
}
|
||||
|
||||
inline G4bool G4QuasiScintillation::GetFiniteRiseTime() const
|
||||
{
|
||||
return fFiniteRiseTime;
|
||||
}
|
||||
|
||||
inline G4PhysicsTable* G4QuasiScintillation::GetIntegralTable1() const
|
||||
{
|
||||
return fIntegralTable1;
|
||||
}
|
||||
|
||||
inline G4PhysicsTable* G4QuasiScintillation::GetIntegralTable2() const
|
||||
{
|
||||
return fIntegralTable2;
|
||||
}
|
||||
|
||||
inline G4PhysicsTable* G4QuasiScintillation::GetIntegralTable3() const
|
||||
{
|
||||
return fIntegralTable3;
|
||||
}
|
||||
|
||||
inline void G4QuasiScintillation::AddSaturation(G4EmSaturation* sat)
|
||||
{
|
||||
fEmSaturation = sat;
|
||||
}
|
||||
|
||||
inline void G4QuasiScintillation::RemoveSaturation()
|
||||
{
|
||||
fEmSaturation = nullptr;
|
||||
}
|
||||
|
||||
inline G4EmSaturation* G4QuasiScintillation::GetSaturation() const
|
||||
{
|
||||
return fEmSaturation;
|
||||
}
|
||||
|
||||
inline G4bool G4QuasiScintillation::GetScintillationByParticleType() const
|
||||
{
|
||||
return fScintillationByParticleType;
|
||||
}
|
||||
|
||||
inline G4bool G4QuasiScintillation::GetScintillationTrackInfo() const
|
||||
{
|
||||
return fScintillationTrackInfo;
|
||||
}
|
||||
|
||||
inline G4bool G4QuasiScintillation::GetStackPhotons() const
|
||||
{
|
||||
return fStackingFlag;
|
||||
}
|
||||
|
||||
inline G4bool G4QuasiScintillation::GetOffloadPhotons() const
|
||||
{
|
||||
return fOffloadingFlag;
|
||||
}
|
||||
|
||||
inline G4int G4QuasiScintillation::GetNumPhotons() const
|
||||
{
|
||||
return fNumPhotons;
|
||||
}
|
||||
|
||||
#endif /* G4QuasiScintillation_h */
|
||||
@@ -0,0 +1,111 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
// Class Description:
|
||||
//
|
||||
// Concrete implementation of G4VAuxiliaryTrackInformation used to store
|
||||
// metadata associated with a quasi-scintillation track generated during
|
||||
// the Scintillation process.
|
||||
//
|
||||
// This class is intended to be attached to a G4Track of G4QuasiOpticalPhoton
|
||||
// via G4Track::SetAuxiliaryTrackInformation(modelId, this) where modelId
|
||||
// is obtained by G4PhysicsModelCatalog::GetModelID("model_Scintillation")
|
||||
// The stored information can later be retrieved using:
|
||||
// G4Track::GetAuxiliaryTrackInformation(modelId).
|
||||
//
|
||||
#ifndef G4ScintillationQuasiTrackInfo_h
|
||||
#define G4ScintillationQuasiTrackInfo_h
|
||||
|
||||
#include "G4Allocator.hh"
|
||||
#include "G4QuasiOpticalData.hh"
|
||||
#include "G4VAuxiliaryTrackInformation.hh"
|
||||
|
||||
class G4ScintillationQuasiTrackInfo : public G4VAuxiliaryTrackInformation
|
||||
{
|
||||
public:
|
||||
// Construct with scintillation quasi optical data and auxiliary information
|
||||
explicit G4ScintillationQuasiTrackInfo(const G4QuasiOpticalData& data,
|
||||
G4double scint_time,
|
||||
G4double rise_time);
|
||||
|
||||
~G4ScintillationQuasiTrackInfo() override = default;
|
||||
|
||||
// Required by G4VAuxiliaryTrackInformation
|
||||
void* operator new(size_t);
|
||||
void operator delete(void* aScintillationTI);
|
||||
|
||||
// Copy Constructor/instruction
|
||||
G4ScintillationQuasiTrackInfo(const G4ScintillationQuasiTrackInfo&) = default;
|
||||
G4ScintillationQuasiTrackInfo& operator=(
|
||||
const G4ScintillationQuasiTrackInfo&) = default;
|
||||
|
||||
void Print() const override;
|
||||
|
||||
G4QuasiOpticalData GetQuasiOpticalData() const { return fQuasiOpticalData; }
|
||||
G4double GetScintTime() const { return fScintTime; }
|
||||
G4double GetRiseTime() const { return fRiseTime; }
|
||||
|
||||
// Static class allowing to check if a G4VAuxiliaryTrackInformation is a
|
||||
// G4ScintillationQuasiTrackInfo and cast it without changing the pointer
|
||||
// of the pointed data.
|
||||
static G4ScintillationQuasiTrackInfo* Cast(
|
||||
const G4VAuxiliaryTrackInformation* const);
|
||||
|
||||
private:
|
||||
G4QuasiOpticalData fQuasiOpticalData; // Common optical data
|
||||
G4double fScintTime{}; // Scintillation decay time constant
|
||||
G4double fRiseTime{}; // Scintillation rise time constant
|
||||
};
|
||||
|
||||
///
|
||||
// Inline methods
|
||||
// Implementation adapted from G4ScintillationTrackInformation
|
||||
///
|
||||
|
||||
#if defined G4EM_ALLOC_EXPORT
|
||||
extern G4DLLEXPORT G4Allocator<G4ScintillationQuasiTrackInfo>*&
|
||||
aScintillationATIAllocator();
|
||||
#else
|
||||
extern G4DLLIMPORT G4Allocator<G4ScintillationQuasiTrackInfo>*&
|
||||
aScintillationATIAllocator();
|
||||
#endif
|
||||
|
||||
inline void* G4ScintillationQuasiTrackInfo::operator new(size_t)
|
||||
{
|
||||
if(aScintillationATIAllocator() == nullptr)
|
||||
{
|
||||
aScintillationATIAllocator() =
|
||||
new G4Allocator<G4ScintillationQuasiTrackInfo>;
|
||||
}
|
||||
return (void*) aScintillationATIAllocator()->MallocSingle();
|
||||
}
|
||||
|
||||
inline void G4ScintillationQuasiTrackInfo::operator delete(
|
||||
void* aScintillationATI)
|
||||
{
|
||||
aScintillationATIAllocator()->FreeSingle(
|
||||
(G4ScintillationQuasiTrackInfo*) aScintillationATI);
|
||||
}
|
||||
|
||||
#endif // G4ScintillationQuasiTrackInfo_h
|
||||
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
//
|
||||
// G4StandardCerenkovModel
|
||||
//
|
||||
// Class description:
|
||||
// The classical Cerenkov gamma emission assuming infinite media.
|
||||
// The model is active only inside defined list of logical volumes
|
||||
//
|
||||
// Created 25.05.2025 V.Ivanchenko on base of G4Cerenkov class
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef G4StandardCerenkovModel_h
|
||||
#define G4StandardCerenkovModel_h 1
|
||||
|
||||
#include "G4VXRayModel.hh"
|
||||
#include "globals.hh"
|
||||
#include "G4LogicalVolume.hh"
|
||||
#include "G4MaterialPropertyVector.hh"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class G4MaterialCutsCouple;
|
||||
class G4ParticleDefinition;
|
||||
class G4Step;
|
||||
class G4Track;
|
||||
|
||||
class G4StandardCerenkovModel : public G4VXRayModel
|
||||
{
|
||||
public:
|
||||
G4StandardCerenkovModel();
|
||||
|
||||
// the default copy constructor is used by G4GeneralCerenkov class
|
||||
G4StandardCerenkovModel(const G4StandardCerenkovModel&) = default;
|
||||
|
||||
~G4StandardCerenkovModel() override;
|
||||
|
||||
G4StandardCerenkovModel& operator=(const G4StandardCerenkovModel& right) = delete;
|
||||
G4StandardCerenkovModel& operator==(const G4StandardCerenkovModel& right) = delete;
|
||||
G4StandardCerenkovModel& operator!=(const G4StandardCerenkovModel& right) = delete;
|
||||
|
||||
void InitialiseModel() override;
|
||||
|
||||
G4bool StepLimitForVolume(G4double& limit) override;
|
||||
|
||||
void SampleXRays(std::vector<G4Track*>& out, const G4Step&) override;
|
||||
|
||||
void ModelDescription(std::ostream& outFile) const override;
|
||||
|
||||
private:
|
||||
|
||||
G4double AverageNumberOfPhotons(const G4double charge, const G4double beta,
|
||||
const G4double n) const
|
||||
{
|
||||
return fRfact*charge*charge*std::max(1.0 - 1.0/(beta*n), 0.0);
|
||||
}
|
||||
|
||||
static std::vector<G4double>* fBetaLim;
|
||||
static std::vector<std::vector<G4double>* >* fMeanNumberOfPhotons;
|
||||
static std::vector<std::vector<std::vector<G4double>* >* >* fIntegral;
|
||||
static std::vector<G4MaterialPropertyVector*>* fRindex;
|
||||
|
||||
const G4ParticleDefinition* fParticle{nullptr};
|
||||
const G4ParticleDefinition* fPhoton{nullptr};
|
||||
G4double fPreStepKinE{0.0};
|
||||
G4double fMass{0.0};
|
||||
G4double fCharge{0.0};
|
||||
G4double fMeanNPhotons{0.0};
|
||||
G4double fRfact{1.0};
|
||||
|
||||
G4bool isInitializer{false};
|
||||
G4bool isInitialized{false};
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,12 +4,19 @@
|
||||
geant4_add_module(G4xrays
|
||||
PUBLIC_HEADERS
|
||||
G4Cerenkov.hh
|
||||
G4CerenkovQuasiTrackInfo.hh
|
||||
G4ForwardXrayTR.hh
|
||||
G4GammaXTRadiator.hh
|
||||
G4GaussXTRadiator.hh
|
||||
G4GeneralCerenkov.hh
|
||||
G4QuasiCerenkov.hh
|
||||
G4QuasiScintillation.hh
|
||||
G4QuasiOpticalData.hh
|
||||
G4RegularXTRadiator.hh
|
||||
G4Scintillation.hh
|
||||
G4ScintillationQuasiTrackInfo.hh
|
||||
G4ScintillationTrackInformation.hh
|
||||
G4StandardCerenkovModel.hh
|
||||
G4StrawTubeXTRadiator.hh
|
||||
G4SynchrotronRadiation.hh
|
||||
G4SynchrotronRadiationInMat.hh
|
||||
@@ -25,12 +32,18 @@ geant4_add_module(G4xrays
|
||||
G4XrayReflection.hh
|
||||
SOURCES
|
||||
G4Cerenkov.cc
|
||||
G4CerenkovQuasiTrackInfo.cc
|
||||
G4ForwardXrayTR.cc
|
||||
G4GammaXTRadiator.cc
|
||||
G4GaussXTRadiator.cc
|
||||
G4GeneralCerenkov.cc
|
||||
G4QuasiCerenkov.cc
|
||||
G4QuasiScintillation.cc
|
||||
G4RegularXTRadiator.cc
|
||||
G4Scintillation.cc
|
||||
G4ScintillationQuasiTrackInfo.cc
|
||||
G4ScintillationTrackInformation.cc
|
||||
G4StandardCerenkovModel.cc
|
||||
G4StrawTubeXTRadiator.cc
|
||||
G4SynchrotronRadiation.cc
|
||||
G4SynchrotronRadiationInMat.cc
|
||||
|
||||
@@ -77,19 +77,18 @@
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4Cerenkov::G4Cerenkov(const G4String& processName, G4ProcessType type)
|
||||
: G4VProcess(processName, type)
|
||||
: G4VDiscreteProcess(processName, type)
|
||||
, fNumPhotons(0)
|
||||
{
|
||||
secID = G4PhysicsModelCatalog::GetModelID("model_Cerenkov");
|
||||
SetProcessSubType(fCerenkov);
|
||||
|
||||
thePhysicsTable = nullptr;
|
||||
|
||||
if(verboseLevel > 0)
|
||||
{
|
||||
Initialise();
|
||||
|
||||
if (verboseLevel > 0) {
|
||||
G4cout << GetProcessName() << " is created." << G4endl;
|
||||
}
|
||||
Initialise();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -118,17 +117,6 @@ void G4Cerenkov::ProcessDescription(std::ostream& out) const
|
||||
out << "Verbose level: " << params->GetCerenkovVerboseLevel();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4bool G4Cerenkov::IsApplicable(const G4ParticleDefinition& aParticleType)
|
||||
{
|
||||
return (aParticleType.GetPDGCharge() != 0.0 &&
|
||||
aParticleType.GetPDGMass() != 0.0 &&
|
||||
aParticleType.GetParticleName() != "chargedgeantino" &&
|
||||
!aParticleType.IsShortLived())
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4Cerenkov::Initialise()
|
||||
{
|
||||
@@ -140,6 +128,15 @@ void G4Cerenkov::Initialise()
|
||||
SetVerboseLevel(params->GetCerenkovVerboseLevel());
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4bool G4Cerenkov::IsApplicable(const G4ParticleDefinition& aParticleType)
|
||||
{
|
||||
return ((aParticleType.GetPDGCharge() != 0.0 &&
|
||||
aParticleType.GetPDGMass() != 0.0 &&
|
||||
!aParticleType.IsShortLived()) ||
|
||||
aParticleType.GetParticleName() == "unknown");
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4Cerenkov::BuildPhysicsTable(const G4ParticleDefinition&)
|
||||
{
|
||||
@@ -287,6 +284,10 @@ G4VParticleChange* G4Cerenkov::PostStepDoIt(const G4Track& aTrack,
|
||||
return pParticleChange;
|
||||
}
|
||||
|
||||
G4double deltaVelocity = pPostStepPoint->GetVelocity() -
|
||||
pPreStepPoint->GetVelocity();
|
||||
auto touchableHandle = aStep.GetPreStepPoint()->GetTouchableHandle();
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
aParticleChange.SetNumberOfSecondaries(fNumPhotons);
|
||||
|
||||
@@ -300,18 +301,21 @@ G4VParticleChange* G4Cerenkov::PostStepDoIt(const G4Track& aTrack,
|
||||
G4double Pmin = Rindex->Energy(0);
|
||||
G4double Pmax = Rindex->GetMaxEnergy();
|
||||
G4double dp = Pmax - Pmin;
|
||||
G4double deltaNumberOfPhotons = MeanNumberOfPhotons1 - MeanNumberOfPhotons2;
|
||||
G4double maxNumberOfPhotons =
|
||||
std::max(MeanNumberOfPhotons1, MeanNumberOfPhotons2);
|
||||
|
||||
G4double nMax = Rindex->GetMaxValue();
|
||||
G4double BetaInverse = 1. / beta;
|
||||
|
||||
G4double maxCos = BetaInverse / nMax;
|
||||
G4double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
|
||||
G4double maxSin2 = 1.0 - maxCos * maxCos;
|
||||
|
||||
for(G4int i = 0; i < fNumPhotons; ++i)
|
||||
{
|
||||
// Determine photon energy
|
||||
G4double rand;
|
||||
G4double sampledEnergy, sampledRI;
|
||||
G4double sampledEnergy;
|
||||
G4double cosTheta, sin2Theta;
|
||||
|
||||
// sample an energy
|
||||
@@ -319,10 +323,9 @@ G4VParticleChange* G4Cerenkov::PostStepDoIt(const G4Track& aTrack,
|
||||
{
|
||||
rand = G4UniformRand();
|
||||
sampledEnergy = Pmin + rand * dp;
|
||||
sampledRI = Rindex->Value(sampledEnergy);
|
||||
cosTheta = BetaInverse / sampledRI;
|
||||
cosTheta = BetaInverse / Rindex->Value(sampledEnergy);
|
||||
|
||||
sin2Theta = (1.0 - cosTheta) * (1.0 + cosTheta);
|
||||
sin2Theta = 1.0 - cosTheta * cosTheta;
|
||||
rand = G4UniformRand();
|
||||
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
@@ -356,24 +359,18 @@ G4VParticleChange* G4Cerenkov::PostStepDoIt(const G4Track& aTrack,
|
||||
aCerenkovPhoton->SetPolarization(photonPolarization);
|
||||
aCerenkovPhoton->SetKineticEnergy(sampledEnergy);
|
||||
|
||||
G4double NumberOfPhotons, N;
|
||||
G4double NumberOfPhotons;
|
||||
|
||||
do
|
||||
{
|
||||
rand = G4UniformRand();
|
||||
NumberOfPhotons = MeanNumberOfPhotons1 -
|
||||
rand * (MeanNumberOfPhotons1 - MeanNumberOfPhotons2);
|
||||
N =
|
||||
G4UniformRand() * std::max(MeanNumberOfPhotons1, MeanNumberOfPhotons2);
|
||||
NumberOfPhotons = MeanNumberOfPhotons1 - rand * deltaNumberOfPhotons;
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
} while(N > NumberOfPhotons);
|
||||
} while(G4UniformRand() * maxNumberOfPhotons > NumberOfPhotons);
|
||||
|
||||
G4double delta = rand * aStep.GetStepLength();
|
||||
G4double deltaTime =
|
||||
delta /
|
||||
(pPreStepPoint->GetVelocity() +
|
||||
rand * (pPostStepPoint->GetVelocity() - pPreStepPoint->GetVelocity()) *
|
||||
0.5);
|
||||
delta / (pPreStepPoint->GetVelocity() + rand * deltaVelocity * 0.5);
|
||||
|
||||
G4double aSecondaryTime = t0 + deltaTime;
|
||||
G4ThreeVector aSecondaryPosition = x0 + rand * aStep.GetDeltaPosition();
|
||||
@@ -382,8 +379,7 @@ G4VParticleChange* G4Cerenkov::PostStepDoIt(const G4Track& aTrack,
|
||||
G4Track* aSecondaryTrack =
|
||||
new G4Track(aCerenkovPhoton, aSecondaryTime, aSecondaryPosition);
|
||||
|
||||
aSecondaryTrack->SetTouchableHandle(
|
||||
aStep.GetPreStepPoint()->GetTouchableHandle());
|
||||
aSecondaryTrack->SetTouchableHandle(touchableHandle);
|
||||
aSecondaryTrack->SetParentID(aTrack.GetTrackID());
|
||||
aSecondaryTrack->SetCreatorModelID(secID);
|
||||
aParticleChange.AddSecondary(aSecondaryTrack);
|
||||
@@ -408,7 +404,7 @@ void G4Cerenkov::PreparePhysicsTable(const G4ParticleDefinition&)
|
||||
G4double G4Cerenkov::GetMeanFreePath(const G4Track&, G4double,
|
||||
G4ForceCondition*)
|
||||
{
|
||||
return 1.;
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -417,6 +413,9 @@ G4double G4Cerenkov::PostStepGetPhysicalInteractionLength(
|
||||
{
|
||||
*condition = NotForced;
|
||||
G4double StepLimit = DBL_MAX;
|
||||
if (aTrack.GetDynamicParticle()->GetCharge() == 0.0) {
|
||||
return StepLimit;
|
||||
}
|
||||
fNumPhotons = 0;
|
||||
|
||||
const G4Material* aMaterial = aTrack.GetMaterial();
|
||||
@@ -424,11 +423,9 @@ G4double G4Cerenkov::PostStepGetPhysicalInteractionLength(
|
||||
|
||||
// If Physics Vector is not defined no Cerenkov photons
|
||||
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
|
||||
G4MaterialPropertiesTable* MPT =
|
||||
auto const MPT =
|
||||
((*materialTable)[materialIndex])->GetMaterialPropertiesTable();
|
||||
// if(!(*thePhysicsTable)[materialIndex])
|
||||
if(!MPT)
|
||||
{
|
||||
if (nullptr == MPT) {
|
||||
return StepLimit;
|
||||
}
|
||||
|
||||
@@ -649,3 +646,11 @@ void G4Cerenkov::SetVerboseLevel(G4int verbose)
|
||||
verboseLevel = verbose;
|
||||
G4OpticalParameters::Instance()->SetCerenkovVerboseLevel(verboseLevel);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4Cerenkov::DumpInfo() const
|
||||
{
|
||||
ProcessDescription(G4cout);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "G4CerenkovQuasiTrackInfo.hh"
|
||||
|
||||
G4Allocator<G4CerenkovQuasiTrackInfo>*& aCerenkovATIAllocator()
|
||||
{
|
||||
G4ThreadLocalStatic G4Allocator<G4CerenkovQuasiTrackInfo>* _instance =
|
||||
nullptr;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
G4CerenkovQuasiTrackInfo::G4CerenkovQuasiTrackInfo(
|
||||
const G4QuasiOpticalData& aOpticalData,
|
||||
G4double aPreNumPhotons, G4double aPostNumPhotons)
|
||||
: G4VAuxiliaryTrackInformation()
|
||||
, fQuasiOpticalData(aOpticalData)
|
||||
, fPreNumPhotons(aPreNumPhotons)
|
||||
, fPostNumPhotons(aPostNumPhotons)
|
||||
{}
|
||||
|
||||
void G4CerenkovQuasiTrackInfo::Print() const
|
||||
{
|
||||
G4cout << "Auxiliary track information for a Cerenkov step" << G4endl;
|
||||
}
|
||||
|
||||
G4CerenkovQuasiTrackInfo* G4CerenkovQuasiTrackInfo::Cast(
|
||||
const G4VAuxiliaryTrackInformation* const aATI)
|
||||
{
|
||||
G4CerenkovQuasiTrackInfo* CATI = nullptr;
|
||||
if(aATI != nullptr)
|
||||
{
|
||||
// No change will be done to the pointer and to the pointed data
|
||||
auto temp = const_cast<G4VAuxiliaryTrackInformation*>(aATI);
|
||||
CATI = dynamic_cast<G4CerenkovQuasiTrackInfo*>(temp);
|
||||
}
|
||||
return CATI;
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// G4GeneralCerenkov
|
||||
//
|
||||
// Created 25.05.2025 V.Ivanchenko
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "G4GeneralCerenkov.hh"
|
||||
#include "G4StandardCerenkovModel.hh"
|
||||
|
||||
#include "G4Material.hh"
|
||||
#include "G4MaterialPropertiesTable.hh"
|
||||
#include "G4OpticalParameters.hh"
|
||||
#include "G4PhysicsModelCatalog.hh"
|
||||
#include "G4EmProcessSubType.hh"
|
||||
#include "G4LogicalVolumeStore.hh"
|
||||
|
||||
std::vector<std::vector<const G4LogicalVolume*>* >* G4GeneralCerenkov::fLV = nullptr;
|
||||
std::vector<G4VXRayModel*>* G4GeneralCerenkov::fSharedModels = nullptr;
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4GeneralCerenkov::G4GeneralCerenkov(const G4String& nam, G4ProcessType type)
|
||||
: G4VDiscreteProcess(nam, type)
|
||||
{
|
||||
secID = G4PhysicsModelCatalog::GetModelID("model_Cerenkov");
|
||||
SetProcessSubType(fCerenkov);
|
||||
if (nullptr == fLV) {
|
||||
// initialise static data
|
||||
fSharedModels = new std::vector<G4VXRayModel*>;
|
||||
fLV = new std::vector<std::vector<const G4LogicalVolume*>* >;
|
||||
fLVNames = new std::vector<G4String>;
|
||||
|
||||
isInitializer = true;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4GeneralCerenkov::~G4GeneralCerenkov()
|
||||
{
|
||||
if (isInitializer) {
|
||||
delete fSharedModels;
|
||||
fSharedModels = nullptr;
|
||||
delete fLVNames;
|
||||
for (auto const & p : *fLV) {
|
||||
delete p;
|
||||
}
|
||||
delete fLV;
|
||||
fLV = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4bool G4GeneralCerenkov::IsApplicable(const G4ParticleDefinition&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4GeneralCerenkov::AddModelForVolume(G4VXRayModel* model,
|
||||
const G4String& nameLogVolume)
|
||||
{
|
||||
if (isPrepared || !isInitializer || nullptr == model) {
|
||||
G4ExceptionDescription ed;
|
||||
G4String nam;
|
||||
if (model != nullptr) { nam = model->GetName(); }
|
||||
ed << " Attempt to add Cerenkov model <" << nam << "> for LogicalVolume "
|
||||
<< nameLogVolume << " is failed!\n isPrepared:" << isPrepared
|
||||
<< " isInitilizer:" << isInitializer;
|
||||
G4Exception("G4GeneralCerenkov::AddModelForVolume", "em0304",
|
||||
FatalException, ed, "");
|
||||
return;
|
||||
}
|
||||
fSharedModels->push_back(model);
|
||||
fLVNames->push_back(nameLogVolume);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4GeneralCerenkov::PreparePhysicsTable(const G4ParticleDefinition&)
|
||||
{
|
||||
// definition of models is done only once
|
||||
if (isPrepared) { return; }
|
||||
isPrepared = true;
|
||||
|
||||
const G4OpticalParameters* params = G4OpticalParameters::Instance();
|
||||
fMaxBetaChange = params->GetCerenkovMaxBetaChange();
|
||||
fMaxPhotons = params->GetCerenkovMaxPhotonsPerStep();
|
||||
fStackingFlag = params->GetCerenkovStackPhotons();
|
||||
fTrackSecondariesFirst = params->GetCerenkovTrackSecondariesFirst();
|
||||
verboseLevel = params->GetCerenkovVerboseLevel();
|
||||
|
||||
auto nmod = fSharedModels->size();
|
||||
if (0 == nmod) {
|
||||
// the default model is added without association with a logical volume
|
||||
G4VXRayModel* mod = new G4StandardCerenkovModel();
|
||||
fSharedModels->push_back(mod);
|
||||
nmod = 1;
|
||||
}
|
||||
|
||||
fSecondaries.reserve(fMaxPhotons);
|
||||
nModels = (G4int)nmod;
|
||||
|
||||
// fill static data structures
|
||||
if (isInitializer) {
|
||||
const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
|
||||
const auto & modAndVol = params->ActiveVolumes();
|
||||
|
||||
// preparation of logical volume vector per model
|
||||
fLV->reserve(nmod);
|
||||
for (G4int i=0; i<nModels; ++i) {
|
||||
auto v = new std::vector<const G4LogicalVolume*>;
|
||||
fLV->push_back(v);
|
||||
}
|
||||
|
||||
for (auto const & lv : *lvs) {
|
||||
// only volumes with material property defined are considered
|
||||
auto const MPT = lv->GetMaterial()->GetMaterialPropertiesTable();
|
||||
if (nullptr == MPT) { continue; }
|
||||
|
||||
const G4String& lvname = lv->GetName();
|
||||
G4bool ok{false};
|
||||
// search for the default model in the list
|
||||
if (!modAndVol.empty()) {
|
||||
for (auto const & it : modAndVol) {
|
||||
if (it.second == lvname) {
|
||||
if (kCerenkovDefault == it.first) {
|
||||
(*fLV)[0]->push_back(lv);
|
||||
fLVNames->push_back(lvname);
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ok) { continue; }
|
||||
|
||||
// search in external models
|
||||
for (G4int i=0; i<nModels; ++i) {
|
||||
if (lvname == (*fLVNames)[i]) {
|
||||
(*fLV)[i]->push_back(lv);
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) { continue; }
|
||||
|
||||
// temporary for backward compatibility search for a RINDEX of the volume
|
||||
if (nullptr != MPT->GetProperty(kRINDEX)) {
|
||||
(*fLV)[0]->push_back(lv);
|
||||
fLVNames->push_back(lvname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4GeneralCerenkov::BuildPhysicsTable(const G4ParticleDefinition&)
|
||||
{
|
||||
// Initialisation of models is done only once
|
||||
if (isBuilt) { return; }
|
||||
isBuilt = true;
|
||||
if (nModels == 0) { return; }
|
||||
|
||||
// worker thread
|
||||
if (!isInitializer) {
|
||||
// worker initialisation - clone master models
|
||||
fModels.reserve(nModels);
|
||||
for (G4int i=0; i<nModels; ++i) {
|
||||
auto newmod = new G4VXRayModel(*((*fSharedModels)[i]));
|
||||
fModels.push_back(newmod);
|
||||
G4double b = newmod->Initialise((*fLV)[i]);
|
||||
fBetaMin = std::min(fBetaMin, b);
|
||||
}
|
||||
} else if (verboseLevel > 0) {
|
||||
// needed for printout
|
||||
std::size_t nn = 0;
|
||||
for (G4int i=0; i<nModels; ++i) {
|
||||
G4double b = (*fSharedModels)[i]->Initialise((*fLV)[i]);
|
||||
fBetaMin = std::min(fBetaMin, b);
|
||||
nn += ((*fLV)[i])->size();
|
||||
}
|
||||
G4long pres = G4cout.precision();
|
||||
G4cout.precision(6);
|
||||
G4cout << " " << GetProcessName() << std::setw(20) << " fBetaMin=" << fBetaMin
|
||||
<< " fMaxBetaChange=" << fMaxBetaChange << G4endl;
|
||||
G4cout << std::setw(20) << "fMaxNphot=" << fMaxPhotons
|
||||
<< " Nlv=" << nn << " fStackingFlag:" << fStackingFlag
|
||||
<< " fTrackSecondariesFirst:" << fTrackSecondariesFirst
|
||||
<< G4endl;
|
||||
for (G4int i=0; i<nModels; ++i) {
|
||||
G4int n = (G4int)((*fLV)[i]->size());
|
||||
G4cout << std::setw(10) << (*fSharedModels)[i]->GetName()
|
||||
<< std::setw(30) << "Nvolumes=" << n << " Volumes:" << G4endl;
|
||||
G4cout << std::setw(12);
|
||||
for (G4int j=0; j<n; ++j) {
|
||||
G4cout << (*((*fLV)[i]))[j]->GetName() << " ";
|
||||
if (0 != j && (j/5)*5 == j) {
|
||||
G4cout << G4endl << std::setw(12);
|
||||
}
|
||||
}
|
||||
G4cout << G4endl;
|
||||
}
|
||||
G4cout.precision(pres);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4double
|
||||
G4GeneralCerenkov::PostStepGetPhysicalInteractionLength(const G4Track& aTrack,
|
||||
G4double,
|
||||
G4ForceCondition* cond)
|
||||
{
|
||||
*cond = NotForced;
|
||||
G4double limit = DBL_MAX;
|
||||
auto const dp = aTrack.GetDynamicParticle();
|
||||
if (dp->GetCharge() == 0.0) { return limit; }
|
||||
fCurrentModel = nullptr;
|
||||
fPreStepBeta = dp->GetBeta();
|
||||
if (fPreStepBeta <= fBetaMin) { return limit; }
|
||||
|
||||
auto volume = aTrack.GetVolume();
|
||||
if (nullptr == volume) { return limit; }
|
||||
|
||||
fCurrentLV = volume->GetLogicalVolume();
|
||||
auto const MPT = fCurrentLV->GetMaterial()->GetMaterialPropertiesTable();
|
||||
if (nullptr == MPT) { return limit; }
|
||||
|
||||
G4bool ok{false};
|
||||
for (G4int i=0; i<nModels; ++i) {
|
||||
auto const v = (*fLV)[i];
|
||||
std::size_t nn = v->size();
|
||||
for (std::size_t j = 0; j < nn; ++j) {
|
||||
if ((*v)[j] == fCurrentLV) {
|
||||
fCurrentModel = fModels[i];
|
||||
if (fCurrentModel->StepLimit(j, aTrack, fPreStepBeta, limit)) {
|
||||
*cond = StronglyForced;
|
||||
}
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) { break; }
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4VParticleChange* G4GeneralCerenkov::PostStepDoIt(const G4Track& aTrack,
|
||||
const G4Step& aStep)
|
||||
{
|
||||
aParticleChange.Initialize(aTrack);
|
||||
if (fCurrentModel == nullptr) { return &aParticleChange; }
|
||||
fCurrentModel->SampleXRays(fSecondaries, aStep);
|
||||
if (!fSecondaries.empty()) {
|
||||
|
||||
// X-rays
|
||||
auto touch = aStep.GetPreStepPoint()->GetTouchableHandle();
|
||||
G4int parent = aTrack.GetTrackID();
|
||||
for (auto & t : fSecondaries) {
|
||||
t->SetTouchableHandle(touch);
|
||||
t->SetParentID(parent);
|
||||
t->SetCreatorModelID(secID);
|
||||
aParticleChange.AddSecondary(t);
|
||||
}
|
||||
fSecondaries.clear();
|
||||
|
||||
// primary track suspended
|
||||
if (fTrackSecondariesFirst && aTrack.GetTrackStatus() == fAlive) {
|
||||
aParticleChange.ProposeTrackStatus(fSuspend);
|
||||
}
|
||||
}
|
||||
return &aParticleChange;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4GeneralCerenkov::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "The Cerenkov effect simulates optical photons created by the\n";
|
||||
out << "passage of charged particles through matter. Materials need\n";
|
||||
out << "to have the property RINDEX (refractive index) defined." << G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4GeneralCerenkov::SetTrackSecondariesFirst(const G4bool state)
|
||||
{
|
||||
fTrackSecondariesFirst = state;
|
||||
G4OpticalParameters::Instance()->SetCerenkovTrackSecondariesFirst(
|
||||
fTrackSecondariesFirst);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4GeneralCerenkov::SetMaxBetaChangePerStep(const G4double value)
|
||||
{
|
||||
fMaxBetaChange = value;
|
||||
G4OpticalParameters::Instance()->SetCerenkovMaxBetaChange(value);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4GeneralCerenkov::SetMaxNumPhotonsPerStep(const G4int NumPhotons)
|
||||
{
|
||||
fMaxPhotons = NumPhotons;
|
||||
G4OpticalParameters::Instance()->SetCerenkovMaxPhotonsPerStep(fMaxPhotons);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4GeneralCerenkov::SetStackPhotons(const G4bool stackingFlag)
|
||||
{
|
||||
fStackingFlag = stackingFlag;
|
||||
G4OpticalParameters::Instance()->SetCerenkovStackPhotons(fStackingFlag);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4GeneralCerenkov::SetVerboseLevel(G4int verbose)
|
||||
{
|
||||
verboseLevel = verbose;
|
||||
G4OpticalParameters::Instance()->SetCerenkovVerboseLevel(verboseLevel);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4double
|
||||
G4GeneralCerenkov::GetMeanFreePath(const G4Track&, G4double, G4ForceCondition*)
|
||||
{
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -0,0 +1,653 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "G4QuasiCerenkov.hh"
|
||||
#include "G4CerenkovQuasiTrackInfo.hh"
|
||||
|
||||
#include "G4ios.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4Material.hh"
|
||||
#include "G4MaterialCutsCouple.hh"
|
||||
#include "G4MaterialPropertiesTable.hh"
|
||||
#include "G4OpticalParameters.hh"
|
||||
#include "G4OpticalPhoton.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "G4ParticleMomentum.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4PhysicsFreeVector.hh"
|
||||
#include "G4Poisson.hh"
|
||||
#include "G4QuasiOpticalData.hh"
|
||||
#include "G4QuasiOpticalPhoton.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4PhysicsModelCatalog.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4QuasiCerenkov::G4QuasiCerenkov(const G4String& processName, G4ProcessType type)
|
||||
: G4VProcess(processName, type)
|
||||
, fNumPhotons(0)
|
||||
{
|
||||
secID = G4PhysicsModelCatalog::GetModelID("model_QuasiCerenkov");
|
||||
SetProcessSubType(fCerenkov);
|
||||
|
||||
thePhysicsTable = nullptr;
|
||||
|
||||
if(verboseLevel > 0)
|
||||
{
|
||||
G4cout << GetProcessName() << " is created." << G4endl;
|
||||
}
|
||||
Initialise();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4QuasiCerenkov::~G4QuasiCerenkov()
|
||||
{
|
||||
if(thePhysicsTable != nullptr)
|
||||
{
|
||||
thePhysicsTable->clearAndDestroy();
|
||||
delete thePhysicsTable;
|
||||
}
|
||||
}
|
||||
|
||||
void G4QuasiCerenkov::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "The Cerenkov effect simulates optical photons created by the\n";
|
||||
out << "passage of charged particles through matter. Materials need\n";
|
||||
out << "to have the property RINDEX (refractive index) defined.\n";
|
||||
G4VProcess::DumpInfo();
|
||||
|
||||
G4OpticalParameters* params = G4OpticalParameters::Instance();
|
||||
out << "Maximum beta change per step: " << params->GetCerenkovMaxBetaChange();
|
||||
out << "Maximum photons per step: " << params->GetCerenkovMaxPhotonsPerStep();
|
||||
out << "Track secondaries first: "
|
||||
<< params->GetCerenkovTrackSecondariesFirst();
|
||||
out << "Stack photons: " << params->GetCerenkovStackPhotons();
|
||||
out << "Verbose level: " << params->GetCerenkovVerboseLevel();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4bool G4QuasiCerenkov::IsApplicable(const G4ParticleDefinition& aParticleType)
|
||||
{
|
||||
return (aParticleType.GetPDGCharge() != 0.0 &&
|
||||
aParticleType.GetPDGMass() != 0.0 &&
|
||||
aParticleType.GetParticleName() != "chargedgeantino" &&
|
||||
!aParticleType.IsShortLived())
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiCerenkov::Initialise()
|
||||
{
|
||||
G4OpticalParameters* params = G4OpticalParameters::Instance();
|
||||
SetMaxBetaChangePerStep(params->GetCerenkovMaxBetaChange());
|
||||
SetMaxNumPhotonsPerStep(params->GetCerenkovMaxPhotonsPerStep());
|
||||
SetTrackSecondariesFirst(params->GetCerenkovTrackSecondariesFirst());
|
||||
SetStackPhotons(params->GetCerenkovStackPhotons());
|
||||
SetOffloadPhotons(params->GetCerenkovOffloadPhotons());
|
||||
SetVerboseLevel(params->GetCerenkovVerboseLevel());
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiCerenkov::BuildPhysicsTable(const G4ParticleDefinition&)
|
||||
{
|
||||
if(thePhysicsTable)
|
||||
return;
|
||||
|
||||
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
|
||||
std::size_t numOfMaterials = G4Material::GetNumberOfMaterials();
|
||||
|
||||
// Find the number of materials that have non-empty material property tables
|
||||
std::size_t numOfMaterialsWithMPT = 0;
|
||||
for(std::size_t i = 0; i < numOfMaterials; ++i)
|
||||
{
|
||||
if(((*theMaterialTable)[i])->GetMaterialPropertiesTable())
|
||||
{
|
||||
++numOfMaterialsWithMPT;
|
||||
}
|
||||
}
|
||||
|
||||
thePhysicsTable = new G4PhysicsTable(numOfMaterialsWithMPT);
|
||||
|
||||
// loop over materials
|
||||
std::size_t indexMPT = 0;
|
||||
for(std::size_t i = 0; i < numOfMaterials; ++i)
|
||||
{
|
||||
G4PhysicsFreeVector* cerenkovIntegral = nullptr;
|
||||
|
||||
// Retrieve vector of refraction indices for the material
|
||||
// from the material's optical properties table
|
||||
G4Material* aMaterial = (*theMaterialTable)[i];
|
||||
G4MaterialPropertiesTable* MPT = aMaterial->GetMaterialPropertiesTable();
|
||||
|
||||
if(MPT)
|
||||
{
|
||||
cerenkovIntegral = new G4PhysicsFreeVector();
|
||||
G4MaterialPropertyVector* refractiveIndex = MPT->GetProperty(kRINDEX);
|
||||
|
||||
if(refractiveIndex)
|
||||
{
|
||||
// Retrieve the first refraction index in vector
|
||||
// of (photon energy, refraction index) pairs
|
||||
G4double currentRI = (*refractiveIndex)[0];
|
||||
if(currentRI > 1.0)
|
||||
{
|
||||
// Create first (photon energy, Cerenkov Integral) pair
|
||||
G4double currentPM = refractiveIndex->Energy(0);
|
||||
G4double currentCAI = 0.0;
|
||||
|
||||
cerenkovIntegral->InsertValues(currentPM, currentCAI);
|
||||
|
||||
// Set previous values to current ones prior to loop
|
||||
G4double prevPM = currentPM;
|
||||
G4double prevCAI = currentCAI;
|
||||
G4double prevRI = currentRI;
|
||||
|
||||
// loop over all (photon energy, refraction index)
|
||||
// pairs stored for this material
|
||||
for(std::size_t ii = 1; ii < refractiveIndex->GetVectorLength(); ++ii)
|
||||
{
|
||||
currentRI = (*refractiveIndex)[ii];
|
||||
currentPM = refractiveIndex->Energy(ii);
|
||||
currentCAI = prevCAI + (currentPM - prevPM) * 0.5 *
|
||||
(1.0 / (prevRI * prevRI) +
|
||||
1.0 / (currentRI * currentRI));
|
||||
|
||||
cerenkovIntegral->InsertValues(currentPM, currentCAI);
|
||||
|
||||
prevPM = currentPM;
|
||||
prevCAI = currentCAI;
|
||||
prevRI = currentRI;
|
||||
}
|
||||
}
|
||||
}
|
||||
// The Cerenkov integral for a given material will be inserted in
|
||||
// thePhysicsTable according to the position of the material in
|
||||
// the material table.
|
||||
thePhysicsTable->insertAt(indexMPT, cerenkovIntegral);
|
||||
fIndexMPT.insert(std::make_pair(i, indexMPT));
|
||||
++indexMPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4VParticleChange* G4QuasiCerenkov::PostStepDoIt(const G4Track& aTrack,
|
||||
const G4Step& aStep)
|
||||
// This routine is called for each tracking Step of a charged particle
|
||||
// in a radiator. A Poisson-distributed number of photons is generated
|
||||
// according to the Cerenkov formula, distributed evenly along the track
|
||||
// segment and uniformly azimuth w.r.t. the particle direction. The
|
||||
// parameters are then transformed into the Master Reference System, and
|
||||
// they are added to the particle change.
|
||||
|
||||
{
|
||||
aParticleChange.Initialize(aTrack);
|
||||
|
||||
const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
|
||||
const G4Material* aMaterial = aTrack.GetMaterial();
|
||||
|
||||
G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
|
||||
G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
|
||||
|
||||
G4ThreeVector x0 = pPreStepPoint->GetPosition();
|
||||
G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
|
||||
G4double t0 = pPreStepPoint->GetGlobalTime();
|
||||
|
||||
G4MaterialPropertiesTable* MPT = aMaterial->GetMaterialPropertiesTable();
|
||||
if(!MPT)
|
||||
return pParticleChange;
|
||||
|
||||
G4MaterialPropertyVector* Rindex = MPT->GetProperty(kRINDEX);
|
||||
if(!Rindex)
|
||||
return pParticleChange;
|
||||
|
||||
G4double charge = aParticle->GetDefinition()->GetPDGCharge();
|
||||
|
||||
G4double beta1 = pPreStepPoint->GetBeta();
|
||||
G4double beta2 = pPostStepPoint->GetBeta();
|
||||
G4double beta = (beta1 + beta2) * 0.5;
|
||||
|
||||
G4double MeanNumberOfPhotons =
|
||||
GetAverageNumberOfPhotons(charge, beta, aMaterial, Rindex);
|
||||
G4double MeanNumberOfPhotons1 =
|
||||
GetAverageNumberOfPhotons(charge, beta1, aMaterial, Rindex);
|
||||
G4double MeanNumberOfPhotons2 =
|
||||
GetAverageNumberOfPhotons(charge, beta2, aMaterial, Rindex);
|
||||
|
||||
if(MeanNumberOfPhotons <= 0.0)
|
||||
{
|
||||
// return unchanged particle and no secondaries
|
||||
aParticleChange.SetNumberOfSecondaries(0);
|
||||
return pParticleChange;
|
||||
}
|
||||
|
||||
MeanNumberOfPhotons *= aStep.GetStepLength();
|
||||
fNumPhotons = (G4int) G4Poisson(MeanNumberOfPhotons);
|
||||
|
||||
// third condition added to prevent infinite loop in do-while below,
|
||||
// see bugzilla 2555
|
||||
if(fNumPhotons <= 0 || !fStackingFlag ||
|
||||
std::max(MeanNumberOfPhotons1, MeanNumberOfPhotons2) < 1e-15)
|
||||
{
|
||||
// return unchanged particle and no secondaries
|
||||
aParticleChange.SetNumberOfSecondaries(0);
|
||||
return pParticleChange;
|
||||
}
|
||||
|
||||
G4double deltaVelocity = pPostStepPoint->GetVelocity() -
|
||||
pPreStepPoint->GetVelocity();
|
||||
auto touchableHandle = aStep.GetPreStepPoint()->GetTouchableHandle();
|
||||
|
||||
if(fOffloadingFlag)
|
||||
{
|
||||
// Create a G4DynamicParticle with G4QuasiOpticalPhoton
|
||||
auto quasiPhoton = new G4DynamicParticle(
|
||||
G4QuasiOpticalPhoton::QuasiOpticalPhotonDefinition(),
|
||||
aParticle->GetMomentum());
|
||||
|
||||
// Create a new G4Track object with the quasi-optical photon
|
||||
G4Track* aSecondaryTrack = new G4Track(quasiPhoton, t0, x0);
|
||||
aSecondaryTrack->SetTouchableHandle(touchableHandle);
|
||||
aSecondaryTrack->SetParentID(aTrack.GetTrackID());
|
||||
aSecondaryTrack->SetCreatorModelID(secID);
|
||||
|
||||
// Attach auxiliary track information with associated metadata
|
||||
G4QuasiOpticalData quasiTrackData{aMaterial->GetIndex(), fNumPhotons,
|
||||
charge, aStep.GetStepLength(), pPreStepPoint->GetVelocity(),
|
||||
deltaVelocity, aStep.GetDeltaPosition()};
|
||||
aSecondaryTrack->SetAuxiliaryTrackInformation(secID,
|
||||
new G4CerenkovQuasiTrackInfo(quasiTrackData,
|
||||
MeanNumberOfPhotons1, MeanNumberOfPhotons2));
|
||||
aParticleChange.AddSecondary(aSecondaryTrack);
|
||||
|
||||
// Return early when offloading is enabled
|
||||
return pParticleChange;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
aParticleChange.SetNumberOfSecondaries(fNumPhotons);
|
||||
|
||||
if(fTrackSecondariesFirst)
|
||||
{
|
||||
if(aTrack.GetTrackStatus() == fAlive)
|
||||
aParticleChange.ProposeTrackStatus(fSuspend);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
G4double Pmin = Rindex->Energy(0);
|
||||
G4double Pmax = Rindex->GetMaxEnergy();
|
||||
G4double dp = Pmax - Pmin;
|
||||
G4double deltaNumberOfPhotons = MeanNumberOfPhotons1 - MeanNumberOfPhotons2;
|
||||
G4double maxNumberOfPhotons =
|
||||
std::max(MeanNumberOfPhotons1, MeanNumberOfPhotons2);
|
||||
|
||||
G4double nMax = Rindex->GetMaxValue();
|
||||
G4double BetaInverse = 1. / beta;
|
||||
|
||||
G4double maxCos = BetaInverse / nMax;
|
||||
G4double maxSin2 = 1.0 - maxCos * maxCos;
|
||||
|
||||
for(G4int i = 0; i < fNumPhotons; ++i)
|
||||
{
|
||||
// Determine photon energy
|
||||
G4double rand;
|
||||
G4double sampledEnergy;
|
||||
G4double cosTheta, sin2Theta;
|
||||
|
||||
// sample an energy
|
||||
do
|
||||
{
|
||||
rand = G4UniformRand();
|
||||
sampledEnergy = Pmin + rand * dp;
|
||||
cosTheta = BetaInverse / Rindex->Value(sampledEnergy);
|
||||
|
||||
sin2Theta = 1.0 - cosTheta * cosTheta;
|
||||
rand = G4UniformRand();
|
||||
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
} while(rand * maxSin2 > sin2Theta);
|
||||
|
||||
// Create photon momentum direction vector. The momentum direction is still
|
||||
// with respect to the coordinate system where the primary particle
|
||||
// direction is aligned with the z axis
|
||||
rand = G4UniformRand();
|
||||
G4double phi = twopi * rand;
|
||||
G4double sinPhi = std::sin(phi);
|
||||
G4double cosPhi = std::cos(phi);
|
||||
G4double sinTheta = std::sqrt(sin2Theta);
|
||||
G4ParticleMomentum photonMomentum(sinTheta * cosPhi, sinTheta * sinPhi,
|
||||
cosTheta);
|
||||
|
||||
// Rotate momentum direction back to global reference system
|
||||
photonMomentum.rotateUz(p0);
|
||||
|
||||
// Determine polarization of new photon
|
||||
G4ThreeVector photonPolarization(cosTheta * cosPhi, cosTheta * sinPhi,
|
||||
-sinTheta);
|
||||
|
||||
// Rotate back to original coord system
|
||||
photonPolarization.rotateUz(p0);
|
||||
|
||||
// Generate a new photon:
|
||||
auto aCerenkovPhoton =
|
||||
new G4DynamicParticle(G4OpticalPhoton::OpticalPhoton(), photonMomentum);
|
||||
|
||||
aCerenkovPhoton->SetPolarization(photonPolarization);
|
||||
aCerenkovPhoton->SetKineticEnergy(sampledEnergy);
|
||||
|
||||
G4double NumberOfPhotons;
|
||||
|
||||
do
|
||||
{
|
||||
rand = G4UniformRand();
|
||||
NumberOfPhotons = MeanNumberOfPhotons1 - rand * deltaNumberOfPhotons;
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
} while(G4UniformRand() * maxNumberOfPhotons > NumberOfPhotons);
|
||||
|
||||
G4double delta = rand * aStep.GetStepLength();
|
||||
G4double deltaTime =
|
||||
delta / (pPreStepPoint->GetVelocity() + rand * deltaVelocity * 0.5);
|
||||
|
||||
G4double aSecondaryTime = t0 + deltaTime;
|
||||
G4ThreeVector aSecondaryPosition = x0 + rand * aStep.GetDeltaPosition();
|
||||
|
||||
// Generate new G4Track object:
|
||||
G4Track* aSecondaryTrack =
|
||||
new G4Track(aCerenkovPhoton, aSecondaryTime, aSecondaryPosition);
|
||||
|
||||
aSecondaryTrack->SetTouchableHandle(touchableHandle);
|
||||
aSecondaryTrack->SetParentID(aTrack.GetTrackID());
|
||||
aSecondaryTrack->SetCreatorModelID(secID);
|
||||
aParticleChange.AddSecondary(aSecondaryTrack);
|
||||
}
|
||||
|
||||
if(verboseLevel > 1)
|
||||
{
|
||||
G4cout << "\n Exiting from G4QuasiCerenkov::DoIt -- NumberOfSecondaries = "
|
||||
<< aParticleChange.GetNumberOfSecondaries() << G4endl;
|
||||
}
|
||||
|
||||
return pParticleChange;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiCerenkov::PreparePhysicsTable(const G4ParticleDefinition&)
|
||||
{
|
||||
Initialise();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4double G4QuasiCerenkov::GetMeanFreePath(const G4Track&, G4double,
|
||||
G4ForceCondition*)
|
||||
{
|
||||
return 1.;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4double G4QuasiCerenkov::PostStepGetPhysicalInteractionLength(
|
||||
const G4Track& aTrack, G4double, G4ForceCondition* condition)
|
||||
{
|
||||
*condition = NotForced;
|
||||
G4double StepLimit = DBL_MAX;
|
||||
fNumPhotons = 0;
|
||||
|
||||
const G4Material* aMaterial = aTrack.GetMaterial();
|
||||
std::size_t materialIndex = aMaterial->GetIndex();
|
||||
|
||||
// If Physics Vector is not defined no Cerenkov photons
|
||||
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
|
||||
G4MaterialPropertiesTable* MPT =
|
||||
((*materialTable)[materialIndex])->GetMaterialPropertiesTable();
|
||||
// if(!(*thePhysicsTable)[materialIndex])
|
||||
if(!MPT)
|
||||
{
|
||||
return StepLimit;
|
||||
}
|
||||
|
||||
const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
|
||||
const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
|
||||
|
||||
G4double kineticEnergy = aParticle->GetKineticEnergy();
|
||||
const G4ParticleDefinition* particleType = aParticle->GetDefinition();
|
||||
G4double mass = particleType->GetPDGMass();
|
||||
|
||||
G4double beta = aParticle->GetTotalMomentum() / aParticle->GetTotalEnergy();
|
||||
G4double gamma = aParticle->GetTotalEnergy() / mass;
|
||||
|
||||
G4MaterialPropertiesTable* aMaterialPropertiesTable =
|
||||
aMaterial->GetMaterialPropertiesTable();
|
||||
|
||||
G4MaterialPropertyVector* Rindex = nullptr;
|
||||
|
||||
if(aMaterialPropertiesTable)
|
||||
Rindex = aMaterialPropertiesTable->GetProperty(kRINDEX);
|
||||
|
||||
G4double nMax;
|
||||
if(Rindex)
|
||||
{
|
||||
nMax = Rindex->GetMaxValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
return StepLimit;
|
||||
}
|
||||
|
||||
G4double BetaMin = 1. / nMax;
|
||||
if(BetaMin >= 1.)
|
||||
return StepLimit;
|
||||
|
||||
G4double GammaMin = 1. / std::sqrt(1. - BetaMin * BetaMin);
|
||||
if(gamma < GammaMin)
|
||||
return StepLimit;
|
||||
|
||||
G4double kinEmin = mass * (GammaMin - 1.);
|
||||
G4double RangeMin =
|
||||
G4LossTableManager::Instance()->GetRange(particleType, kinEmin, couple);
|
||||
G4double Range = G4LossTableManager::Instance()->GetRange(
|
||||
particleType, kineticEnergy, couple);
|
||||
G4double Step = Range - RangeMin;
|
||||
|
||||
// If the step is smaller than G4ThreeVector::getTolerance(), it may happen
|
||||
// that the particle does not move. See bug 1992.
|
||||
static const G4double minAllowedStep = G4ThreeVector::getTolerance();
|
||||
if(Step < minAllowedStep)
|
||||
return StepLimit;
|
||||
|
||||
if(Step < StepLimit)
|
||||
StepLimit = Step;
|
||||
|
||||
// If user has defined an average maximum number of photons to be generated in
|
||||
// a Step, then calculate the Step length for that number of photons.
|
||||
if(fMaxPhotons > 0)
|
||||
{
|
||||
const G4double charge = aParticle->GetDefinition()->GetPDGCharge();
|
||||
G4double MeanNumberOfPhotons =
|
||||
GetAverageNumberOfPhotons(charge, beta, aMaterial, Rindex);
|
||||
Step = 0.;
|
||||
if(MeanNumberOfPhotons > 0.0)
|
||||
Step = fMaxPhotons / MeanNumberOfPhotons;
|
||||
if(Step > 0. && Step < StepLimit)
|
||||
StepLimit = Step;
|
||||
}
|
||||
|
||||
// If user has defined an maximum allowed change in beta per step
|
||||
if(fMaxBetaChange > 0.)
|
||||
{
|
||||
G4double dedx = G4LossTableManager::Instance()->GetDEDX(
|
||||
particleType, kineticEnergy, couple);
|
||||
G4double deltaGamma =
|
||||
gamma - 1. / std::sqrt(1. - beta * beta * (1. - fMaxBetaChange) *
|
||||
(1. - fMaxBetaChange));
|
||||
|
||||
Step = mass * deltaGamma / dedx;
|
||||
if(Step > 0. && Step < StepLimit)
|
||||
StepLimit = Step;
|
||||
}
|
||||
|
||||
*condition = StronglyForced;
|
||||
return StepLimit;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4double G4QuasiCerenkov::GetAverageNumberOfPhotons(
|
||||
const G4double charge, const G4double beta, const G4Material* aMaterial,
|
||||
G4MaterialPropertyVector* Rindex) const
|
||||
// This routine computes the number of Cerenkov photons produced per
|
||||
// Geant4-unit (millimeter) in the current medium.
|
||||
{
|
||||
constexpr G4double Rfact = 369.81 / (eV * cm);
|
||||
if(beta <= 0.0)
|
||||
return 0.0;
|
||||
G4double BetaInverse = 1. / beta;
|
||||
|
||||
// Vectors used in computation of Cerenkov Angle Integral:
|
||||
// - Refraction Indices for the current material
|
||||
// - new G4PhysicsFreeVector allocated to hold CAI's
|
||||
std::size_t materialIndex = aMaterial->GetIndex();
|
||||
|
||||
// Retrieve the Cerenkov Angle Integrals for this material
|
||||
auto it = fIndexMPT.find(materialIndex);
|
||||
|
||||
std::size_t indexMPT = 0;
|
||||
if(it != fIndexMPT.end())
|
||||
{
|
||||
indexMPT = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
G4ExceptionDescription ed;
|
||||
ed << "G4MaterialPropertiesTable for " << aMaterial->GetName()
|
||||
<< " is not found!" << G4endl;
|
||||
G4Exception("G4QuasiCerenkov::GetAverageNumberOfPhotons",
|
||||
"QuasiCerenkovCerenkov01", FatalException, ed);
|
||||
}
|
||||
|
||||
G4PhysicsVector* CerenkovAngleIntegrals = ((*thePhysicsTable)(indexMPT));
|
||||
|
||||
std::size_t length = CerenkovAngleIntegrals->GetVectorLength();
|
||||
if(0 == length)
|
||||
return 0.0;
|
||||
|
||||
// Min and Max photon energies
|
||||
G4double Pmin = Rindex->Energy(0);
|
||||
G4double Pmax = Rindex->GetMaxEnergy();
|
||||
|
||||
// Min and Max Refraction Indices
|
||||
G4double nMin = Rindex->GetMinValue();
|
||||
G4double nMax = Rindex->GetMaxValue();
|
||||
|
||||
// Max Cerenkov Angle Integral
|
||||
G4double CAImax = (*CerenkovAngleIntegrals)[length - 1];
|
||||
|
||||
G4double dp, ge;
|
||||
// If n(Pmax) < 1/Beta -- no photons generated
|
||||
if(nMax < BetaInverse)
|
||||
{
|
||||
dp = 0.0;
|
||||
ge = 0.0;
|
||||
}
|
||||
// otherwise if n(Pmin) >= 1/Beta -- photons generated
|
||||
else if(nMin > BetaInverse)
|
||||
{
|
||||
dp = Pmax - Pmin;
|
||||
ge = CAImax;
|
||||
}
|
||||
// If n(Pmin) < 1/Beta, and n(Pmax) >= 1/Beta, then we need to find a P such
|
||||
// that the value of n(P) == 1/Beta. Interpolation is performed by the
|
||||
// GetEnergy() and Value() methods of the G4MaterialPropertiesTable and
|
||||
// the Value() method of G4PhysicsVector.
|
||||
else
|
||||
{
|
||||
Pmin = Rindex->GetEnergy(BetaInverse);
|
||||
dp = Pmax - Pmin;
|
||||
|
||||
G4double CAImin = CerenkovAngleIntegrals->Value(Pmin);
|
||||
ge = CAImax - CAImin;
|
||||
|
||||
if(verboseLevel > 1)
|
||||
{
|
||||
G4cout << "CAImin = " << CAImin << G4endl << "ge = " << ge << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate number of photons
|
||||
G4double NumPhotons = Rfact * charge / eplus * charge / eplus *
|
||||
(dp - ge * BetaInverse * BetaInverse);
|
||||
|
||||
return NumPhotons;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiCerenkov::SetTrackSecondariesFirst(const G4bool state)
|
||||
{
|
||||
fTrackSecondariesFirst = state;
|
||||
G4OpticalParameters::Instance()->SetCerenkovTrackSecondariesFirst(
|
||||
fTrackSecondariesFirst);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiCerenkov::SetMaxBetaChangePerStep(const G4double value)
|
||||
{
|
||||
fMaxBetaChange = value * CLHEP::perCent;
|
||||
G4OpticalParameters::Instance()->SetCerenkovMaxBetaChange(value);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiCerenkov::SetMaxNumPhotonsPerStep(const G4int NumPhotons)
|
||||
{
|
||||
fMaxPhotons = NumPhotons;
|
||||
G4OpticalParameters::Instance()->SetCerenkovMaxPhotonsPerStep(fMaxPhotons);
|
||||
}
|
||||
|
||||
void G4QuasiCerenkov::SetStackPhotons(const G4bool stackingFlag)
|
||||
{
|
||||
fStackingFlag = stackingFlag;
|
||||
G4OpticalParameters::Instance()->SetCerenkovStackPhotons(fStackingFlag);
|
||||
}
|
||||
|
||||
void G4QuasiCerenkov::SetOffloadPhotons(const G4bool offloadingFlag)
|
||||
{
|
||||
fOffloadingFlag = offloadingFlag;
|
||||
G4OpticalParameters::Instance()->SetCerenkovOffloadPhotons(fOffloadingFlag);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiCerenkov::DumpPhysicsTable() const
|
||||
{
|
||||
G4cout << "Dump Physics Table!" << G4endl;
|
||||
for(std::size_t i = 0; i < thePhysicsTable->entries(); ++i)
|
||||
{
|
||||
(*thePhysicsTable)[i]->DumpValues();
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiCerenkov::SetVerboseLevel(G4int verbose)
|
||||
{
|
||||
verboseLevel = verbose;
|
||||
G4OpticalParameters::Instance()->SetCerenkovVerboseLevel(verboseLevel);
|
||||
}
|
||||
@@ -0,0 +1,947 @@
|
||||
// ********************************************************************
|
||||
// * 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 "G4QuasiScintillation.hh"
|
||||
#include "G4QuasiOpticalData.hh"
|
||||
#include "G4QuasiOpticalPhoton.hh"
|
||||
#include "G4ScintillationQuasiTrackInfo.hh"
|
||||
|
||||
#include "globals.hh"
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "G4EmProcessSubType.hh"
|
||||
#include "G4Material.hh"
|
||||
#include "G4MaterialPropertiesTable.hh"
|
||||
#include "G4MaterialPropertyVector.hh"
|
||||
#include "G4OpticalParameters.hh"
|
||||
#include "G4ParticleMomentum.hh"
|
||||
#include "G4ParticleTypes.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4PhysicsFreeVector.hh"
|
||||
#include "G4PhysicsTable.hh"
|
||||
#include "G4Poisson.hh"
|
||||
#include "G4ScintillationTrackInformation.hh"
|
||||
#include "G4StepPoint.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4PhysicsModelCatalog.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4QuasiScintillation::G4QuasiScintillation(const G4String& processName,
|
||||
G4ProcessType type)
|
||||
: G4VRestDiscreteProcess(processName, type)
|
||||
, fIntegralTable1(nullptr)
|
||||
, fIntegralTable2(nullptr)
|
||||
, fIntegralTable3(nullptr)
|
||||
, fEmSaturation(nullptr)
|
||||
, fNumPhotons(0)
|
||||
{
|
||||
secID = G4PhysicsModelCatalog::GetModelID("model_QuasiScintillation");
|
||||
SetProcessSubType(fScintillation);
|
||||
|
||||
#ifdef G4DEBUG_SCINTILLATION
|
||||
ScintTrackEDep = 0.;
|
||||
ScintTrackYield = 0.;
|
||||
#endif
|
||||
|
||||
if(verboseLevel > 0)
|
||||
{
|
||||
G4cout << GetProcessName() << " is created " << G4endl;
|
||||
}
|
||||
Initialise();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4QuasiScintillation::~G4QuasiScintillation()
|
||||
{
|
||||
if(fIntegralTable1 != nullptr)
|
||||
{
|
||||
fIntegralTable1->clearAndDestroy();
|
||||
delete fIntegralTable1;
|
||||
}
|
||||
if(fIntegralTable2 != nullptr)
|
||||
{
|
||||
fIntegralTable2->clearAndDestroy();
|
||||
delete fIntegralTable2;
|
||||
}
|
||||
if(fIntegralTable3 != nullptr)
|
||||
{
|
||||
fIntegralTable3->clearAndDestroy();
|
||||
delete fIntegralTable3;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::ProcessDescription(std::ostream& out) const
|
||||
{
|
||||
out << "Scintillation simulates production of optical photons produced\n"
|
||||
"by a high energy particle traversing matter.\n"
|
||||
"Various material properties need to be defined.\n";
|
||||
G4VRestDiscreteProcess::DumpInfo();
|
||||
|
||||
G4OpticalParameters* params = G4OpticalParameters::Instance();
|
||||
out << "Track secondaries first: " << params->GetScintTrackSecondariesFirst();
|
||||
out << "Finite rise time: " << params->GetScintFiniteRiseTime();
|
||||
out << "Scintillation by particle type: " << params->GetScintByParticleType();
|
||||
out << "Save track information: " << params->GetScintTrackInfo();
|
||||
out << "Stack photons: " << params->GetScintStackPhotons();
|
||||
out << "Verbose level: " << params->GetScintVerboseLevel();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4bool
|
||||
G4QuasiScintillation::IsApplicable(const G4ParticleDefinition& aParticleType)
|
||||
{
|
||||
if(aParticleType.GetParticleName() == "opticalphoton")
|
||||
return false;
|
||||
if(aParticleType.IsShortLived())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::PreparePhysicsTable(const G4ParticleDefinition&)
|
||||
{
|
||||
Initialise();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::Initialise()
|
||||
{
|
||||
G4OpticalParameters* params = G4OpticalParameters::Instance();
|
||||
SetTrackSecondariesFirst(params->GetScintTrackSecondariesFirst());
|
||||
SetOffloadPhotons(params->GetScintOffloadPhotons());
|
||||
SetFiniteRiseTime(params->GetScintFiniteRiseTime());
|
||||
SetScintillationByParticleType(params->GetScintByParticleType());
|
||||
SetScintillationTrackInfo(params->GetScintTrackInfo());
|
||||
SetStackPhotons(params->GetScintStackPhotons());
|
||||
SetVerboseLevel(params->GetScintVerboseLevel());
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::BuildPhysicsTable(const G4ParticleDefinition&)
|
||||
{
|
||||
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
|
||||
std::size_t numOfMaterials = G4Material::GetNumberOfMaterials();
|
||||
|
||||
// Find the number of materials that have non-empty material property tables
|
||||
std::size_t numOfMaterialsWithMPT = 0;
|
||||
for(std::size_t i = 0; i < numOfMaterials; ++i)
|
||||
{
|
||||
if(((*materialTable)[i])->GetMaterialPropertiesTable())
|
||||
{
|
||||
++numOfMaterialsWithMPT;
|
||||
}
|
||||
}
|
||||
|
||||
// create new physics table
|
||||
fIntegralTable1 = new G4PhysicsTable(numOfMaterialsWithMPT);
|
||||
fIntegralTable2 = new G4PhysicsTable(numOfMaterialsWithMPT);
|
||||
fIntegralTable3 = new G4PhysicsTable(numOfMaterialsWithMPT);
|
||||
|
||||
std::size_t indexMPT = 0;
|
||||
for(std::size_t i = 0; i < numOfMaterials; ++i)
|
||||
{
|
||||
// Retrieve vector of scintillation wavelength intensity for
|
||||
// the material from the material's optical properties table.
|
||||
G4MaterialPropertiesTable* MPT =
|
||||
((*materialTable)[i])->GetMaterialPropertiesTable();
|
||||
|
||||
if(MPT)
|
||||
{
|
||||
auto vector1 = new G4PhysicsFreeVector();
|
||||
auto vector2 = new G4PhysicsFreeVector();
|
||||
auto vector3 = new G4PhysicsFreeVector();
|
||||
|
||||
BuildInverseCdfTable(MPT->GetProperty(kSCINTILLATIONCOMPONENT1), vector1);
|
||||
BuildInverseCdfTable(MPT->GetProperty(kSCINTILLATIONCOMPONENT2), vector2);
|
||||
BuildInverseCdfTable(MPT->GetProperty(kSCINTILLATIONCOMPONENT3), vector3);
|
||||
|
||||
fIntegralTable1->insertAt(indexMPT, vector1);
|
||||
fIntegralTable2->insertAt(indexMPT, vector2);
|
||||
fIntegralTable3->insertAt(indexMPT, vector3);
|
||||
|
||||
fIndexMPT.insert(std::make_pair(i, indexMPT));
|
||||
++indexMPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void
|
||||
G4QuasiScintillation::BuildInverseCdfTable(const G4MaterialPropertyVector* MPV,
|
||||
G4PhysicsFreeVector* vec) const
|
||||
// Build the inverse cumulative distribution function (C.D.F.) vector for the
|
||||
// scintillation photon spectrum from a given G4MaterialPropertyVector.
|
||||
// The resulting C.D.F. is stored in a G4PhysicsFreeVector, with values
|
||||
// representing the inverse C.D.F. as a function of photon energy.
|
||||
{
|
||||
if(MPV && (*MPV)[0] >= 0.0)
|
||||
{
|
||||
std::vector<G4double> cdf(MPV->GetVectorLength());
|
||||
cdf.front() = 0.0;
|
||||
for (std::size_t ii = 1; ii < MPV->GetVectorLength() ; ++ii)
|
||||
{
|
||||
cdf[ii] = cdf[ii - 1] + 0.5 * (MPV->Energy(ii) - MPV->Energy(ii-1))
|
||||
* ((*MPV)[ii] + (*MPV)[ii - 1]);
|
||||
}
|
||||
// Normalize for the inverse C.D.F. vector
|
||||
for (std::size_t ii = 0; ii < MPV->GetVectorLength(); ++ii)
|
||||
{
|
||||
cdf[ii] = cdf[ii] / cdf.back();
|
||||
vec->InsertValues(cdf[ii], MPV->Energy(ii));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4VParticleChange* G4QuasiScintillation::AtRestDoIt(const G4Track& aTrack,
|
||||
const G4Step& aStep)
|
||||
// This routine simply calls the equivalent PostStepDoIt since all the
|
||||
// necessary information resides in aStep.GetTotalEnergyDeposit()
|
||||
{
|
||||
return G4QuasiScintillation::PostStepDoIt(aTrack, aStep);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4VParticleChange* G4QuasiScintillation::PostStepDoIt(const G4Track& aTrack,
|
||||
const G4Step& aStep)
|
||||
// This routine is called for each tracking step of a charged particle
|
||||
// in a scintillator. A Poisson/Gauss-distributed number of photons is
|
||||
// generated according to the scintillation yield formula, distributed
|
||||
// evenly along the track segment and uniformly into 4pi.
|
||||
{
|
||||
aParticleChange.Initialize(aTrack);
|
||||
fNumPhotons = 0;
|
||||
|
||||
const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
|
||||
const G4Material* aMaterial = aTrack.GetMaterial();
|
||||
|
||||
G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
|
||||
G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
|
||||
|
||||
G4ThreeVector x0 = pPreStepPoint->GetPosition();
|
||||
G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
|
||||
G4double t0 = pPreStepPoint->GetGlobalTime();
|
||||
|
||||
G4double TotalEnergyDeposit = aStep.GetTotalEnergyDeposit();
|
||||
|
||||
G4MaterialPropertiesTable* MPT = aMaterial->GetMaterialPropertiesTable();
|
||||
if(!MPT)
|
||||
return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
|
||||
|
||||
G4int N_timeconstants = 1;
|
||||
|
||||
if(MPT->GetProperty(kSCINTILLATIONCOMPONENT3))
|
||||
N_timeconstants = 3;
|
||||
else if(MPT->GetProperty(kSCINTILLATIONCOMPONENT2))
|
||||
N_timeconstants = 2;
|
||||
else if(!(MPT->GetProperty(kSCINTILLATIONCOMPONENT1)))
|
||||
{
|
||||
// no components were specified
|
||||
return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
|
||||
}
|
||||
|
||||
G4double ResolutionScale = MPT->GetConstProperty(kRESOLUTIONSCALE);
|
||||
G4double MeanNumberOfPhotons;
|
||||
|
||||
G4double yield1 = 0.;
|
||||
G4double yield2 = 0.;
|
||||
G4double yield3 = 0.;
|
||||
G4double timeconstant1 = 0.;
|
||||
G4double timeconstant2 = 0.;
|
||||
G4double timeconstant3 = 0.;
|
||||
G4double sum_yields = 0.;
|
||||
|
||||
if(fScintillationByParticleType)
|
||||
{
|
||||
MeanNumberOfPhotons = GetScintillationYieldByParticleType(
|
||||
aTrack, aStep, yield1, yield2, yield3, timeconstant1, timeconstant2,
|
||||
timeconstant3);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield1 = MPT->ConstPropertyExists(kSCINTILLATIONYIELD1)
|
||||
? MPT->GetConstProperty(kSCINTILLATIONYIELD1)
|
||||
: 1.;
|
||||
yield2 = MPT->ConstPropertyExists(kSCINTILLATIONYIELD2)
|
||||
? MPT->GetConstProperty(kSCINTILLATIONYIELD2)
|
||||
: 0.;
|
||||
yield3 = MPT->ConstPropertyExists(kSCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kSCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
// The default linear scintillation process
|
||||
// Units: [# scintillation photons / MeV]
|
||||
MeanNumberOfPhotons = MPT->GetConstProperty(kSCINTILLATIONYIELD);
|
||||
// Birk's correction via fEmSaturation and specifying scintillation by
|
||||
// by particle type are physically mutually exclusive
|
||||
if(fEmSaturation)
|
||||
MeanNumberOfPhotons *=
|
||||
(fEmSaturation->VisibleEnergyDepositionAtAStep(&aStep));
|
||||
else
|
||||
MeanNumberOfPhotons *= TotalEnergyDeposit;
|
||||
}
|
||||
sum_yields = yield1 + yield2 + yield3;
|
||||
|
||||
if(MeanNumberOfPhotons > 10.)
|
||||
{
|
||||
G4double sigma = ResolutionScale * std::sqrt(MeanNumberOfPhotons);
|
||||
fNumPhotons = G4int(G4RandGauss::shoot(MeanNumberOfPhotons, sigma) + 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
fNumPhotons = G4int(G4Poisson(MeanNumberOfPhotons));
|
||||
}
|
||||
|
||||
if(fNumPhotons <= 0 || !fStackingFlag)
|
||||
{
|
||||
// return unchanged particle and no secondaries
|
||||
aParticleChange.SetNumberOfSecondaries(0);
|
||||
return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
|
||||
}
|
||||
|
||||
aParticleChange.SetNumberOfSecondaries(fNumPhotons);
|
||||
|
||||
if(fTrackSecondariesFirst)
|
||||
{
|
||||
if(aTrack.GetTrackStatus() == fAlive)
|
||||
aParticleChange.ProposeTrackStatus(fSuspend);
|
||||
}
|
||||
|
||||
std::size_t materialIndex = aMaterial->GetIndex();
|
||||
auto it = fIndexMPT.find(materialIndex);
|
||||
|
||||
std::size_t indexMPT = 0;
|
||||
if(it != fIndexMPT.end())
|
||||
{
|
||||
indexMPT = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
G4ExceptionDescription ed;
|
||||
ed << "G4MaterialPropertiesTable for " << aMaterial->GetName()
|
||||
<< " is not found!" << G4endl;
|
||||
G4Exception("G4QuasiScintillation::PostStepDoIt", "Scint04",
|
||||
FatalException, ed);
|
||||
}
|
||||
|
||||
// Retrieve the Scintillation Integral for this material
|
||||
// new G4PhysicsFreeVector allocated to hold CII's
|
||||
G4int numPhot = fNumPhotons;
|
||||
G4double scintTime = 0.;
|
||||
G4double riseTime = 0.;
|
||||
G4PhysicsFreeVector* scintIntegral = nullptr;
|
||||
G4ScintillationType scintType = Slow;
|
||||
|
||||
G4bool isNeutral = (aParticle->GetDefinition()->GetPDGCharge() == 0);
|
||||
G4double deltaVelocity = pPostStepPoint->GetVelocity() -
|
||||
pPreStepPoint->GetVelocity();
|
||||
auto touchableHandle = aStep.GetPreStepPoint()->GetTouchableHandle();
|
||||
|
||||
for(G4int scnt = 0; scnt < N_timeconstants; ++scnt)
|
||||
{
|
||||
// if there is 1 time constant it is #1, etc.
|
||||
if(scnt == 0)
|
||||
{
|
||||
if(N_timeconstants == 1)
|
||||
{
|
||||
numPhot = fNumPhotons;
|
||||
}
|
||||
else
|
||||
{
|
||||
numPhot = yield1 / sum_yields * fNumPhotons;
|
||||
}
|
||||
if(fScintillationByParticleType)
|
||||
{
|
||||
scintTime = timeconstant1;
|
||||
}
|
||||
else
|
||||
{
|
||||
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
}
|
||||
if(fFiniteRiseTime)
|
||||
{
|
||||
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME1);
|
||||
}
|
||||
scintType = Fast;
|
||||
scintIntegral = (G4PhysicsFreeVector*) ((*fIntegralTable1)(indexMPT));
|
||||
}
|
||||
else if(scnt == 1)
|
||||
{
|
||||
// to be consistent with old version (due to double->int conversion)
|
||||
if(N_timeconstants == 2)
|
||||
{
|
||||
numPhot = fNumPhotons - numPhot;
|
||||
}
|
||||
else
|
||||
{
|
||||
numPhot = yield2 / sum_yields * fNumPhotons;
|
||||
}
|
||||
if(fScintillationByParticleType)
|
||||
{
|
||||
scintTime = timeconstant2;
|
||||
}
|
||||
else
|
||||
{
|
||||
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(fFiniteRiseTime)
|
||||
{
|
||||
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME2);
|
||||
}
|
||||
scintType = Medium;
|
||||
scintIntegral = (G4PhysicsFreeVector*) ((*fIntegralTable2)(indexMPT));
|
||||
}
|
||||
else if(scnt == 2)
|
||||
{
|
||||
numPhot = yield3 / sum_yields * fNumPhotons;
|
||||
if(fScintillationByParticleType)
|
||||
{
|
||||
scintTime = timeconstant3;
|
||||
}
|
||||
else
|
||||
{
|
||||
scintTime = MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
if(fFiniteRiseTime)
|
||||
{
|
||||
riseTime = MPT->GetConstProperty(kSCINTILLATIONRISETIME3);
|
||||
}
|
||||
scintType = Slow;
|
||||
scintIntegral = (G4PhysicsFreeVector*) ((*fIntegralTable3)(indexMPT));
|
||||
}
|
||||
|
||||
if(!scintIntegral)
|
||||
continue;
|
||||
|
||||
if(fOffloadingFlag)
|
||||
{
|
||||
// Create a G4DynamicParticle with G4QuasiOpticalPhoton
|
||||
auto quasiPhoton = new G4DynamicParticle(
|
||||
G4QuasiOpticalPhoton::QuasiOpticalPhotonDefinition(),
|
||||
aParticle->GetMomentum());
|
||||
|
||||
// Create a new G4Track object with the quasi-optical photon
|
||||
G4Track* aSecondaryTrack = new G4Track(quasiPhoton, t0, x0);
|
||||
aSecondaryTrack->SetTouchableHandle(touchableHandle);
|
||||
aSecondaryTrack->SetParentID(aTrack.GetTrackID());
|
||||
aSecondaryTrack->SetCreatorModelID(secID);
|
||||
|
||||
// Attach auxiliary track information with associated metadata
|
||||
G4QuasiOpticalData quasiTrackData{aMaterial->GetIndex(), numPhot,
|
||||
aParticle->GetDefinition()->GetPDGCharge(), aStep.GetStepLength(),
|
||||
pPreStepPoint->GetVelocity(), deltaVelocity, aStep.GetDeltaPosition()};
|
||||
aSecondaryTrack->SetAuxiliaryTrackInformation(secID,
|
||||
new G4ScintillationQuasiTrackInfo(quasiTrackData, scintTime, riseTime));
|
||||
aParticleChange.AddSecondary(aSecondaryTrack);
|
||||
}
|
||||
|
||||
for(G4int i = 0; i < numPhot; ++i)
|
||||
{
|
||||
// Determine photon energy
|
||||
G4double sampledEnergy = scintIntegral->Value(G4UniformRand());
|
||||
|
||||
if(verboseLevel > 1)
|
||||
{
|
||||
G4cout << "sampledEnergy = " << sampledEnergy << G4endl;
|
||||
}
|
||||
|
||||
// Generate random photon direction
|
||||
G4double cost = 1. - 2. * G4UniformRand();
|
||||
G4double sint = std::sqrt((1. - cost) * (1. + cost));
|
||||
G4double phi = twopi * G4UniformRand();
|
||||
G4double sinp = std::sin(phi);
|
||||
G4double cosp = std::cos(phi);
|
||||
G4ParticleMomentum photonMomentum(sint * cosp, sint * sinp, cost);
|
||||
|
||||
// Determine polarization of new photon
|
||||
G4ThreeVector photonPolarization(cost * cosp, cost * sinp, -sint);
|
||||
G4ThreeVector perp = photonMomentum.cross(photonPolarization);
|
||||
phi = twopi * G4UniformRand();
|
||||
sinp = std::sin(phi);
|
||||
cosp = std::cos(phi);
|
||||
photonPolarization = (cosp * photonPolarization + sinp * perp).unit();
|
||||
|
||||
// Generate a new photon:
|
||||
auto scintPhoton = new G4DynamicParticle(opticalphoton, photonMomentum);
|
||||
scintPhoton->SetPolarization(photonPolarization);
|
||||
scintPhoton->SetKineticEnergy(sampledEnergy);
|
||||
|
||||
// Generate new G4Track object:
|
||||
G4double rand = (isNeutral) ? 1.0 : G4UniformRand();
|
||||
|
||||
// emission time distribution
|
||||
G4double delta = rand * aStep.GetStepLength();
|
||||
G4double deltaTime =
|
||||
delta / (pPreStepPoint->GetVelocity() + 0.5 * rand * deltaVelocity);
|
||||
if(riseTime == 0.0)
|
||||
{
|
||||
deltaTime -= scintTime * std::log(G4UniformRand());
|
||||
}
|
||||
else
|
||||
{
|
||||
deltaTime += sample_time(riseTime, scintTime);
|
||||
}
|
||||
|
||||
G4double secTime = t0 + deltaTime;
|
||||
G4ThreeVector secPosition = x0 + rand * aStep.GetDeltaPosition();
|
||||
|
||||
G4Track* secTrack = new G4Track(scintPhoton, secTime, secPosition);
|
||||
secTrack->SetTouchableHandle(touchableHandle);
|
||||
secTrack->SetParentID(aTrack.GetTrackID());
|
||||
secTrack->SetCreatorModelID(secID);
|
||||
if(fScintillationTrackInfo)
|
||||
secTrack->SetUserInformation(
|
||||
new G4ScintillationTrackInformation(scintType));
|
||||
aParticleChange.AddSecondary(secTrack);
|
||||
}
|
||||
}
|
||||
|
||||
if(verboseLevel > 1)
|
||||
{
|
||||
G4cout << "\n Exiting from G4QuasiScintillation::DoIt -- "
|
||||
<< " NumberOfSecondaries = "
|
||||
<< aParticleChange.GetNumberOfSecondaries() << G4endl;
|
||||
}
|
||||
|
||||
return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4double G4QuasiScintillation::GetMeanFreePath(const G4Track&, G4double,
|
||||
G4ForceCondition* condition)
|
||||
{
|
||||
*condition = StronglyForced;
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4double G4QuasiScintillation::GetMeanLifeTime(const G4Track&,
|
||||
G4ForceCondition* condition)
|
||||
{
|
||||
*condition = Forced;
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4double G4QuasiScintillation::sample_time(G4double tau1, G4double tau2)
|
||||
{
|
||||
// tau1: rise time and tau2: decay time
|
||||
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
|
||||
G4double t;
|
||||
|
||||
do
|
||||
{
|
||||
// The exponential distribution as an envelope function: very efficient
|
||||
t = -1.0 * tau2 * G4Log(1.0 - G4UniformRand());
|
||||
}
|
||||
while (G4UniformRand() > (1.0 - G4Exp(-t/tau1)));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4double G4QuasiScintillation::GetScintillationYieldByParticleType(
|
||||
const G4Track& aTrack, const G4Step& aStep, G4double& yield1,
|
||||
G4double& yield2, G4double& yield3, G4double& timeconstant1,
|
||||
G4double& timeconstant2, G4double& timeconstant3)
|
||||
{
|
||||
// new in 10.7, allow multiple time constants with ScintByParticleType
|
||||
// Get the G4MaterialPropertyVector containing the scintillation
|
||||
// yield as a function of the energy deposited and particle type
|
||||
// In 11.2, allow different time constants for different particles
|
||||
|
||||
G4ParticleDefinition* pDef = aTrack.GetDynamicParticle()->GetDefinition();
|
||||
G4MaterialPropertyVector* yieldVector = nullptr;
|
||||
G4MaterialPropertiesTable* MPT =
|
||||
aTrack.GetMaterial()->GetMaterialPropertiesTable();
|
||||
|
||||
// Protons
|
||||
if(pDef == G4Proton::ProtonDefinition())
|
||||
{
|
||||
yieldVector = MPT->GetProperty(kPROTONSCINTILLATIONYIELD);
|
||||
yield1 = MPT->ConstPropertyExists(kPROTONSCINTILLATIONYIELD1)
|
||||
? MPT->GetConstProperty(kPROTONSCINTILLATIONYIELD1)
|
||||
: 1.;
|
||||
yield2 = MPT->ConstPropertyExists(kPROTONSCINTILLATIONYIELD2)
|
||||
? MPT->GetConstProperty(kPROTONSCINTILLATIONYIELD2)
|
||||
: 0.;
|
||||
yield3 = MPT->ConstPropertyExists(kPROTONSCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kPROTONSCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kPROTONSCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kPROTONSCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kPROTONSCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kPROTONSCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kPROTONSCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kPROTONSCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Deuterons
|
||||
else if(pDef == G4Deuteron::DeuteronDefinition())
|
||||
{
|
||||
yieldVector = MPT->GetProperty(kDEUTERONSCINTILLATIONYIELD);
|
||||
yield1 = MPT->ConstPropertyExists(kDEUTERONSCINTILLATIONYIELD1)
|
||||
? MPT->GetConstProperty(kDEUTERONSCINTILLATIONYIELD1)
|
||||
: 1.;
|
||||
yield2 = MPT->ConstPropertyExists(kDEUTERONSCINTILLATIONYIELD2)
|
||||
? MPT->GetConstProperty(kDEUTERONSCINTILLATIONYIELD2)
|
||||
: 0.;
|
||||
yield3 = MPT->ConstPropertyExists(kDEUTERONSCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kDEUTERONSCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kDEUTERONSCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kDEUTERONSCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kDEUTERONSCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kDEUTERONSCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kDEUTERONSCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kDEUTERONSCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Tritons
|
||||
else if(pDef == G4Triton::TritonDefinition())
|
||||
{
|
||||
yieldVector = MPT->GetProperty(kTRITONSCINTILLATIONYIELD);
|
||||
yield1 = MPT->ConstPropertyExists(kTRITONSCINTILLATIONYIELD1)
|
||||
? MPT->GetConstProperty(kTRITONSCINTILLATIONYIELD1)
|
||||
: 1.;
|
||||
yield2 = MPT->ConstPropertyExists(kTRITONSCINTILLATIONYIELD2)
|
||||
? MPT->GetConstProperty(kTRITONSCINTILLATIONYIELD2)
|
||||
: 0.;
|
||||
yield3 = MPT->ConstPropertyExists(kTRITONSCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kTRITONSCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kTRITONSCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kTRITONSCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kTRITONSCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kTRITONSCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kTRITONSCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kTRITONSCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Alphas
|
||||
else if(pDef == G4Alpha::AlphaDefinition())
|
||||
{
|
||||
yieldVector = MPT->GetProperty(kALPHASCINTILLATIONYIELD);
|
||||
yield1 = MPT->ConstPropertyExists(kALPHASCINTILLATIONYIELD1)
|
||||
? MPT->GetConstProperty(kALPHASCINTILLATIONYIELD1)
|
||||
: 1.;
|
||||
yield2 = MPT->ConstPropertyExists(kALPHASCINTILLATIONYIELD2)
|
||||
? MPT->GetConstProperty(kALPHASCINTILLATIONYIELD2)
|
||||
: 0.;
|
||||
yield3 = MPT->ConstPropertyExists(kALPHASCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kALPHASCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kALPHASCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kALPHASCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kALPHASCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kALPHASCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kALPHASCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kALPHASCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Ions (particles derived from G4VIon and G4Ions) and recoil ions
|
||||
// below the production cut from neutrons after hElastic
|
||||
else if(pDef->GetParticleType() == "nucleus" ||
|
||||
pDef == G4Neutron::NeutronDefinition())
|
||||
{
|
||||
yieldVector = MPT->GetProperty(kIONSCINTILLATIONYIELD);
|
||||
yield1 = MPT->ConstPropertyExists(kIONSCINTILLATIONYIELD1)
|
||||
? MPT->GetConstProperty(kIONSCINTILLATIONYIELD1)
|
||||
: 1.;
|
||||
yield2 = MPT->ConstPropertyExists(kIONSCINTILLATIONYIELD2)
|
||||
? MPT->GetConstProperty(kIONSCINTILLATIONYIELD2)
|
||||
: 0.;
|
||||
yield3 = MPT->ConstPropertyExists(kIONSCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kIONSCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kIONSCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kIONSCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kIONSCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kIONSCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kIONSCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kIONSCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Electrons (must also account for shell-binding energy
|
||||
// attributed to gamma from standard photoelectric effect)
|
||||
// and, default for particles not enumerated/listed above
|
||||
else
|
||||
{
|
||||
yieldVector = MPT->GetProperty(kELECTRONSCINTILLATIONYIELD);
|
||||
yield1 = MPT->ConstPropertyExists(kELECTRONSCINTILLATIONYIELD1)
|
||||
? MPT->GetConstProperty(kELECTRONSCINTILLATIONYIELD1)
|
||||
: 1.;
|
||||
yield2 = MPT->ConstPropertyExists(kELECTRONSCINTILLATIONYIELD2)
|
||||
? MPT->GetConstProperty(kELECTRONSCINTILLATIONYIELD2)
|
||||
: 0.;
|
||||
yield3 = MPT->ConstPropertyExists(kELECTRONSCINTILLATIONYIELD3)
|
||||
? MPT->GetConstProperty(kELECTRONSCINTILLATIONYIELD3)
|
||||
: 0.;
|
||||
timeconstant1 = MPT->ConstPropertyExists(kELECTRONSCINTILLATIONTIMECONSTANT1)
|
||||
? MPT->GetConstProperty(kELECTRONSCINTILLATIONTIMECONSTANT1)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT1);
|
||||
if(yield2 > 0.)
|
||||
{
|
||||
timeconstant2 = MPT->ConstPropertyExists(kELECTRONSCINTILLATIONTIMECONSTANT2)
|
||||
? MPT->GetConstProperty(kELECTRONSCINTILLATIONTIMECONSTANT2)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT2);
|
||||
}
|
||||
if(yield3 > 0.)
|
||||
{
|
||||
timeconstant3 = MPT->ConstPropertyExists(kELECTRONSCINTILLATIONTIMECONSTANT3)
|
||||
? MPT->GetConstProperty(kELECTRONSCINTILLATIONTIMECONSTANT3)
|
||||
: MPT->GetConstProperty(kSCINTILLATIONTIMECONSTANT3);
|
||||
}
|
||||
}
|
||||
|
||||
// Throw an exception if no scintillation yield vector is found
|
||||
if(yieldVector == nullptr)
|
||||
{
|
||||
G4ExceptionDescription ed;
|
||||
ed << "\nG4QuasiScintillation::PostStepDoIt(): "
|
||||
<< "Request for scintillation yield for energy deposit and particle\n"
|
||||
<< "type without correct entry in MaterialPropertiesTable. A material\n"
|
||||
<< "property (vector) with name like PARTICLESCINTILLATIONYIELD is\n"
|
||||
<< "needed (hint: PARTICLE might not be the primary particle."
|
||||
<< G4endl;
|
||||
G4String comments = "Missing MaterialPropertiesTable entry - No correct "
|
||||
"entry in MaterialPropertiesTable";
|
||||
G4Exception("G4QuasiScintillation::PostStepDoIt", "Scint01", FatalException, ed,
|
||||
comments);
|
||||
return 0.; // NOLINT: required to help Coverity recognise this as exit point
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// Calculate the scintillation light //
|
||||
///////////////////////////////////////
|
||||
// To account for potential nonlinearity and scintillation photon
|
||||
// density along the track, light (L) is produced according to:
|
||||
// L_currentStep = L(PreStepKE) - L(PreStepKE - EDep)
|
||||
|
||||
G4double ScintillationYield = 0.;
|
||||
G4double StepEnergyDeposit = aStep.GetTotalEnergyDeposit();
|
||||
G4double PreStepKineticEnergy = aStep.GetPreStepPoint()->GetKineticEnergy();
|
||||
|
||||
if(PreStepKineticEnergy <= yieldVector->GetMaxEnergy())
|
||||
{
|
||||
// G4double Yield1 = yieldVector->Value(PreStepKineticEnergy);
|
||||
// G4double Yield2 = yieldVector->Value(PreStepKineticEnergy -
|
||||
// StepEnergyDeposit); ScintillationYield = Yield1 - Yield2;
|
||||
ScintillationYield =
|
||||
yieldVector->Value(PreStepKineticEnergy) -
|
||||
yieldVector->Value(PreStepKineticEnergy - StepEnergyDeposit);
|
||||
}
|
||||
else
|
||||
{
|
||||
++fNumEnergyWarnings;
|
||||
if(verboseLevel > 0 && fNumEnergyWarnings <= 10)
|
||||
{
|
||||
G4ExceptionDescription ed;
|
||||
ed << "\nG4QuasiScintillation::GetScintillationYieldByParticleType(): "
|
||||
<< "Request\n"
|
||||
<< "for scintillation light yield above the available energy range\n"
|
||||
<< "specified in G4MaterialPropertiesTable. A linear interpolation\n"
|
||||
<< "will be performed to compute the scintillation light yield using\n"
|
||||
<< "(L_max / E_max) as the photon yield per unit energy." << G4endl;
|
||||
G4String cmt = "\nScintillation yield may be unphysical!\n";
|
||||
|
||||
if(fNumEnergyWarnings == 10)
|
||||
{
|
||||
ed << G4endl << "*** Scintillation energy warnings stopped.";
|
||||
}
|
||||
G4Exception("G4QuasiScintillation::GetScintillationYieldByParticleType()",
|
||||
"Scint03", JustWarning, ed, cmt);
|
||||
}
|
||||
|
||||
// Units: [# scintillation photons]
|
||||
ScintillationYield = yieldVector->GetMaxValue() /
|
||||
yieldVector->GetMaxEnergy() * StepEnergyDeposit;
|
||||
}
|
||||
|
||||
#ifdef G4DEBUG_SCINTILLATION
|
||||
// Increment track aggregators
|
||||
ScintTrackYield += ScintillationYield;
|
||||
ScintTrackEDep += StepEnergyDeposit;
|
||||
|
||||
G4cout << "\n-- "
|
||||
<< "G4QuasiScintillation::GetScintillationYieldByParticleType() --\n"
|
||||
<< "--\n"
|
||||
<< "-- Name = "
|
||||
<< aTrack.GetParticleDefinition()->GetParticleName() << "\n"
|
||||
<< "-- TrackID = " << aTrack.GetTrackID() << "\n"
|
||||
<< "-- ParentID = " << aTrack.GetParentID() << "\n"
|
||||
<< "-- Current KE = " << aTrack.GetKineticEnergy() / MeV
|
||||
<< " MeV\n"
|
||||
<< "-- Step EDep = " << aStep.GetTotalEnergyDeposit() / MeV
|
||||
<< " MeV\n"
|
||||
<< "-- Track EDep = " << ScintTrackEDep / MeV << " MeV\n"
|
||||
<< "-- Vertex KE = " << aTrack.GetVertexKineticEnergy() / MeV
|
||||
<< " MeV\n"
|
||||
<< "-- Step yield = " << ScintillationYield << " photons\n"
|
||||
<< "-- Track yield = " << ScintTrackYield << " photons\n"
|
||||
<< G4endl;
|
||||
|
||||
// The track has terminated within or has left the scintillator volume
|
||||
if((aTrack.GetTrackStatus() == fStopButAlive) or
|
||||
(aStep.GetPostStepPoint()->GetStepStatus() == fGeomBoundary))
|
||||
{
|
||||
// Reset aggregators for the next track
|
||||
ScintTrackEDep = 0.;
|
||||
ScintTrackYield = 0.;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ScintillationYield;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::DumpPhysicsTable() const
|
||||
{
|
||||
if(fIntegralTable1)
|
||||
{
|
||||
for(std::size_t i = 0; i < fIntegralTable1->entries(); ++i)
|
||||
{
|
||||
((G4PhysicsFreeVector*) (*fIntegralTable1)[i])->DumpValues();
|
||||
}
|
||||
}
|
||||
if(fIntegralTable2)
|
||||
{
|
||||
for(std::size_t i = 0; i < fIntegralTable2->entries(); ++i)
|
||||
{
|
||||
((G4PhysicsFreeVector*) (*fIntegralTable2)[i])->DumpValues();
|
||||
}
|
||||
}
|
||||
if(fIntegralTable3)
|
||||
{
|
||||
for(std::size_t i = 0; i < fIntegralTable3->entries(); ++i)
|
||||
{
|
||||
((G4PhysicsFreeVector*) (*fIntegralTable3)[i])->DumpValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::SetTrackSecondariesFirst(const G4bool state)
|
||||
{
|
||||
fTrackSecondariesFirst = state;
|
||||
G4OpticalParameters::Instance()->SetScintTrackSecondariesFirst(
|
||||
fTrackSecondariesFirst);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::SetFiniteRiseTime(const G4bool state)
|
||||
{
|
||||
fFiniteRiseTime = state;
|
||||
G4OpticalParameters::Instance()->SetScintFiniteRiseTime(fFiniteRiseTime);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::SetScintillationByParticleType(const G4bool scintType)
|
||||
{
|
||||
if(fEmSaturation && scintType)
|
||||
{
|
||||
G4Exception("G4QuasiScintillation::SetScintillationByParticleType",
|
||||
"Scint02", JustWarning,
|
||||
"Redefinition: Birks Saturation is replaced by "
|
||||
"ScintillationByParticleType!");
|
||||
RemoveSaturation();
|
||||
}
|
||||
fScintillationByParticleType = scintType;
|
||||
G4OpticalParameters::Instance()->SetScintByParticleType(
|
||||
fScintillationByParticleType);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::SetScintillationTrackInfo(const G4bool trackType)
|
||||
{
|
||||
fScintillationTrackInfo = trackType;
|
||||
G4OpticalParameters::Instance()->SetScintTrackInfo(fScintillationTrackInfo);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::SetStackPhotons(const G4bool stackingFlag)
|
||||
{
|
||||
fStackingFlag = stackingFlag;
|
||||
G4OpticalParameters::Instance()->SetScintStackPhotons(fStackingFlag);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::SetOffloadPhotons(const G4bool offloadingFlag)
|
||||
{
|
||||
fOffloadingFlag = offloadingFlag;
|
||||
G4OpticalParameters::Instance()->SetScintOffloadPhotons(fOffloadingFlag);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4QuasiScintillation::SetVerboseLevel(G4int verbose)
|
||||
{
|
||||
verboseLevel = verbose;
|
||||
G4OpticalParameters::Instance()->SetScintVerboseLevel(verboseLevel);
|
||||
}
|
||||
@@ -149,11 +149,7 @@ void G4Scintillation::ProcessDescription(std::ostream& out) const
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4bool G4Scintillation::IsApplicable(const G4ParticleDefinition& aParticleType)
|
||||
{
|
||||
if(aParticleType.GetParticleName() == "opticalphoton")
|
||||
return false;
|
||||
if(aParticleType.IsShortLived())
|
||||
return false;
|
||||
return true;
|
||||
return (!aParticleType.IsShortLived());
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -280,6 +276,9 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
|
||||
G4double t0 = pPreStepPoint->GetGlobalTime();
|
||||
|
||||
G4double TotalEnergyDeposit = aStep.GetTotalEnergyDeposit();
|
||||
if (0.0 >= TotalEnergyDeposit) {
|
||||
G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
|
||||
}
|
||||
|
||||
G4MaterialPropertiesTable* MPT = aMaterial->GetMaterialPropertiesTable();
|
||||
if(!MPT)
|
||||
@@ -381,12 +380,17 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
|
||||
|
||||
// Retrieve the Scintillation Integral for this material
|
||||
// new G4PhysicsFreeVector allocated to hold CII's
|
||||
std::size_t numPhot = fNumPhotons;
|
||||
G4int numPhot = fNumPhotons;
|
||||
G4double scintTime = 0.;
|
||||
G4double riseTime = 0.;
|
||||
G4PhysicsFreeVector* scintIntegral = nullptr;
|
||||
G4ScintillationType scintType = Slow;
|
||||
|
||||
G4bool isNeutral = (aParticle->GetDefinition()->GetPDGCharge() == 0);
|
||||
G4double deltaVelocity = pPostStepPoint->GetVelocity() -
|
||||
pPreStepPoint->GetVelocity();
|
||||
auto touchableHandle = aStep.GetPreStepPoint()->GetTouchableHandle();
|
||||
|
||||
for(G4int scnt = 0; scnt < N_timeconstants; ++scnt)
|
||||
{
|
||||
// if there is 1 time constant it is #1, etc.
|
||||
@@ -463,7 +467,7 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
|
||||
if(!scintIntegral)
|
||||
continue;
|
||||
|
||||
for(std::size_t i = 0; i < numPhot; ++i)
|
||||
for(G4int i = 0; i < numPhot; ++i)
|
||||
{
|
||||
// Determine photon energy
|
||||
G4double sampledEnergy = scintIntegral->Value(G4UniformRand());
|
||||
@@ -495,19 +499,12 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
|
||||
scintPhoton->SetKineticEnergy(sampledEnergy);
|
||||
|
||||
// Generate new G4Track object:
|
||||
G4double rand = G4UniformRand();
|
||||
if(aParticle->GetDefinition()->GetPDGCharge() == 0)
|
||||
{
|
||||
rand = 1.0;
|
||||
}
|
||||
G4double rand = (isNeutral) ? 1.0 : G4UniformRand();
|
||||
|
||||
// emission time distribution
|
||||
G4double delta = rand * aStep.GetStepLength();
|
||||
G4double deltaTime =
|
||||
delta /
|
||||
(pPreStepPoint->GetVelocity() +
|
||||
rand * (pPostStepPoint->GetVelocity() - pPreStepPoint->GetVelocity()) /
|
||||
2.);
|
||||
delta / (pPreStepPoint->GetVelocity() + 0.5 * rand * deltaVelocity);
|
||||
if(riseTime == 0.0)
|
||||
{
|
||||
deltaTime -= scintTime * std::log(G4UniformRand());
|
||||
@@ -521,8 +518,7 @@ G4VParticleChange* G4Scintillation::PostStepDoIt(const G4Track& aTrack,
|
||||
G4ThreeVector secPosition = x0 + rand * aStep.GetDeltaPosition();
|
||||
|
||||
G4Track* secTrack = new G4Track(scintPhoton, secTime, secPosition);
|
||||
secTrack->SetTouchableHandle(
|
||||
aStep.GetPreStepPoint()->GetTouchableHandle());
|
||||
secTrack->SetTouchableHandle(touchableHandle);
|
||||
secTrack->SetParentID(aTrack.GetTrackID());
|
||||
secTrack->SetCreatorModelID(secID);
|
||||
if(fScintillationTrackInfo)
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "G4ScintillationQuasiTrackInfo.hh"
|
||||
|
||||
G4Allocator<G4ScintillationQuasiTrackInfo>*& aScintillationATIAllocator()
|
||||
{
|
||||
G4ThreadLocalStatic G4Allocator<G4ScintillationQuasiTrackInfo>* _instance =
|
||||
nullptr;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
G4ScintillationQuasiTrackInfo::G4ScintillationQuasiTrackInfo(
|
||||
const G4QuasiOpticalData& aData, G4double aScintTime, G4double aRiseTime)
|
||||
: G4VAuxiliaryTrackInformation()
|
||||
, fQuasiOpticalData(aData)
|
||||
, fScintTime(aScintTime)
|
||||
, fRiseTime(aRiseTime)
|
||||
{}
|
||||
|
||||
void G4ScintillationQuasiTrackInfo::Print() const
|
||||
{
|
||||
G4cout << "Auxiliary track information for a scintillation step" << G4endl;
|
||||
}
|
||||
|
||||
G4ScintillationQuasiTrackInfo* G4ScintillationQuasiTrackInfo::Cast(
|
||||
const G4VAuxiliaryTrackInformation* const aATI)
|
||||
{
|
||||
G4ScintillationQuasiTrackInfo* SATI = nullptr;
|
||||
if(aATI != nullptr)
|
||||
{
|
||||
// No change will be done to the pointer and to the pointed data
|
||||
auto temp = const_cast<G4VAuxiliaryTrackInformation*>(aATI);
|
||||
SATI = dynamic_cast<G4ScintillationQuasiTrackInfo*>(temp);
|
||||
}
|
||||
return SATI;
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// G4StandardCerenkovModel
|
||||
//
|
||||
// Created 25.05.2025 V.Ivanchenko
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "G4StandardCerenkovModel.hh"
|
||||
|
||||
#include "G4ios.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4Material.hh"
|
||||
#include "G4MaterialCutsCouple.hh"
|
||||
#include "G4MaterialPropertiesTable.hh"
|
||||
#include "G4OpticalParameters.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "G4ParticleMomentum.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4PhysicsFreeVector.hh"
|
||||
#include "G4Poisson.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4OpticalPhoton.hh"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr G4double minAllowedStep = 0.001*CLHEP::mm;
|
||||
constexpr G4int nvec = 10; // number of slices in beta of projectile
|
||||
}
|
||||
|
||||
std::vector<G4double>* G4StandardCerenkovModel::fBetaLim = nullptr;
|
||||
std::vector<G4MaterialPropertyVector*>* G4StandardCerenkovModel::fRindex = nullptr;
|
||||
std::vector<std::vector<G4double>* >* G4StandardCerenkovModel::fMeanNumberOfPhotons = nullptr;
|
||||
std::vector<std::vector<std::vector<G4double>* >* >* G4StandardCerenkovModel::fIntegral = nullptr;
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4StandardCerenkovModel::G4StandardCerenkovModel()
|
||||
: G4VXRayModel("theCerenkov")
|
||||
{
|
||||
if (nullptr == fBetaLim) {
|
||||
isInitializer = true;
|
||||
fBetaLim = new std::vector<G4double>;
|
||||
fMeanNumberOfPhotons = new std::vector<std::vector<G4double>* >;
|
||||
fIntegral = new std::vector<std::vector<std::vector<G4double>* >* >;
|
||||
fRindex = new std::vector<G4MaterialPropertyVector*>;
|
||||
}
|
||||
fPhoton = G4OpticalPhoton::OpticalPhoton();
|
||||
fRfact = 369.81 / (CLHEP::eV * CLHEP::cm); // number of photons per mm
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4StandardCerenkovModel::~G4StandardCerenkovModel()
|
||||
{
|
||||
if (isInitializer && isInitialized) {
|
||||
delete fBetaLim;
|
||||
for (auto const & ptr : *fRindex) {
|
||||
delete ptr;
|
||||
}
|
||||
delete fRindex;
|
||||
for (auto const & ptr : *fMeanNumberOfPhotons) {
|
||||
delete ptr;
|
||||
}
|
||||
delete fMeanNumberOfPhotons;
|
||||
for (auto const & ptr : *fIntegral) {
|
||||
for (auto const & p : *ptr) {
|
||||
delete p;
|
||||
}
|
||||
delete ptr;
|
||||
}
|
||||
delete fIntegral;
|
||||
fIntegral = nullptr;
|
||||
fBetaLim = nullptr;
|
||||
fRindex = nullptr;
|
||||
fMeanNumberOfPhotons = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4StandardCerenkovModel::InitialiseModel()
|
||||
{
|
||||
G4double beta = 1.0;
|
||||
if (0 == nVolumes) { return; }
|
||||
if (isInitializer && !isInitialized) {
|
||||
isInitialized = true;
|
||||
fBetaLim->resize(nVolumes, 1.0);
|
||||
fRindex->resize(nVolumes, nullptr);
|
||||
fMeanNumberOfPhotons->resize(nVolumes, new std::vector<G4double>(nvec, 0.0));
|
||||
fIntegral->resize(nVolumes, nullptr);
|
||||
|
||||
for (std::size_t i = 0; i < nVolumes; ++i) {
|
||||
auto mat = ((*pLogicalVolumes)[i])->GetMaterial();
|
||||
auto MPT = mat->GetMaterialPropertiesTable();
|
||||
|
||||
if (nullptr == MPT) { continue; }
|
||||
G4MaterialPropertyVector* rindex = MPT->GetProperty(kRINDEX);
|
||||
if (nullptr == rindex) { continue; }
|
||||
(*fRindex)[i] = rindex;
|
||||
|
||||
G4double nMax = rindex->GetMaxValue();
|
||||
if (nMax <= 1.0) { continue; }
|
||||
G4double b = 1.0/nMax;
|
||||
(*fBetaLim)[i] = b;
|
||||
beta = std::min(beta, b);
|
||||
G4double dbeta = (1.0 - b)/(G4double)(nvec - 1);
|
||||
G4double b0 = b;
|
||||
std::size_t nn = rindex->GetVectorLength();
|
||||
if (0 == nn) { continue; }
|
||||
|
||||
auto iptr = new std::vector<std::vector<G4double>* >((std::size_t)nvec, nullptr);
|
||||
(*fIntegral)[i] = iptr;
|
||||
for (auto & ptr : *iptr) {
|
||||
ptr = new std::vector<G4double>(nn, 0.0);
|
||||
}
|
||||
|
||||
// Initialisation for charge = 1.0
|
||||
G4double y0 = AverageNumberOfPhotons(1.0, b0, (*rindex)[0]);
|
||||
(*(*fMeanNumberOfPhotons)[i])[0] = y0;
|
||||
if (1 == nn) { continue; }
|
||||
|
||||
// Initialisation for charge = 1.0
|
||||
for (G4int k = 0; k < nvec; ++k) {
|
||||
(*((*fIntegral)[i]))[k]->resize(nn, 0.0);
|
||||
G4double sum = 0.0;
|
||||
G4double e0 = rindex->GetMinEnergy();
|
||||
G4double deltae = rindex->GetMaxEnergy() - e0;
|
||||
for (std::size_t j = 1; j < nn; ++j) {
|
||||
G4double e = rindex->Energy(j);
|
||||
G4double y = AverageNumberOfPhotons(1.0, beta, (*rindex)[j]);
|
||||
sum += 0.5*(y - y0)*(e - e0);
|
||||
y0 = y;
|
||||
e0 = e;
|
||||
(*(*((*fIntegral)[i]))[k])[j] = sum;
|
||||
}
|
||||
if (deltae > 0.0) { (*(*fMeanNumberOfPhotons)[i])[k] = sum/deltae; }
|
||||
if (sum > 0.0) { sum = 1.0/sum; }
|
||||
for (std::size_t j = 1; j < nn; ++j) {
|
||||
G4double y = (*(*((*fIntegral)[i]))[k])[j]/sum;
|
||||
(*(*((*fIntegral)[i]))[k])[j] = y;
|
||||
}
|
||||
beta += dbeta;
|
||||
beta = std::min(beta, 1.0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (std::size_t i = 0; i < nVolumes; ++i) {
|
||||
beta = std::min(beta, (*fBetaLim)[i]);
|
||||
}
|
||||
}
|
||||
pBetaMin = beta;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4bool G4StandardCerenkovModel::StepLimitForVolume(G4double& limit)
|
||||
{
|
||||
G4double betaMin = (*fBetaLim)[pIndex];
|
||||
if (pPreStepBeta <= betaMin) { return false; }
|
||||
|
||||
// step limitation
|
||||
betaMin = std::max(betaMin, pPreStepBeta*pMaxBetaChange);
|
||||
|
||||
auto const dynPart = pCurrentTrack->GetDynamicParticle();
|
||||
fParticle = dynPart->GetDefinition();
|
||||
fPreStepKinE = dynPart->GetKineticEnergy();
|
||||
fCharge = fParticle->GetPDGCharge()/CLHEP::eplus;
|
||||
fMass = fParticle->GetPDGMass();
|
||||
G4double x = limit;
|
||||
|
||||
// If the step is smaller than G4ThreeVector::getTolerance(), it may happen
|
||||
// that the particle does not move. See bug 1992.
|
||||
if (x < minAllowedStep) { return false; }
|
||||
|
||||
// If user has defined an average maximum number of photons to be generated in
|
||||
// a Step, then calculate the Step length for that number of photons using preStep beta.
|
||||
G4double nmax = (*fRindex)[pIndex]->GetMaxValue();
|
||||
fMeanNPhotons = x * AverageNumberOfPhotons(fCharge, pPreStepBeta, nmax);
|
||||
if (pMaxPhotons < fMeanNPhotons) {
|
||||
x *= pMaxPhotons/fMeanNPhotons;
|
||||
x = std::max(x, minAllowedStep);
|
||||
}
|
||||
limit = x;
|
||||
return true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4StandardCerenkovModel::SampleXRays(std::vector<G4Track*>& out,
|
||||
const G4Step& step)
|
||||
{
|
||||
auto const preStep = step.GetPreStepPoint();
|
||||
auto const postStep = step.GetPostStepPoint();
|
||||
G4double kinE = postStep->GetKineticEnergy();
|
||||
G4double beta = pPreStepBeta;
|
||||
G4double b = (*fBetaLim)[pIndex];
|
||||
G4double dbeta = (1.0 - b)/(G4double)(nvec - 1);
|
||||
G4int idx = std::max(G4int((beta - b)/dbeta), 0);
|
||||
idx = std::min(idx, nvec - 1);
|
||||
std::vector<G4double>* v = (*((*fIntegral)[pIndex]))[idx];
|
||||
|
||||
G4ThreeVector pos = preStep->GetPosition();
|
||||
G4ThreeVector dpos = postStep->GetPosition() - pos;
|
||||
G4ThreeVector dir = dpos.unit();
|
||||
G4double time = preStep->GetGlobalTime();
|
||||
G4double dt = postStep->GetGlobalTime() - time;
|
||||
G4double de = fPreStepKinE - kinE;
|
||||
|
||||
// define sub-steps inside the current step
|
||||
G4double x = (1.0 + fPreStepKinE/fMass);
|
||||
G4double delim = fMass*pMaxBetaChange*x*x*x;
|
||||
G4int nn = (G4int)(de/delim) + 1;
|
||||
x = 1.0/(G4double)nn;
|
||||
dpos *= x;
|
||||
dt *= x;
|
||||
de *= x;
|
||||
G4double delta = dpos.mag();
|
||||
fMeanNPhotons *= x;
|
||||
|
||||
// produce Cerenkov gamma - loop over sub-steps
|
||||
G4double ekin = fPreStepKinE;
|
||||
auto const rindex = (*fRindex)[pIndex];
|
||||
std::size_t ni = rindex->GetVectorLength();
|
||||
if (0 == ni) { return; }
|
||||
G4double emin = rindex->Energy(0);
|
||||
G4double mean = delta*fCharge*fCharge*(*(*fMeanNumberOfPhotons)[pIndex])[idx];
|
||||
|
||||
for (G4int i=0; i<nn; ++i) {
|
||||
G4int ngamma = (G4int)G4Poisson(mean);
|
||||
for (G4int j = 0; j < ngamma; ++j) {
|
||||
G4double q = G4UniformRand();
|
||||
G4double e = emin;
|
||||
G4double n = (*rindex)[0];
|
||||
if (ni > 1) {
|
||||
for (std::size_t k = 1; k < ni; ++k) {
|
||||
if ((*v)[k] <= q) {
|
||||
e = rindex->Energy(k - 1);
|
||||
e += (rindex->Energy(k) - e)*(q - (*v)[k - 1])/((*v)[k] - (*v)[k - 1]);
|
||||
n = (*rindex)[k - 1];
|
||||
n += ((*rindex)[k] - n)*(q - (*v)[k - 1])/((*v)[k] - (*v)[k - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
q = G4UniformRand();
|
||||
G4double t = time + q*dt;
|
||||
G4ThreeVector posnew = pos + q*dpos;
|
||||
G4double minCos = 1.0/(n*beta);
|
||||
G4double maxSin2 = (1.0 - minCos)*(1.0 + minCos);
|
||||
G4double cost, sint2;
|
||||
do {
|
||||
cost = 1.0 - G4UniformRand()*(1.0 - minCos);
|
||||
sint2 = (1.0 - cost)*(1.0 + cost);
|
||||
q = G4UniformRand();
|
||||
} while(q * maxSin2 > sint2);
|
||||
|
||||
G4double sint = std::sqrt(sint2);
|
||||
G4double phi = G4UniformRand()*CLHEP::twopi;
|
||||
G4double cosPhi = std::cos(phi);
|
||||
G4double sinPhi = std::sin(phi);
|
||||
G4ThreeVector dirnew(sint*cosPhi, sint*sinPhi, cost);
|
||||
dirnew.rotateUz(dir);
|
||||
|
||||
// Determine polarization of new photon
|
||||
G4ThreeVector photonPolarization(cost*cosPhi, cost*sinPhi, -sint);
|
||||
|
||||
// Rotate back to original coord system
|
||||
photonPolarization.rotateUz(dir);
|
||||
|
||||
auto dp = new G4DynamicParticle(fPhoton, dirnew, e);
|
||||
dp->SetPolarization(photonPolarization);
|
||||
auto track = new G4Track(dp, t, posnew);
|
||||
out.push_back(track);
|
||||
}
|
||||
pos += dpos;
|
||||
time += dt;
|
||||
ekin -= de;
|
||||
beta = std::sqrt(ekin * (ekin + 2*fMass))/(fMass + ekin);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
void G4StandardCerenkovModel::ModelDescription(std::ostream& out) const
|
||||
{
|
||||
out << "The Cerenkov effect simulates optical photons created by the\n";
|
||||
out << "passage of charged particles through matter. Materials need\n";
|
||||
out << "to have the property RINDEX (refractive index) defined." << G4endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -279,7 +279,7 @@ void G4XrayReflection::SaveHenkeDataAsMaterialProperty()
|
||||
for (std::size_t i = 0; i < Ephot.size(); ++i) {
|
||||
G4double lambda = CLHEP::twopi * CLHEP::hbarc / Ephot[i];
|
||||
G4double lambda_sqr = lambda * lambda;
|
||||
RealIndex[i] = fmax(0, factor * lambda_sqr * f1[i]); // delta or 1-RealIndex
|
||||
RealIndex[i] = std::fmax(0, factor * lambda_sqr * f1[i]); // delta or 1-RealIndex
|
||||
ImagIndex[i] = factor * lambda_sqr * f2[i]; // beta or -ImagIndex
|
||||
if (GetVerboseLevel() > 2)
|
||||
G4cout << "Ephot=" << std::setw(10) << Ephot[i] / eV << " eV delta=" << std::setw(10)
|
||||
|
||||
Reference in New Issue
Block a user