Import Geant4 10.3.1 source tree

This commit is contained in:
Gabriele Cosmo
2017-02-28 16:16:20 +01:00
parent a3452e42ac
commit 4597adb7c4
267 changed files with 14761 additions and 24650 deletions
@@ -1,4 +1,4 @@
$Id: History 100666 2016-10-31 10:27:00Z gcosmo $
$Id: History 102545 2017-02-08 14:20:36Z gcosmo $
-------------------------------------------------------------------
=========================================================
@@ -16,6 +16,10 @@ committal in the CVS repository !
----------------------------------------------------------
* Reverse chronological order (last date on top), please *
---------------------------------------------------------
27 Jan 2017: L. Desorgher (emadjoint-V10-02-04)
-Correction of occurence of FPE in G4AdjointForcedInteractionForGamma.
27 Octb 2016: L. Desorgher (emadjoint-V10-02-03)
-Correction in G4AdjointForcedInteractionForGamma to avoid high weight of forced gamma
when only the brem is used.
@@ -172,7 +172,7 @@ G4VParticleChange* G4AdjointForcedInteractionForGamma::AlongStepDoIt(const G4Tra
if (is_free_flight_gamma) { //for free_flight survival probability stays 1
//Accumulate the number of interaction lengths during free flight of gamma
total_acc_nb_fwd_interaction_length+=nb_fwd_interaction_length_over_step;
total_acc_nb_fwd_interaction_length+=nb_fwd_interaction_length_over_step;
total_acc_nb_adj_interaction_length+=nb_adj_interaction_length_over_step;
acc_track_length+=stepLength;
}
@@ -182,8 +182,14 @@ G4VParticleChange* G4AdjointForcedInteractionForGamma::AlongStepDoIt(const G4Tra
acc_nb_adj_interaction_length+=nb_adj_interaction_length_over_step;
theNumberOfInteractionLengthLeft-=nb_adj_interaction_length_over_step;
mc_induced_survival_probability= std::exp(-acc_nb_adj_interaction_length)-std::exp(-total_acc_nb_adj_interaction_length);
mc_induced_survival_probability=mc_induced_survival_probability/(std::exp(-previous_acc_nb_adj_interaction_length)-std::exp(-total_acc_nb_adj_interaction_length));
//Following condition to remove very rare FPE issue
if (total_acc_nb_adj_interaction_length <= 1.e-50 && theNumberOfInteractionLengthLeft<=1.e-50) { //condition added to avoid FPE issue
mc_induced_survival_probability = 1.e50;
}
else {
mc_induced_survival_probability= std::exp(-acc_nb_adj_interaction_length)-std::exp(-total_acc_nb_adj_interaction_length);
mc_induced_survival_probability=mc_induced_survival_probability/(std::exp(-previous_acc_nb_adj_interaction_length)-std::exp(-total_acc_nb_adj_interaction_length));
}
}
G4double weight_correction = fwd_survival_probability/mc_induced_survival_probability;
//weight_correction = 1.;
@@ -14,6 +14,18 @@ committal in the CVS repository !
* Reverse chronological order (last date on top), please *
----------------------------------------------------------*
09-02-2017, MK, tag emdna-V10-02-38
- G4KDNode.hh: remove unused G4ThreeVector header
- G4KDMap.hh: int->size_t + indentation
- G4KDMap.cc: int->size_t
- G4IT & G4Molecule: template specialization
template<> G4KDNode<G4IT / G4Molecule>::~G4KDNode()
14-01-2017, MK, tag emdna-V10-02-37
- Prevent a crash when calling G4ITTrackingManager::EndTracking from
the UserTimeStepAction::PostTimeStepAction
- Add missing: G4ITTrackingManager* G4Scheduler::GetTrackingManager()
27-11-2016, MK, tag emdna-V10-02-36
- G4Electron_aq: correct charge
- G4DNADamages -> G4DNADamage
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4IT.hh 100802 2016-11-02 14:55:27Z gcosmo $
// $Id: G4IT.hh 102637 2017-02-10 11:08:17Z gcosmo $
//
// Author: Mathieu Karamitros
@@ -51,6 +51,7 @@
#include "G4ITType.hh"
#include "G4ThreeVector.hh"
#include "G4VUserTrackInformation.hh"
#include "G4KDNode.hh"
///
// To implement your own IT class, you should use
@@ -60,6 +61,9 @@
///
class G4IT;
template<>
G4KDNode<G4IT>::~G4KDNode();
class G4TrackingInformation;
//template<typename PointT> class G4KDNode;
class G4KDNode_Base;
@@ -163,7 +163,12 @@ public:
inline void PushToKill(G4Track* track)
{
G4TrackList::Pop(track);
fToBeKilledList.push_back(track);
if(track->GetTrackStatus() != fKillTrackAndSecondaries){
track->SetTrackStatus(fStopAndKill);
}
}
bool MergeNextTimeToMainList(double& time);
@@ -57,67 +57,67 @@ class G4KDNode_Base;
class __1DSortOut
{
public :
__1DSortOut(size_t dimension);
__1DSortOut(const __1DSortOut& right);
int GetDimension();
G4KDNode_Base* GetMidle(int& /*G4KDNode_deque*/);
__1DSortOut(size_t dimension);
__1DSortOut(const __1DSortOut& right);
int GetDimension();
G4KDNode_Base* GetMidle(size_t& /*G4KDNode_deque*/);
std::deque<G4KDNode_Base*>::iterator Insert(G4KDNode_Base*);
G4KDNode_Base* PopOutMiddle();
void Sort();
void Erase(std::deque<G4KDNode_Base*>::iterator &);
size_t Size()
{
return fContainer.size();
}
std::deque<G4KDNode_Base*>::iterator Insert(G4KDNode_Base*);
G4KDNode_Base* PopOutMiddle();
void Sort();
void Erase(std::deque<G4KDNode_Base*>::iterator &);
size_t Size()
{
return fContainer.size();
}
protected :
struct sortOutNDim
{
sortOutNDim( size_t dimension)
{
fDimension = dimension;
}
bool operator() (G4KDNode_Base* const& lhs, G4KDNode_Base* const& rhs);
size_t fDimension;
};
struct sortOutNDim
{
sortOutNDim( size_t dimension)
{
fDimension = dimension;
}
bool operator() (G4KDNode_Base* const& lhs, G4KDNode_Base* const& rhs);
size_t fDimension;
};
std::deque<G4KDNode_Base*> fContainer;
sortOutNDim fSortOutNDim;
std::deque<G4KDNode_Base*> fContainer;
sortOutNDim fSortOutNDim;
};
class G4KDMap
{
public:
G4KDMap(size_t dimensions) : fSortOut(dimensions, __1DSortOut(dimensions))
{
G4KDMap(size_t dimensions): fSortOut(dimensions, __1DSortOut(dimensions))
{
fIsSorted = false;
// for(size_t i = 0 ; i < dimensions ; i++)
// {
// fSortOut[i] = new __1DSortOut(i);
// }
}
}
void Insert(G4KDNode_Base* pos);
void Sort();
void Insert(G4KDNode_Base* pos);
void Sort();
G4KDNode_Base* PopOutMiddle(size_t dimension);
size_t GetDimension()
{
return fSortOut.size();
}
G4KDNode_Base* PopOutMiddle(size_t dimension);
size_t GetDimension()
{
return fSortOut.size();
}
size_t GetSize()
{
return fMap.size();
}
size_t GetSize()
{
return fMap.size();
}
private:
bool fIsSorted;
std::vector<__1DSortOut> fSortOut;
std::map<G4KDNode_Base*, std::vector<std::deque<G4KDNode_Base*>::iterator > > fMap;
bool fIsSorted;
std::vector<__1DSortOut> fSortOut;
std::map<G4KDNode_Base*, std::vector<std::deque<G4KDNode_Base*>::iterator>> fMap;
// A mettre directement dans G4KDNode
// A mettre directement dans G4KDNode
};
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4KDNode.hh 100802 2016-11-02 14:55:27Z gcosmo $
// $Id: G4KDNode.hh 102637 2017-02-10 11:08:17Z gcosmo $
//
// Author: Mathieu Karamitros
@@ -51,7 +51,9 @@
//#include <map>
#include <vector>
#include <deque>
#include <G4ThreeVector.hh>
#include <ostream>
// geant4
#include <G4Allocator.hh>
#include "globals.hh"
@@ -63,7 +65,7 @@ class G4KDMap;
class G4KDNode_Base
{
public:
//________________________
//----------------------------
// For root node :
// parent = 0, axis = 0, side = 0
G4KDNode_Base(G4KDTree*, G4KDNode_Base* /*parent*/);
@@ -72,25 +74,25 @@ public:
virtual void InactiveNode();
virtual bool IsValid() const{ return true; }
//________________________
//----------------------------
inline G4KDTree* GetTree() const {return fTree;}
inline void SetTree(G4KDTree* tree) {fTree = tree;}
//________________________
//----------------------------
int GetDim() const;
inline int GetAxis() const{return fAxis;}
inline G4KDNode_Base* GetParent(){return fParent;}
inline G4KDNode_Base* GetLeft(){return fLeft;}
inline G4KDNode_Base* GetRight(){return fRight;}
//________________________
//----------------------------
template<typename Position>
G4KDNode_Base* FindParent(const Position& x0);
template<typename PointT>
G4KDNode_Base* Insert(PointT* point);
template<typename PointT>
G4KDNode_Base* Insert(const PointT& point);
G4KDNode_Base* Insert(const PointT& point);
int Insert(G4KDNode_Base* newNode);
void PullSubTree();
@@ -98,8 +100,10 @@ public:
void Print(std::ostream& out, int level = 0) const;
// std::vector<std::deque<G4KDNode_Base* >::iterator >* GetIteratorsForSortingAlgo(G4KDMap*);
// std::map<G4KDMap*, std::vector<std::deque<G4KDNode_Base* >::iterator > >* fpIteratorInSortingAlgo;
// std::vector<std::deque<G4KDNode_Base*>::iterator>*
// GetIteratorsForSortingAlgo(G4KDMap*);
// std::map<G4KDMap*, std::vector<std::deque<G4KDNode_Base*>::iterator>>*
// fpIteratorInSortingAlgo;
protected:
//°°°°°°°°°°°
@@ -132,7 +136,7 @@ template<typename PointT>
class G4KDNode : public G4KDNode_Base
{
public:
//________________________
//----------------------------
// For root node :
// parent = 0, axis = 0, side = 0
G4KDNode(G4KDTree*, PointT* /*point*/, G4KDNode_Base* /*parent*/);
@@ -165,18 +169,18 @@ template<typename PointT>
protected:
PointT* fPoint;
G4bool fValid;
bool fValid;
private:
G4KDNode(const G4KDNode<PointT>& right);
G4KDNode& operator=(const G4KDNode<PointT>& right);
static G4ThreadLocal G4Allocator<G4KDNode<PointT> >* fgAllocator;
static G4ThreadLocal G4Allocator<G4KDNode<PointT>>* fgAllocator;
};
template<typename PointT>
G4ThreadLocal G4Allocator<G4KDNode<PointT> >* G4KDNode<PointT>::fgAllocator =
0;
G4ThreadLocal G4Allocator<G4KDNode<PointT>>*
G4KDNode<PointT>::fgAllocator = 0;
template<typename PointT>
void* G4KDNode<PointT>::operator new(size_t)
@@ -191,17 +195,16 @@ template<typename PointT>
fgAllocator->FreeSingle((G4KDNode<PointT> *) aNode);
}
/**
* G4KDNode stores one entity in G4KDTree
* This class is for internal use only
*/
template<typename PointCopyT>
class G4KDNodeCopy : public G4KDNode_Base
class G4KDNodeCopy: public G4KDNode_Base
{
public:
//________________________
//----------------------------
// For root node :
// parent = 0, axis = 0, side = 0
G4KDNodeCopy(G4KDTree* tree,
@@ -254,9 +257,9 @@ template<typename PointCopyT>
private:
G4KDNodeCopy(const G4KDNodeCopy<PointCopyT>& right) :
G4KDNode_Base(right), fPoint(0)
{
fValid = false;
}
{
fValid = false;
}
G4KDNodeCopy<PointCopyT>&
operator=(const G4KDNodeCopy<PointCopyT>& right)
@@ -276,8 +279,8 @@ template<typename PointCopyT>
};
template<typename PointT>
G4ThreadLocal G4Allocator<G4KDNodeCopy<PointT>>* G4KDNodeCopy<PointT>::fgAllocator =
0;
G4ThreadLocal G4Allocator<G4KDNodeCopy<PointT>>*
G4KDNodeCopy<PointT>::fgAllocator = 0;
#include "G4KDNode.icc"
@@ -190,6 +190,11 @@ public:
{
return fMaxTimeStep;
}
inline G4ITTrackingManager* GetTrackingManager() const
{
return fpTrackingManager;
}
protected:
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4IT.cc 94218 2015-11-09 08:24:48Z gcosmo $
// $Id: G4IT.cc 102637 2017-02-10 11:08:17Z gcosmo $
//
// Author: Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr)
//
@@ -56,20 +56,25 @@ G4IT* GetIT(const G4Track& track)
return (dynamic_cast<G4IT*>(track.GetUserInformation()));
}
template<>
G4KDNode<G4IT>::~G4KDNode(){
fPoint->SetNode(nullptr);
}
//------------------------------------------------------------------------------
//
// Constructors / Destructors
//
G4IT::G4IT() :
G4VUserTrackInformation("G4IT"),
fpTrack(0),
fpPreviousIT(0),
fpNextIT(0),
fpTrack(nullptr),
fpPreviousIT(nullptr),
fpNextIT(nullptr),
fpTrackingInformation(new G4TrackingInformation())
{
fpITBox = 0;
fpKDNode = 0;
fpTrackNode = 0;
fpITBox = nullptr;
fpKDNode = nullptr;
fpTrackNode = nullptr;
fParentID_A = 0;
fParentID_B = 0;
}
@@ -77,14 +82,14 @@ G4IT::G4IT() :
// Use only by inheriting classes
G4IT::G4IT(const G4IT& /*right*/) :
G4VUserTrackInformation("G4IT"),
fpTrack(0),
fpPreviousIT(0),
fpNextIT(0),
fpTrack(nullptr),
fpPreviousIT(nullptr),
fpNextIT(nullptr),
fpTrackingInformation(new G4TrackingInformation())
{
fpITBox = 0;
fpKDNode = 0;
fpTrackNode = 0;
fpITBox = nullptr;
fpKDNode = nullptr;
fpTrackNode = nullptr;
fParentID_A = 0;
fParentID_B = 0;
}
@@ -104,15 +109,15 @@ G4IT& G4IT::operator=(const G4IT& right)
if (this == &right) return *this;
fpTrack = 0;
fpITBox = 0;
fpPreviousIT = 0;
fpNextIT = 0;
fpKDNode = 0;
fpTrack = nullptr;
fpITBox = nullptr;
fpPreviousIT = nullptr;
fpNextIT = nullptr;
fpKDNode = nullptr;
fParentID_A = 0;
fParentID_B = 0;
fpTrackingInformation = 0;
fpTrackNode = 0;
fpTrackingInformation = nullptr;
fpTrackNode = nullptr;
return *this;
}
@@ -125,8 +130,8 @@ G4IT::G4IT(G4Track * aTrack) :
{
fpITBox = 0;
fpTrack = aTrack;
fpKDNode = 0;
fpTrackNode = 0;
fpKDNode = nullptr;
fpTrackNode = nullptr;
fParentID_A = 0;
fParentID_B = 0;
RecordCurrentPositionNTime();
@@ -137,18 +142,19 @@ void G4IT::TakeOutBox()
if(fpITBox)
{
fpITBox->Extract(this);
fpITBox = nullptr;
}
if(fpTrackNode)
{
delete fpTrackNode;
fpTrackNode = 0;
fpTrackNode = nullptr;
}
if(fpKDNode)
{
InactiveNode(fpKDNode);
fpKDNode = 0;
fpKDNode = nullptr;
}
}
@@ -159,7 +165,7 @@ G4IT::~G4IT()
if(fpTrackingInformation)
{
delete fpTrackingInformation;
fpTrackingInformation = 0;
fpTrackingInformation = nullptr;
}
// Note :
@@ -199,8 +205,6 @@ G4bool G4IT::operator!=(const G4IT& right) const
return !(this->operator==(right));
}
double G4IT::operator[](int i) const
{
return fpTrack->GetPosition()[i];
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4ITTrackingManager.cc 91584 2015-07-27 13:01:48Z gcosmo $
// $Id: G4ITTrackingManager.cc 102637 2017-02-10 11:08:17Z gcosmo $
//
// Author: Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr)
//
@@ -96,7 +96,7 @@ void G4ITTrackingManager::EndTracking(G4Track* track)
fpTrackingInteractivity->GetSteppingVerbose()->TrackingEnded(track);
#endif
}
G4TrackList::Pop(track);
G4ITTrackHolder::Instance()->PushToKill(track);
}
@@ -53,10 +53,10 @@ int __1DSortOut::GetDimension()
return fSortOutNDim.fDimension;
}
G4KDNode_Base* __1DSortOut::GetMidle(int& main_middle)
G4KDNode_Base* __1DSortOut::GetMidle(size_t& main_middle)
{
int contSize = fContainer.size();
main_middle = (int) ceil(contSize / 2.); // ceil = round up
size_t contSize = fContainer.size();
main_middle = (size_t) ceil(contSize / 2.); // ceil = round up
return fContainer[main_middle];
}
@@ -67,7 +67,7 @@ _deq_iterator __1DSortOut::Insert(G4KDNode_Base* pos)
G4KDNode_Base* __1DSortOut::PopOutMiddle()
{
int middle;
size_t middle;
G4KDNode_Base* pos = GetMidle(middle);
_deq_iterator deq_pos = fContainer.begin() + middle;
@@ -57,15 +57,15 @@
void InactiveNode(G4KDNode_Base* node)
{
if(!node) return ;
node->InactiveNode() ;
if(node == nullptr) return;
// if(node->IsValid())
node->InactiveNode();
}
void Free(G4KDNode_Base*& node)
{
if(node)
delete node ;
node = 0;
if(node) delete node;
node = nullptr;
}
//______________________________________________________________________
@@ -74,8 +74,8 @@ G4KDNode_Base::G4KDNode_Base(G4KDTree* tree,
fTree(tree),
fLeft(0), fRight(0), fParent(parent)
{
fSide = 0;
fAxis = fParent == 0? 0 : fParent->fAxis +1 < fTree->fDim? fParent->fAxis+1:0;
fSide = 0;
fAxis = fParent == 0? 0 : fParent->fAxis +1 < fTree->fDim? fParent->fAxis+1:0;
}
// Copy constructor should not be used
@@ -83,8 +83,8 @@ G4KDNode_Base::G4KDNode_Base(const G4KDNode_Base& ):
fTree(0),
fLeft(0), fRight(0), fParent(0)
{
fSide = 0;
fAxis = 0;
fSide = 0;
fAxis = 0;
}
// Assignement should not be used
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAOneStepThermalizationModel.cc 101807 2016-11-30 13:42:28Z gunter $
// $Id: G4DNAOneStepThermalizationModel.cc 102637 2017-02-10 11:08:17Z gcosmo $
//
// Author: Mathieu Karamitros
//
@@ -141,7 +141,7 @@ namespace DNA{ namespace Penetration{
size_t lowBin, upBin;
if(k_eV >= 1.){
lowBin=std::floor(k_eV)+1;
lowBin=floor(k_eV)+1;
upBin=std::min(lowBin+1, size_t(10));
}
else{
@@ -183,7 +183,7 @@ namespace DNA{ namespace Penetration{
static constexpr double factor = 2.20496999539;
// 1./(3. - 8./CLHEP::pi);
double sigma1D = std::sqrt(std::pow(sigma3D, 2.)*factor);
double sigma1D = sqrt(pow(sigma3D, 2.)*factor);
// G4cout << "sigma1D = " << sigma1D/CLHEP::nanometer << G4endl;
@@ -75,6 +75,10 @@
#include "G4Allocator.hh"
#include "G4MoleculeDefinition.hh"
class G4Molecule;
template<>
G4KDNode<G4Molecule>::~G4KDNode();
class G4Molecule;
class G4MolecularConfiguration;
class G4MoleculeDefinition;
@@ -22,7 +22,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4Molecule.cc 100802 2016-11-02 14:55:27Z gcosmo $
// $Id: G4Molecule.cc 102637 2017-02-10 11:08:17Z gcosmo $
//
// ---------------------------------------------------------------------
// GEANT 4 class header file
@@ -66,6 +66,13 @@ G4ThreadLocal G4Allocator<G4Molecule> *aMoleculeAllocator = 0;
//______________________________________________________________________________
template<>
G4KDNode<G4Molecule>::~G4KDNode(){
fPoint->SetNode(nullptr);
}
//______________________________________________________________________________
G4Molecule* GetMolecule(const G4Track& track)
{
return (G4Molecule*) (GetIT(track));
@@ -152,7 +159,7 @@ G4Molecule::G4Molecule() :
G4Molecule::~G4Molecule()
{
if (fpTrack != NULL)
if (fpTrack != nullptr)
{
if (G4VMoleculeCounter::Instance()->InUse())
{
@@ -161,9 +168,9 @@ G4Molecule::~G4Molecule()
fpTrack->GetGlobalTime(),
&(fpTrack->GetPosition()));
}
fpTrack = 0;
fpTrack = nullptr;
}
fpMolecularConfiguration = 0;
fpMolecularConfiguration = nullptr;
}
//______________________________________________________________________________
@@ -1,4 +1,4 @@
$Id: History 101681 2016-11-21 09:33:05Z gcosmo $
$Id: History 102548 2017-02-08 14:33:25Z gcosmo $
-------------------------------------------------------------------
=========================================================
@@ -17,6 +17,9 @@ committal in the CVS repository !
* Reverse chronological order (last date on top), please *
----------------------------------------------------------
14 December 16: V.Ivant (emutils-V10-02-39)
- G4EmParametersMessenger - fixed typo (#1929)
19 November 16: V.Ivant (emutils-V10-02-38)
- G4EmParametersMessenger - fixed typo
@@ -259,7 +259,7 @@ G4EmParametersMessenger::G4EmParametersMessenger(G4EmParameters* ptr)
fr1Cmd = new G4UIcmdWithADouble("/process/msc/RangeFactorMuHad",this);
fr1Cmd->SetGuidance("Set RangeFactor for msc processes of muons/hadrons");
fr1Cmd->SetParameterName("Fr1",true);
fr1Cmd->SetRange("Fr>0");
fr1Cmd->SetRange("Fr1>0");
fr1Cmd->SetDefaultValue(0.2);
fr1Cmd->AvailableForStates(G4State_PreInit,G4State_Idle);
@@ -14,6 +14,103 @@ code and to keep track of all tags.
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
21 February 2017 Vladimir Ivanchenko (hadr-deex-V10-02-72)
- G4LevelReader - in the case of broken file structure or absence of
a file G4Exception will be issued
16 February 2017 Vladimir Ivanchenko (hadr-deex-V10-02-71)
- G4GammaTransition - added control on printout for all G4cout; removed
thread unsafe check
15 February 2017 Vladimir Ivanchenko
- G4GammaTransition - added control on printout
- G4LevelManager - fixed unpacking of spin
14 February 2017 Vladimir Ivanchenko
Fix no-reproducibility due to precision lost in Lorentz transformations
- G4ExcitationHandler, G4PhotonEvaporation - use floating level number
- G4GammaTransition - use a new method of G4Fragment::SetExcitationEnergy()
which allows to keep excitation energy exact as in the database to
avoid rare non-reproducibility; added SetVerbose method
- G4PolarizationTransition - added SetVerbose method; protect from
extra verbosity
13 February 2017 Vladimir Ivanchenko
Fixed U235[0.076] problem:
- G4DeexPrecoParameters - min excitation energy is set to 10 eV (was 100 eV)
- G4LevelReader - if value of alpha (relative probability of the internal
conversion) is 10^10, then assume that internal conversion will go via
outer levels and gamma emission has zero probability, internal
conversion is forced intdependently on other flags
08 February 2017 Vladimir Ivanchenko (hadr-deex-V10-02-70)
- G4GammaTransition::SampleDirection - D.Wright fixed multipolarity
after changing multipolarity Nx by 1 in the new dataset
27 January 2017 Vladimir Ivanchenko
- G4GammaTransition, G4PhotonEvaporation, G4NuclLevel - minor cleanup
- G4DeexPrecoParameters - by default used uniform angular distribution
in CM sytem of precompound decay
18 January 2017 Vladimir Ivanchenko
- G4GammaTransition::SampleDirection - return back sampling in the case, when
initial state has angular moment but its polarisation is random
- G4PhotonEvaporation - added internal conversion even if the data are not
stored
11 January 2017 Dennis Wright
- G4PolarizationTransition::SetGammaTransitionData: replace fTwoJ1 and fTwoJ2
with their absolute values to avoid crash
- G4GammaTransition::SampleDirection: remove return; from (!np) block,
otherwise only zero polarization is returned.
Also remove line
fPolTrans.UpdatePolarizationToFinalState(fDirection.z(), fDirection.phi(), nuc);
in order to comply with instructions in G4PolarizationTransition.hh (call order)
and to properly initialize the nuclear polarization.
9 January 2017 Dennis Wright
- G4NucLevel::TransitionType: use % operator to correctly strip off
leading digit
- G4LevelReader::LevelManager: added comments to describe some variables
- G4PolarizationTransition::UpdatePolarizationToFinalState: add comment
showing where zero-value entries are trimmed off
19 December 2016 Vladimir Ivanchenko
- G4LevelReader - fixed Ra228 problem - read all levels from
a data file
16 December 2016 Vladimir Ivanchenko
- G4PolarizationTransition - J.Detwiler has fixed computation
of multipolarity
16 December 2016 Vladimir Ivanchenko
- G4DeexPrecoParameters - change default time limit from 0.01 s to
1 microsecond
- G4PhotonEvaporation, G4GammaTransition - improved sampling
and kinematics for internal conversion
- G4PolarizationTransition - J.Detwiler has fixed computation
of polarisation
14 December 2016 Vladimir Ivanchenko
- G4LevelManager, G4NuclLevel, G4LevelReader - reduce memory for
description of a level: each two integer parameters are packed
into one integer values; use only one set of probabilities of
transition independently on use-case (HEP or radioactive decay);
fill internal conversion coefficients into the data structure only
if a flag SetStoreAllLevels() is set to true. In the last case,
more memory required per isotope (~8 times)
- G4DeexPrecoParameters - extended Dump() printout; make new
data structure default
- G4ExcitationHandler - moved Dump() printout in Initialise()
method, print info if evaporation channels are changed; added
local data member to control verbosity level
- G4VEvaporation - added extra const access method
- G4Evaporation - added data member to control verbosity level
- G4GammaTransition - in the case, when internal conversion data
are not filled but in sampling e- emission is selected, sample e-
with kinetic energy corresponding to transition between nuclear
levels ignoring atomic effects
01 December 2016 Vladimir Ivanchenko (hadr-deex-V10-02-69)
- G4KalbachCrossSection, G4NuclearLevelData, G4GammaTransition
Gunter Folger fixed use of std::sqrt
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4Evaporation.hh 98808 2016-08-11 08:35:24Z gcosmo $
// $Id: G4Evaporation.hh 102590 2017-02-09 10:13:30Z gcosmo $
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara
@@ -86,6 +86,7 @@ private:
G4bool operator==(const G4Evaporation &right) const = delete;
G4bool operator!=(const G4Evaporation &right) const = delete;
G4int fVerbose;
size_t nChannels;
G4double minExcitation;
G4NistManager* nist;
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4VEvaporation.hh 98739 2016-08-09 12:56:55Z gcosmo $
// $Id: G4VEvaporation.hh 102590 2017-02-09 10:13:30Z gcosmo $
//
// Hadronic Process: Nuclear De-excitations interface
//
@@ -74,9 +74,11 @@ public:
inline G4VEvaporationChannel* GetFissionChannel();
// for inverse cross section choice
inline void SetOPTxs(G4int opt) { OPTxs = opt;}
inline void SetOPTxs(G4int opt);
// for superimposed Coulomb Barrier for inverse cross sections
inline void UseSICB(G4bool use) { useSICB = use; }
inline void UseSICB(G4bool use);
inline size_t GetNumberOfChannels() const;
protected:
@@ -116,9 +118,22 @@ inline G4VEvaporationChannel* G4VEvaporation::GetPhotonEvaporation()
inline G4VEvaporationChannel* G4VEvaporation::GetFissionChannel()
{
G4VEvaporationChannel* p = 0;
if(theChannels->size() > 1) { p = (*theChannels)[1]; }
return p;
return (theChannels && theChannels->size() > 1) ? (*theChannels)[1] : nullptr;
}
inline void G4VEvaporation::SetOPTxs(G4int opt)
{
OPTxs = opt;
}
inline void G4VEvaporation::UseSICB(G4bool use)
{
useSICB = use;
}
inline size_t G4VEvaporation::GetNumberOfChannels() const
{
return theChannels ? theChannels->size() : 0;
}
#endif
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4Evaporation.cc 101865 2016-12-02 13:06:50Z gcosmo $
// $Id: G4Evaporation.cc 102590 2017-02-09 10:13:30Z gcosmo $
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (Oct 1998)
@@ -64,7 +64,8 @@
#include "Randomize.hh"
G4Evaporation::G4Evaporation(G4VEvaporationChannel* photoEvaporation)
: G4VEvaporation(),nChannels(0),minExcitation(0.1*keV),isInitialised(false)
: G4VEvaporation(),fVerbose(0),nChannels(0),minExcitation(0.1*keV),
isInitialised(false)
{
if(photoEvaporation) { SetPhotonEvaporation(photoEvaporation); }
else { SetPhotonEvaporation(new G4PhotonEvaporation()); }
@@ -100,11 +101,14 @@ void G4Evaporation::InitialiseChannels()
void G4Evaporation::InitialiseChannelFactory()
{
//G4cout << "### G4Evaporation::InitialiseChannelFactory " << this << G4endl;
theChannels = theChannelFactory->GetChannel();
nChannels = theChannels->size();
probabilities.resize(nChannels, 0.0);
if(fVerbose > 0) {
G4cout << "### G4Evaporation::InitialiseChannelFactory for "
<< nChannels << " channels " << this << G4endl;
}
for(size_t i=0; i<nChannels; ++i) {
(*theChannels)[i]->SetOPTxs(OPTxs);
(*theChannels)[i]->Initialise();
@@ -168,26 +172,27 @@ void G4Evaporation::BreakFragment(G4FragmentVector* theResult,
// check if it is stable, then finish evaporation
G4double abun = nist->GetIsotopeAbundance(Z, A);
/*
G4cout << "### G4Evaporation::BreakItUp step " << ia << " Z= " << Z
<< " A= " << A << " Eex(MeV)= "
<< theResidualNucleus->GetExcitationEnergy()
<< " aban= " << abun << G4endl;
*/
if(fVerbose > 0) {
G4cout << "### G4Evaporation::BreakItUp step " << ia << " Z= " << Z
<< " A= " << A << " Eex(MeV)= "
<< theResidualNucleus->GetExcitationEnergy()
<< " aban= " << abun << G4endl;
}
// stop deecitation loop in the case of a cold stable fragment
if(Eex <= minExcitation && abun > 0.0) { break; }
totprob = 0.0;
maxchannel = nChannels;
/*
G4cout << "### Evaporation loop #" << ia
<< " Fragment: " << theResidualNucleus << G4endl;
*/
if(fVerbose > 1) {
G4cout << "### Evaporation loop #" << ia
<< " Fragment: " << theResidualNucleus << G4endl;
}
// loop over evaporation channels
for(i=0; i<nChannels; ++i) {
prob = (*theChannels)[i]->GetEmissionProbability(theResidualNucleus);
//G4cout << " Channel# " << i << " prob= " << prob << G4endl;
if(fVerbose > 0 && prob > 0.0) {
G4cout << " Channel# " << i << " prob= " << prob << G4endl;
}
totprob += prob;
probabilities[i] = totprob;
@@ -204,7 +209,9 @@ void G4Evaporation::BreakFragment(G4FragmentVector* theResult,
// photon evaporation in the case of no other channels available
// do evaporation chain and reset total probability
if(0.0 < totprob && probabilities[0] == totprob) {
//G4cout << "Start chain of gamma evaporation" << G4endl;
if(fVerbose > 1) {
G4cout << "Start chain of gamma evaporation" << G4endl;
}
(*theChannels)[0]->BreakUpChain(theResult, theResidualNucleus);
totprob = 0.0;
}
@@ -214,9 +221,9 @@ void G4Evaporation::BreakFragment(G4FragmentVector* theResult,
// if fragment is exotic, then force its decay
if(0.0 == abun) {
//G4cout << "$$$ Decay exotic fragment" << G4endl;
if(!unstableBreakUp->BreakUpChain(theResult, theResidualNucleus))
{ break; }
if(fVerbose > 1) { G4cout << "$$$ Decay exotic fragment" << G4endl; }
} else {
break;
}
@@ -227,9 +234,9 @@ void G4Evaporation::BreakFragment(G4FragmentVector* theResult,
// loop over evaporation channels
for(i=0; i<maxchannel; ++i) { if(probabilities[i] >= totprob) { break; } }
//G4cout << "Channel # " << i << G4endl;
if(fVerbose > 1) { G4cout << "Channel # " << i << G4endl; }
G4Fragment* frag = (*theChannels)[i]->EmittedFragment(theResidualNucleus);
//if(frag) G4cout << " " << *frag << G4endl;
if(fVerbose > 1 && frag) { G4cout << " " << *frag << G4endl; }
// normaly a fragment should be created
if(frag) { theResult->push_back(frag); }
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4ExcitationHandler.hh 98808 2016-08-11 08:35:24Z gcosmo $
// $Id: G4ExcitationHandler.hh 102590 2017-02-09 10:13:30Z gcosmo $
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (May 1998)
@@ -127,6 +127,7 @@ private:
G4IonTable* theTableOfIons;
G4NistManager* nist;
G4int fVerbose;
G4bool isInitialised;
G4bool isEvapLocal;
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4ExcitationHandler.cc 101865 2016-12-02 13:06:50Z gcosmo $
// $Id: G4ExcitationHandler.cc 102726 2017-02-20 13:15:29Z gcosmo $
//
// Hadronic Process: Nuclear De-excitations
// by V. Lara (May 1998)
@@ -84,14 +84,13 @@
G4ExcitationHandler::G4ExcitationHandler()
: maxZForFermiBreakUp(9),maxAForFermiBreakUp(17),
isInitialised(false),isEvapLocal(true)
fVerbose(0),isInitialised(false),isEvapLocal(true)
{
theTableOfIons = G4ParticleTable::GetParticleTable()->GetIonTable();
nist = G4NistManager::Instance();
theMultiFragmentation = nullptr;
theFermiModel = nullptr;
G4NuclearLevelData::GetInstance()->GetParameters()->Dump();
G4Pow::GetInstance();
theEvaporation = new G4Evaporation();
thePhotonEvaporation = theEvaporation->GetPhotonEvaporation();
@@ -100,7 +99,7 @@ G4ExcitationHandler::G4ExcitationHandler()
theEvapList.reserve(30);
thePhotoEvapList.reserve(10);
SetParameters();
//G4cout << "### New handler " << this << G4endl;
if(fVerbose > 0) { G4cout << "### New handler " << this << G4endl; }
}
G4ExcitationHandler::~G4ExcitationHandler()
@@ -124,12 +123,21 @@ void G4ExcitationHandler::SetParameters()
void G4ExcitationHandler::Initialise()
{
if(isInitialised) { return; }
//G4cout << "G4ExcitationHandler::Initialise() started " << this << G4endl;
if(fVerbose > 0) {
G4cout << "G4ExcitationHandler::Initialise() started " << this << G4endl;
}
G4NuclearLevelData::GetInstance()->GetParameters()->Dump();
isInitialised = true;
SetParameters();
theMultiFragmentation = new G4StatMF();
theFermiModel->Initialise();
theEvaporation->InitialiseChannels();
if(G4Threading::IsMasterThread()) {
G4cout << "Number of de-excitation channels "
<< theEvaporation->GetNumberOfChannels();
if(fVerbose > 0) { G4cout << " " << this; }
G4cout << G4endl;
}
}
void G4ExcitationHandler::SetEvaporation(G4VEvaporation* ptr, G4bool flag)
@@ -182,16 +190,23 @@ void G4ExcitationHandler::SetDeexChannelsType(G4DeexChannelType val)
evap->SetGEMChannel();
}
evap->InitialiseChannels();
if(G4Threading::IsMasterThread()) {
G4cout << "Number of de-excitation channels is changed to "
<< theEvaporation->GetNumberOfChannels();
if(fVerbose > 0) { G4cout << " " << this; }
G4cout << G4endl;
}
}
G4ReactionProductVector *
G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
{
//G4cout << "@@@@@@@@@@ Start G4Excitation Handler @@@@@@@@@@@@@ " << hcount << G4endl;
{
// Variables existing until end of method
G4Fragment * theInitialStatePtr = new G4Fragment(theInitialState);
//G4cout << theInitialState << G4endl;
if(fVerbose > 1) {
G4cout << "@@@@@@@@@@ Start G4Excitation Handler @@@@@@@@@@@@@ " << G4endl;
G4cout << theInitialState << G4endl;
}
if(!isInitialised) { Initialise(); }
// pointer to fragment vector which receives temporal results
@@ -270,11 +285,11 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
}
}
}
/*
G4cout << "## After first step " << theEvapList.size() << " for evap; "
<< thePhotoEvapList.size() << " for photo-evap; "
<< theResults.size() << " results. " << G4endl;
*/
if(fVerbose > 2) {
G4cout << "## After first step " << theEvapList.size() << " for evap; "
<< thePhotoEvapList.size() << " for photo-evap; "
<< theResults.size() << " results. " << G4endl;
}
// -----------------------------------
// FermiBreakUp and De-excitation loop
// -----------------------------------
@@ -284,8 +299,10 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
size_t kk;
for (kk=0; kk<theEvapList.size(); ++kk) {
frag = theEvapList[kk];
//G4cout << "Next evaporate: " << G4endl;
//G4cout << *frag << G4endl;
if(fVerbose > 2) {
G4cout << "Next evaporate: " << G4endl;
G4cout << *frag << G4endl;
}
if(kk >= countmax) {
G4ExceptionDescription ed;
ed << "Infinite loop in the de-excitation module: " << kk
@@ -304,7 +321,7 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
if(theFermiModel->IsApplicable(Z, A, frag->GetExcitationEnergy())) {
theFermiModel->BreakFragment(&results, frag);
size_t nsec = results.size();
//G4cout << "FermiBreakUp Nsec= " << nsec << G4endl;
if(fVerbose > 2) { G4cout << "FermiBreakUp Nsec= " << nsec << G4endl; }
// FBU takes care to delete input fragment or add it to the results
// The secondary may be excited - photo-evaporation should be applied
@@ -318,7 +335,7 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
// apply Evaporation, residual nucleus is always added to the results
theEvaporation->BreakFragment(&results, frag);
size_t nsec = results.size();
//G4cout << "Evaporation Nsec= " << nsec << G4endl;
if(fVerbose > 2) { G4cout << "Evaporation Nsec= " << nsec << G4endl; }
// no evaporation
if(1 >= nsec) {
@@ -328,10 +345,11 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
// Sort out secondary fragments
for (size_t j = 0; j<nsec; ++j) {
//G4cout << "Evaporated product #" << j << G4endl;
//G4cout << results[j] << G4endl;
if(fVerbose > 3) {
G4cout << "Evaporated product #" << j << G4endl;
G4cout << results[j] << G4endl;
}
A = results[j]->GetA_asInt();
//G4cout << "A= " << A << G4endl;
if(A <= 1) {
theResults.push_back(results[j]); // gamma, p, n
continue;
@@ -356,11 +374,11 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
}
} // end of loop on secondary
} // end of the loop over theEvapList
/*
G4cout << "## After 2nd step " << theEvapList.size() << " was evap; "
<< thePhotoEvapList.size() << " for photo-evap; "
<< theResults.size() << " results. " << G4endl;
*/
if(fVerbose > 2) {
G4cout << "## After 2nd step " << theEvapList.size() << " was evap; "
<< thePhotoEvapList.size() << " for photo-evap; "
<< theResults.size() << " results. " << G4endl;
}
// -----------------------
// Photon-Evaporation loop
// -----------------------
@@ -369,8 +387,10 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
size_t kkmax = thePhotoEvapList.size();
for (kk=0; kk<kkmax; ++kk) {
frag = thePhotoEvapList[kk];
//G4cout << "Next photon evaporate: " << thePhotonEvaporation << G4endl;
//G4cout << *frag << G4endl;
if(fVerbose > 2) {
G4cout << "Next photon evaporate: " << thePhotonEvaporation << G4endl;
G4cout << *frag << G4endl;
}
exEnergy = frag->GetExcitationEnergy();
// photon de-excitation only for hot fragments
@@ -378,15 +398,15 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
thePhotonEvaporation->BreakUpChain(&theResults, frag);
}
// priamry fragment is kept
// primary fragment is kept
theResults.push_back(frag);
} // end of photon-evaporation loop
/*
G4cout << "## After 3d step " << theEvapList.size() << " was evap; "
<< thePhotoEvapList.size() << " was photo-evap; "
<< theResults.size() << " results. " << G4endl;
*/
if(fVerbose > 2) {
G4cout << "## After 3d step " << theEvapList.size() << " was evap; "
<< thePhotoEvapList.size() << " was photo-evap; "
<< theResults.size() << " results. " << G4endl;
}
G4ReactionProductVector * theReactionProductVector =
new G4ReactionProductVector();
@@ -396,12 +416,14 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
G4int theFragmentA, theFragmentZ;
//G4cout << "### ExcitationHandler provides " << theResults.size()
// << " evaporated products:" << G4endl;
if(fVerbose > 1) {
G4cout << "### ExcitationHandler provides " << theResults.size()
<< " evaporated products:" << G4endl;
}
kkmax = theResults.size();
for (kk=0; kk<kkmax; ++kk) {
frag = theResults[kk];
//G4cout << *frag << G4endl;
if(fVerbose > 1) { G4cout << *frag << G4endl; }
theFragmentA = frag->GetA_asInt();
theFragmentZ = frag->GetZ_asInt();
@@ -426,14 +448,19 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
// fragment
eexc = frag->GetExcitationEnergy();
if(eexc < minExcitation) { eexc = 0.0; }
theKindOfFragment =
theTableOfIons->GetIon(theFragmentZ,theFragmentA,eexc,noFloat,0);
/*
G4int idxf = frag->GetFloatingLevelNumber();
if(eexc < minExcitation) {
eexc = 0.0;
idxf = 0;
}
theKindOfFragment = theTableOfIons->GetIon(theFragmentZ,theFragmentA,eexc,
G4Ions::FloatLevelBase(idxf));
if(fVerbose > 2) {
G4cout << "### EXCH: Find ion Z= " << theFragmentZ << " A= " << theFragmentA
<< " Eexc(MeV)= " << eexc/MeV << " " << theKindOfFragment
<< G4endl;
*/
}
}
// fragment identified
if(theKindOfFragment) {
@@ -445,7 +472,8 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
// fragment not found out ground state is created
} else {
theKindOfFragment = theTableOfIons->GetIon(theFragmentZ,theFragmentA,0.0,noFloat,0);
theKindOfFragment =
theTableOfIons->GetIon(theFragmentZ,theFragmentA,0.0,noFloat,0);
if(theKindOfFragment) {
G4ThreeVector mom(0.0,0.0,0.0);
G4double ionmass = theKindOfFragment->GetPDGMass();
@@ -460,18 +488,17 @@ G4ExcitationHandler::BreakItUp(const G4Fragment & theInitialState)
theNew->SetTotalEnergy(etot);
theNew->SetFormationTime(frag->GetCreationTime());
theReactionProductVector->push_back(theNew);
/*
if(fVerbose > 2) {
G4cout << "### Find ion Z= " << theFragmentZ << " A= " << theFragmentA
<< " ground state, energy corrected " << theKindOfFragment << G4endl;
} else {
G4cout << "### Find ion Z= " << theFragmentZ
<< " A= " << theFragmentA << " failed " << G4endl;
*/
<< " ground state, energy corrected E(MeV)= " << etot << G4endl;
}
}
}
delete frag;
}
//G4cout << "@@@@@@@@@@ End G4Excitation Handler "<< G4endl;
if(fVerbose > 2) {
G4cout << "@@@@@@@@@@ End G4Excitation Handler "<< G4endl;
}
return theReactionProductVector;
}
@@ -61,10 +61,7 @@ public:
// spin - 2J, where J is the full angular momentum of the state
G4LevelManager(size_t ntrans,
const std::vector<G4float>& energies,
const std::vector<G4float>& lifetime,
const std::vector<G4float>& lifetimegamma,
const std::vector<G4int>& spin,
const std::vector<G4int>& meta,
const std::vector<const G4NucLevel*>& levels);
~G4LevelManager();
@@ -95,9 +92,13 @@ public:
inline G4float LifeTimeGamma(size_t i) const;
inline G4int SpinTwo(size_t i) const;
inline G4int SpinParity(size_t i) const;
inline G4int IsFloatingLevel(size_t i) const;
inline G4int Parity(size_t i) const;
inline G4int FloatingLevel(size_t i) const;
const G4String& FloatingType(size_t i) const;
@@ -113,12 +114,11 @@ private:
G4bool operator!=(const G4LevelManager &right) const = delete;
std::vector<G4float> fLevelEnergy;
std::vector<G4float> fLifeTime;
std::vector<G4float> fLifeTimeGamma;
std::vector<G4int> fSpin;
std::vector<G4int> fFloating;
std::vector<const G4NucLevel*> fLevels;
size_t nTransitions;
static const G4int nfloting = 13;
static G4String fFloatingLevels[nfloting];
@@ -185,7 +185,7 @@ inline G4float G4LevelManager::LifeTime(size_t i) const
#ifdef G4VERBOSE
if(i > nTransitions) { PrintError(i, "LifeTime"); }
#endif
return fLifeTime[i];
return (fLevels[i]) ? fLevels[i]->GetTimeGamma() : 0.0f;
}
inline G4float G4LevelManager::LifeTimeGamma(size_t i) const
@@ -193,23 +193,39 @@ inline G4float G4LevelManager::LifeTimeGamma(size_t i) const
#ifdef G4VERBOSE
if(i > nTransitions) { PrintError(i, "LifeTimeGamma"); }
#endif
return fLifeTimeGamma[i];
return (fLevels[i]) ? fLevels[i]->GetTimeGamma() : 0.0f;
}
inline G4int G4LevelManager::SpinTwo(size_t i) const
{
#ifdef G4VERBOSE
if(i > nTransitions) { PrintError(i, "SpinTwo"); }
#endif
return std::abs(fSpin[i]%100000 - 100);
}
inline G4int G4LevelManager::SpinParity(size_t i) const
{
#ifdef G4VERBOSE
if(i > nTransitions) { PrintError(i, "SpinParity"); }
if(i > nTransitions) { PrintError(i, "SpinTwo"); }
#endif
return fSpin[i];
return fSpin[i]%100000 - 100;
}
inline G4int G4LevelManager::IsFloatingLevel(size_t i) const
inline G4int G4LevelManager::Parity(size_t i) const
{
#ifdef G4VERBOSE
if(i > nTransitions) { PrintError(i, "Parity"); }
#endif
return (fSpin[i]%100000 - 100)/2;
}
inline G4int G4LevelManager::FloatingLevel(size_t i) const
{
#ifdef G4VERBOSE
if(i > nTransitions) { PrintError(i, "Floating"); }
#endif
return (0 != fFloating[i]);
return fSpin[i]/100000;
}
#endif
@@ -80,6 +80,8 @@ private:
G4bool ReadDataItem(std::istream& dataFile, G4double& x);
G4bool ReadDataItem(std::istream& dataFile, G4float& x);
G4bool ReadDataItem(std::istream& dataFile, G4int& x);
G4bool ReadDataItem(std::istream& dataFile, G4String& x);
@@ -97,18 +99,18 @@ private:
G4NuclearLevelData* fData;
G4DeexPrecoParameters* fParam;
G4double fMinProbability;
G4double fTimeFactor;
G4double fEnergy;
G4double fCurrEnergy;
G4double fTrEnergy;
G4double fProb;
G4double fTime;
G4double fSpin;
G4double fAlpha;
G4double fRatio;
G4double fICC[10];
G4float fTimeFactor;
G4float fTime;
G4float fProb;
G4float fSpin;
G4float fAlpha;
G4float fAlphaMax;
G4float fRatio;
G4float fICC[10];
static const G4int nfloting = 13;
static G4String fFloatingLevels[nfloting];
@@ -118,32 +120,27 @@ private:
G4String fPol;
static const G4int nbufmax = 20;
static const G4int nbuf1 = 14;
static const G4int nbuf2 = 8;
char buffer[nbufmax];
char buff1[nbuf1];
char buff2[nbuf2];
char bufp[2];
char bufp[3];
G4int fVerbose;
G4int fLevelMax;
G4int fTransMax;
G4float fNorm1;
G4float fNorm2;
std::vector<G4float> vEnergy;
std::vector<G4float> vTime;
std::vector<G4float> vTimeg;
std::vector<G4int> vSpin;
std::vector<G4int> vMeta;
std::vector<G4int> vIndexDB;
std::vector<const G4NucLevel*> vLevel;
std::vector<size_t> vIndex;
std::vector<G4int> vTrans;
std::vector<G4float> vRatio;
std::vector<G4float> vGammaCumProbability;
std::vector<G4float> vGammaECumProbability;
std::vector<G4float> vGammaProbability;
std::vector<G4float> vMpRatio;
std::vector<const std::vector<G4float>*> vShellProbability;
@@ -53,11 +53,9 @@ class G4NucLevel
{
public:
explicit G4NucLevel(size_t ntrans,
const std::vector<size_t>& idxTrans,
explicit G4NucLevel(size_t ntrans, G4float tgamma,
const std::vector<G4int>& vTrans,
const std::vector<G4float>& wLevelGamma,
const std::vector<G4float>& wLevelGammaE,
const std::vector<G4float>& wGamma,
const std::vector<G4float>& vRatio,
const std::vector<const std::vector<G4float>*>& wShell);
@@ -66,23 +64,25 @@ public:
inline size_t NumberOfTransitions() const;
inline G4bool IsXLevel() const;
inline size_t FinalExcitationIndex(size_t idx) const;
inline G4int TransitionType(size_t idx) const;
inline G4float GetTimeGamma() const;
inline G4float MixingRatio(size_t idx) const;
inline G4float GammaProbability(size_t idx) const;
inline G4float GammaCumProbability(size_t idx) const;
inline G4float MultipolarityRatio(size_t idx) const;
inline size_t SampleGammaTransition(G4double rndm) const;
inline size_t SampleGammaETransition(G4double rndm) const;
inline G4int SampleShell(size_t idx, G4double rndm) const;
inline size_t SampleShell(size_t idx, G4double rndm) const;
inline const std::vector<G4float>* ShellProbabilty(size_t idx) const;
private:
@@ -94,15 +94,15 @@ private:
G4bool operator!=(const G4NucLevel &right) const = delete;
G4bool operator<(const G4NucLevel &right) const = delete;
const G4NucLevel& operator=(const G4NucLevel &right) = delete;
size_t length;
G4float fTimeGamma;
std::vector<size_t> fFinalIndex;
std::vector<G4int> fTrans;
std::vector<G4float> fGammaCumProbability;
std::vector<G4float> fGammaECumProbability;
std::vector<G4float> fGammaProbability;
std::vector<G4float> fMpRatio;
std::vector<const std::vector<G4float>*> fShellProbability;
size_t length;
};
inline size_t G4NucLevel::NumberOfTransitions() const
@@ -110,17 +110,12 @@ inline size_t G4NucLevel::NumberOfTransitions() const
return length;
}
inline G4bool G4NucLevel::IsXLevel() const
{
return (1 == fTrans[0]);
}
inline size_t G4NucLevel::FinalExcitationIndex(size_t idx) const
{
#ifdef G4VERBOSE
if(idx >= length) { PrintError(idx, "FinalExcitationEnergy"); }
#endif
return fFinalIndex[idx];
return (size_t)(fTrans[idx]/10000);
}
inline G4int G4NucLevel::TransitionType(size_t idx) const
@@ -128,7 +123,12 @@ inline G4int G4NucLevel::TransitionType(size_t idx) const
#ifdef G4VERBOSE
if(idx >= length) { PrintError(idx, "TransitionType"); }
#endif
return fTrans[idx];
return fTrans[idx]%10000;
}
inline G4float G4NucLevel::GetTimeGamma() const
{
return fTimeGamma;
}
inline G4float G4NucLevel::MixingRatio(size_t idx) const
@@ -147,6 +147,14 @@ inline G4float G4NucLevel::GammaProbability(size_t idx) const
return fGammaProbability[idx];
}
inline G4float G4NucLevel::GammaCumProbability(size_t idx) const
{
#ifdef G4VERBOSE
if(idx >= length) { PrintError(idx, "GammaCumProbability"); }
#endif
return fGammaCumProbability[idx];
}
inline G4float G4NucLevel::MultipolarityRatio(size_t idx) const
{
#ifdef G4VERBOSE
@@ -165,31 +173,30 @@ inline size_t G4NucLevel::SampleGammaTransition(G4double rndm) const
return idx;
}
inline size_t G4NucLevel::SampleGammaETransition(G4double rndm) const
{
G4float x = (G4float)rndm;
size_t idx = 0;
for(; idx<length; ++idx) {
if(x <= fGammaECumProbability[idx]) { break; }
}
return idx;
}
inline size_t G4NucLevel::SampleShell(size_t idx, G4double rndm) const
inline G4int G4NucLevel::SampleShell(size_t idx, G4double rndm) const
{
#ifdef G4VERBOSE
if(idx >= length) { PrintError(idx, "SampleShell"); }
#endif
const std::vector<G4float>* prob = fShellProbability[idx];
size_t i = 0;
G4int i(-1);
if(prob) {
size_t nn = prob->size();
G4int nn = prob->size();
G4float x = (G4float)rndm;
for(; i<nn; ++i) { if(x <= (*prob)[i]) { break; } }
for(i=0; i<nn; ++i) { if(x <= (*prob)[i]) { break; } }
}
return i;
}
inline const std::vector<G4float>*
G4NucLevel::ShellProbabilty(size_t idx) const
{
#ifdef G4VERBOSE
if(idx >= length) { PrintError(idx, "ShellProbability"); }
#endif
return fShellProbability[idx];
}
#endif
@@ -57,8 +57,8 @@ void G4DeexPrecoParameters::SetDefaults()
fFermiEnergy = 35.0*CLHEP::MeV;
fPrecoLowEnergy = 0.1*CLHEP::MeV;
fPhenoFactor = 1.0;
fMinExcitation = 0.1*CLHEP::keV;
fMaxLifeTime = 0.01*CLHEP::second;
fMinExcitation = 10*CLHEP::eV;
fMaxLifeTime = 1.0*CLHEP::microsecond;
fMinExPerNucleounForMF = 100*CLHEP::GeV;
fMinZForPreco = 3;
fMinAForPreco = 5;
@@ -69,8 +69,8 @@ void G4DeexPrecoParameters::SetDefaults()
fUseCEM = true;
fUseGNASH = false;
fUseHETC = false;
fUseAngularGen = true;
fUseLongFiles = false;
fUseAngularGen = false;
fUseLongFiles = true;
fCorrelatedGamma = false;
fStoreAllLevels = false;
fDeexChannelType = fEvaporation;
@@ -231,6 +231,8 @@ std::ostream& G4DeexPrecoParameters::StreamInfo(std::ostream& os) const
<< fLevelDensity*CLHEP::MeV << "\n";
os << "Time limit for long lived isomeres (ns) "
<< fMaxLifeTime/CLHEP::ns << "\n";
os << "Use new data files " << fUseLongFiles << "\n";
os << "Use complete data files " << fStoreAllLevels << "\n";
os << "Correlated gamma emission flag " << fCorrelatedGamma << "\n";
os << "=======================================================================" << "\n";
os.precision(prec);
@@ -48,31 +48,22 @@ G4String G4LevelManager::fFloatingLevels[] = {
G4LevelManager::G4LevelManager(size_t ntrans,
const std::vector<G4float>& energies,
const std::vector<G4float>& lifetime,
const std::vector<G4float>& lifetimegamma,
const std::vector<G4int>& spin,
const std::vector<G4int>& fll,
const std::vector<const G4NucLevel*>& levels)
: nTransitions(0)
{
if(0 < ntrans) {
nTransitions = ntrans - 1;
fLevelEnergy.reserve(ntrans);
fLifeTime.reserve(ntrans);
fLifeTimeGamma.reserve(ntrans);
fSpin.reserve(ntrans);
fFloating.reserve(ntrans);
fLevels.reserve(ntrans);
for(size_t i=0; i<ntrans; ++i) {
fLevelEnergy.push_back(energies[i]);
fLifeTime.push_back(lifetime[i]);
fLifeTimeGamma.push_back(lifetimegamma[i]);
fSpin.push_back(spin[i]);
fLevels.push_back(levels[i]);
fFloating.push_back(fll[i]);
}
//G4cout << "New G4LevelManager N= " << nTransitions << " " << fLevelEnergy.size()
// << " <" << this << ">" << G4endl;
//G4cout << "New G4LevelManager N= " << nTransitions << " "
//<< fLevelEnergy.size() << " <" << this << ">" << G4endl;
}
}
@@ -115,7 +106,8 @@ const G4String& G4LevelManager::FloatingType(size_t i) const
#ifdef G4VERBOSE
if(i > nTransitions) { PrintError(i, "Meta"); }
#endif
return fFloatingLevels[fFloating[i]];
return fFloatingLevels[fSpin[i]/100000];
// return fFloatingLevels[fFloating[i]];
}
#ifdef G4VERBOSE
@@ -54,10 +54,10 @@ G4String G4LevelReader::fFloatingLevels[] = {
"-", "+X", "+Y", "+Z", "+U", "+V", "+W", "+R", "+S", "+T", "+A", "+B", "+C"};
G4LevelReader::G4LevelReader(G4NuclearLevelData* ptr)
: fData(ptr),fMinProbability(1.e-8),fVerbose(0),fLevelMax(632),fTransMax(30)
: fData(ptr),fAlphaMax(9.0f+9),fVerbose(0),fLevelMax(632),fTransMax(80)
{
fParam = fData->GetParameters();
fTimeFactor = CLHEP::second/G4Pow::GetInstance()->logZ(2);
fTimeFactor = (G4float)(CLHEP::second/G4Pow::GetInstance()->logZ(2));
char* directory = getenv("G4LEVELGAMMADATA");
if(directory) {
fDirectory = directory;
@@ -68,31 +68,25 @@ G4LevelReader::G4LevelReader(G4NuclearLevelData* ptr)
}
fFile = fDirectory + "/z100.a200";
fPol = " ";
for(G4int i=0; i<10; ++i) { fICC[i] = 0.0; }
for(G4int i=0; i<10; ++i) { fICC[i] = 0.0f; }
for(G4int i=0; i<nbufmax; ++i) { buffer[i] = ' '; }
for(G4int i=0; i<nbuf1; ++i) { buff1[i] = ' '; }
for(G4int i=0; i<nbuf2; ++i) { buff2[i] = ' '; }
bufp[0] = bufp[1] = ' ';
bufp[0] = bufp[1] = bufp[2] = ' ';
fEnergy = fCurrEnergy = fTrEnergy = fProb = fTime =
fSpin = fAlpha = fRatio = 0.0;
fNorm1 = fNorm2 = 0.0f;
fEnergy = fCurrEnergy = fTrEnergy = 0.0;
fTime = fProb = fSpin = fAlpha = fRatio = fNorm1 = 0.0f;
vIndex.resize(fTransMax,0);
vTrans.resize(fTransMax,0);
vRatio.resize(fTransMax,0.0f);
vGammaCumProbability.resize(fTransMax,0.0f);
vGammaECumProbability.resize(fTransMax,0.0f);
vGammaProbability.resize(fTransMax,0.0f);
vShellProbability.resize(fTransMax,nullptr);
vMpRatio.resize(fTransMax,0.0f);
vEnergy.resize(fLevelMax,0.0f);
vTime.resize(fLevelMax,0.0f);
vTimeg.resize(fLevelMax,0.0f);
vSpin.resize(fLevelMax,0);
vLevel.resize(fLevelMax,nullptr);
vMeta.resize(fLevelMax,0);
vIndexDB.resize(fLevelMax,-1);
}
const G4LevelManager*
@@ -109,12 +103,15 @@ const G4LevelManager*
G4LevelReader::MakeLevelManager(G4int Z, G4int A, const G4String& filename)
{
vEnergy.resize(1,0.0f);
vTime.resize(1,FLT_MAX);
vTimeg.resize(1,FLT_MAX);
vSpin.resize(1,0);
vMeta.resize(1,0);
vLevel.resize(1,nullptr);
vTrans.clear();
vGammaCumProbability.clear();
vGammaProbability.clear();
vShellProbability.clear();
vMpRatio.clear();
std::ifstream infile(filename, std::ios::in);
// file is not opened
@@ -127,16 +124,18 @@ G4LevelReader::MakeLevelManager(G4int Z, G4int A, const G4String& filename)
} else {
G4bool allLevels = fParam->StoreAllLevels();
if (fVerbose > 0) {
G4cout << "G4LevelReader: open file for Z= "
<< Z << " A= " << A
<< " <" << filename << ">" << G4endl;
}
// read line by line
G4bool end = false;
G4bool end = false;
G4bool next = true;
G4int nline = -1;
G4String xl = "- ";
G4int spin;
G4int index(0);
fCurrEnergy = DBL_MAX;
do {
fPol = " ";
@@ -148,7 +147,11 @@ G4LevelReader::MakeLevelManager(G4int Z, G4int A, const G4String& filename)
ReadDataItem(infile,fTime) &&
ReadDataItem(infile,fSpin) &&
ReadDataItem(infile,fAlpha));
/*
G4cout << fEnergy << " " << fTrEnergy << " " << fProb << " "
<< fPol << " " << fTime << " " << fSpin << " " << fAlpha
<< " " << isOK << " " << fVerbose << G4endl;
*/
fEnergy *= CLHEP::keV;
fTrEnergy *= CLHEP::keV;
@@ -177,82 +180,74 @@ G4LevelReader::MakeLevelManager(G4int Z, G4int A, const G4String& filename)
if(fVerbose > 1) {
G4cout << "Reader: new level E= " << fEnergy
<< " Ntransitions= " << nn+1 << " fNorm1= " << fNorm1
<< " fNorm2= " << fNorm2 << G4endl;
<< G4endl;
}
if(fNorm1 > 0.0f) {
if(fNorm1 > 0.0f) {
fNorm1 = 1.0f/fNorm1;
vTimeg.push_back(((G4float)(fTime*fTimeFactor))*fNorm2*fNorm1);
fNorm2 = 1.0f/fNorm2;
for(size_t i=0; i<nn; ++i) {
vGammaCumProbability[i] *= fNorm1;
vGammaECumProbability[i] *= fNorm2;
if(fVerbose > 2) {
G4cout << "Probabilities[" << i
<< "]= " << vGammaCumProbability[i]
<< " " << vGammaECumProbability[i]
<< " idxTrans= " << vIndex[i]
<< " idxTrans= " << index
<< G4endl;
}
}
vGammaCumProbability[nn] = 1.0f;
vGammaECumProbability[nn] = 1.0f;
if(fVerbose > 2) {
G4cout << "Probabilities[" << nn << "]= " << vGammaCumProbability[nn]
<< " " << vGammaECumProbability[nn]
<< " IdxTrans= " << vIndex[nn]
G4cout << "Probabilities[" << nn << "]= "
<< vGammaCumProbability[nn]
<< " IdxTrans= " << index
<< G4endl;
}
vMeta.push_back(0);
vLevel.push_back(new G4NucLevel(vTrans.size(), fTime,
vTrans,
vGammaCumProbability,
vGammaProbability,
vMpRatio,
vShellProbability));
//case of X-level
} else {
vMeta.push_back(1);
vTimeg.push_back(0.0f);
vGammaCumProbability[0] = 0.0f;
vGammaECumProbability[0] = 0.0f;
spin += 100000;
fTime = 0.0f;
vLevel.push_back(nullptr);
}
vLevel.push_back(new G4NucLevel(vIndex.size(),
vIndex,
vTrans,
vGammaCumProbability,
vGammaECumProbability,
vGammaProbability,
vMpRatio,
vShellProbability));
vIndex.clear();
vTrans.clear();
vGammaCumProbability.clear();
vGammaECumProbability.clear();
vGammaProbability.clear();
vShellProbability.clear();
vMpRatio.clear();
} else {
vLevel.push_back(nullptr);
}
vSpin.push_back(spin);
vTrans.clear();
vGammaCumProbability.clear();
vGammaProbability.clear();
vShellProbability.clear();
vMpRatio.clear();
if(!end) { next = true; }
}
fCurrEnergy = fEnergy;
G4float ener = (G4float)fEnergy;
// begin nuclear level data
if(next) {
if(fVerbose > 2) {
G4cout << "== Reader: begin of new level E= " << fEnergy << G4endl;
if(fVerbose > 1) {
G4cout << "== Reader: begin of new level E= " << fEnergy
<< " Prob= " << fProb << G4endl;
}
// protection for bad level energy
size_t nn = vEnergy.size();
G4float ener = (G4float)fEnergy;
if(0 < nn && vEnergy[nn-1] > ener) { ener = vEnergy[nn-1]; }
if(0 < nn && vEnergy[nn-1] > ener) {
ener = vEnergy[nn-1];
}
vEnergy.push_back(ener);
vTime.push_back((G4float)(fTime*fTimeFactor));
if(fSpin > 20.0) { fSpin = 0.0; }
fProb = std::max(fProb, fMinProbability);
vSpin.push_back((G4int)(fSpin+fSpin));
fCurrEnergy = fEnergy;
fTime *= fTimeFactor;
if(fSpin > 20.0f) { fSpin = 0.0; }
spin = (G4int)(fSpin+fSpin);
fNorm1 = 0.0f;
fNorm2 = 0.0f;
next = false;
}
// continue filling level data
if(!end) {
if(fProb > 0.0) {
if(fProb > 0.0f) {
// by default transition to a ground state
G4float efinal = std::max((G4float)(fEnergy - fTrEnergy),0.0f);
G4float efinal = (G4float)std::max(fEnergy - fTrEnergy,0.0);
G4float elevel = 0.0f;
size_t idxLevel = 0;
G4int tnum = 0;
@@ -260,7 +255,7 @@ G4LevelReader::MakeLevelManager(G4int Z, G4int A, const G4String& filename)
size_t nn = vEnergy.size();
static const G4float x_energy = (G4float)(0.1*CLHEP::eV);
if(1 < nn) {
G4float ediffMin = fEnergy;
G4float ediffMin = (G4float)fEnergy;
for(size_t i=0; i<nn-1; ++i) {
G4float ediff = std::abs(efinal - vEnergy[i]);
/*
@@ -278,16 +273,13 @@ G4LevelReader::MakeLevelManager(G4int Z, G4int A, const G4String& filename)
}
if(std::abs(vEnergy[nn-1] - elevel) < x_energy) { tnum = 1; }
}
G4double x = 1.0 + fAlpha;
fNorm1 += (G4float)fProb;
fNorm2 += (G4float)(fProb*x);
vIndex.push_back(idxLevel);
G4float x = 1.0f + fAlpha;
fNorm1 += x*fProb;
vGammaCumProbability.push_back(fNorm1);
vGammaECumProbability.push_back(fNorm2);
vGammaProbability.push_back((G4float)(1.0/x));
vGammaProbability.push_back(1.0f/x);
vMpRatio.push_back(0.0f);
vTrans.push_back(tnum);
if(fAlpha > 0.0) {
vTrans.push_back(tnum + idxLevel*10000);
if(allLevels && fAlpha > 0.0f) {
vShellProbability.push_back(NormalizedICCProbability(Z));
} else {
vShellProbability.push_back(nullptr);
@@ -306,14 +298,14 @@ G4LevelReader::MakeLevelManager(G4int Z, G4int A, const G4String& filename)
G4LevelManager* man = nullptr;
if(vEnergy.size() >= 2) {
man = new G4LevelManager(vEnergy.size(),vEnergy,vTime,vTimeg,vSpin,vMeta,vLevel);
man = new G4LevelManager(vEnergy.size(),vEnergy,vSpin,vLevel);
if(fVerbose > 0) {
G4cout << "=== Reader: new manager for Z= " << Z << " A= " << A
<< " Nlevels= " << vEnergy.size() << " E[0]= "
<< vEnergy[0]/CLHEP::MeV << " MeV Emax= "
<< man->MaxLevelEnergy()/CLHEP::MeV << " MeV "
<< " S: " << vEnergy.size() << " " << vTime.size()
<< " " << vTimeg.size() << " " << vSpin.size() << " " << vLevel.size()
<< " S: " << vEnergy.size()
<< " " << vSpin.size() << " " << vLevel.size()
<< G4endl;
}
}
@@ -338,6 +330,18 @@ G4bool G4LevelReader::ReadDataItem(std::istream& dataFile, G4double& x)
return okay;
}
G4bool G4LevelReader::ReadDataItem(std::istream& dataFile, G4float& x)
{
x = 0.0f;
for(G4int i=0; i<nbuf1; ++i) { buff1[i] = ' '; }
G4bool okay = true;
dataFile >> buff1;
if(dataFile.fail()) { okay = false; }
else { x = atof(buff1); }
return okay;
}
G4bool G4LevelReader::ReadDataItem(std::istream& dataFile, G4int& ix)
{
ix = 0;
@@ -353,9 +357,11 @@ G4bool G4LevelReader::ReadDataItem(std::istream& dataFile, G4int& ix)
G4bool G4LevelReader::ReadDataItem(std::istream& dataFile, G4String& x)
{
G4bool okay = true;
bufp[0] = bufp[1] = ' ';
dataFile >> bufp;
if(dataFile.fail()) { okay = false; }
else { x = G4String(bufp, 2); }
return okay;
}
@@ -385,22 +391,25 @@ const std::vector<G4float>* G4LevelReader::NormalizedICCProbability(G4int Z)
M = 4;
N = 1;
}
if(LL < 3) { for(G4int i=LL+1; i<=4; ++i) { fICC[i] = 0.0; } }
if(M < 5) { for(G4int i=M+4; i<=8; ++i) { fICC[i] = 0.0; } }
if(N < 1) { fICC[9] = 0.0; }
if(LL < 3) { for(G4int i=LL+1; i<=4; ++i) { fICC[i] = 0.0f; } }
if(M < 5) { for(G4int i=M+4; i<=8; ++i) { fICC[i] = 0.0f; } }
if(N < 1) { fICC[9] = 0.0f; }
}
G4float norm = 0.0;
G4float norm = 0.0f;
for(G4int i=0; i<10; ++i) {
norm += fICC[i];
fICC[i] = norm;
}
if(norm == 0.0f && fAlpha > fAlphaMax) {
fICC[9] = norm = 1.0f;
}
if(norm > 0.0f) {
norm = 1.0f/norm;
vec = new std::vector<G4float>;
G4float x;
for(G4int i=0; i<10; ++i) {
x = (G4float)(fICC[i]*norm);
if(x > 0.995f) {
x = fICC[i]*norm;
if(x > 0.995f || 9 == i) {
vec->push_back(1.0f);
break;
}
@@ -429,10 +438,12 @@ G4LevelReader::CreateLevelManagerNEW(G4int Z, G4int A)
// file is not opened
if (!infile.is_open()) {
if (fVerbose > 0) {
G4cout << " G4LevelReader: fail open file for Z= "
<< Z << " A= " << A
<< " <" << fFile << ">" << G4endl;
if(fVerbose > 0) {
G4ExceptionDescription ed;
ed << " for Z= " << Z << " A= " << A
<< " <" << fFile << "> is not opened!";
G4Exception("G4LevelReader::CreateLevelManagerNEW(..)","had014",
JustWarning, ed, "");
}
return nullptr;
}
@@ -452,11 +463,11 @@ G4LevelReader::MakeLevelManagerNEW(G4int Z, G4int A,
// file is not opened
if (!infile.is_open()) {
if (fVerbose > 0) {
G4cout << " G4LevelReader: fail open file for Z= "
<< Z << " A= " << A
<< " <" << filename << ">" << G4endl;
}
G4ExceptionDescription ed;
ed << " for Z= " << Z << " A= " << A
<< " data file <" << filename << "> is not opened!";
G4Exception("G4LevelReader::MakeLevelManagerNEW(..)","had014",
JustWarning, ed, "Check G4LEVELGAMMADATA");
return nullptr;
}
if (fVerbose > 0) {
@@ -472,7 +483,6 @@ G4LevelReader::LevelManager(G4int Z, G4int A, G4int nlev,
std::ifstream& infile)
{
G4bool allLevels = fParam->StoreAllLevels();
G4float emax = fData->GetMaxLevelEnergy(Z, A);
static const G4double fkev = CLHEP::keV;
G4int nlevels = (0 == nlev) ? fLevelMax : nlev;
@@ -484,72 +494,69 @@ G4LevelReader::LevelManager(G4int Z, G4int A, G4int nlev,
if(nlevels > fLevelMax) {
fLevelMax = nlevels;
vEnergy.resize(fLevelMax,0.0f);
vTime.resize(fLevelMax,0.0f);
vTimeg.resize(fLevelMax,0.0f);
vSpin.resize(fLevelMax,0);
vLevel.resize(fLevelMax,0);
vMeta.resize(fLevelMax,0);
vIndexDB.resize(fLevelMax,-1);
vLevel.resize(fLevelMax,nullptr);
}
G4int ntrans(0), i(0), i1, i2, i3, j, k;
G4int ntrans(0), i1, i, k;
G4int i2; // Level number at which transition ends
G4int tnum; // Multipolarity index
G4String xf(" ");
G4float x, x1;
G4float x, ener, tener;
for(G4int ii=0; ii<nlevels; ++ii) {
infile >> i1 >> xf;
for(i=0; i<nlevels; ++i) {
infile >> i1 >> xf; // Level number and floating level
//G4cout << "New line: i1= " << i1 << " xf= <" << xf << "> " << G4endl;
if(infile.eof()) {
if(fVerbose > 1) {
G4cout << "### End of file Z= " << Z << " A= " << A
<< " Nlevels= " << ii << G4endl;
<< " Nlevels= " << i << G4endl;
}
break;
}
if(!(ReadDataItem(infile,fEnergy) &&
if(i1 != i) {
G4ExceptionDescription ed;
ed << " G4LevelReader: wrong data file for Z= " << Z << " A= " << A
<< " level #" << i << " has index " << i1 << G4endl;
G4Exception("G4LevelReader::LevelManager(..)","had014",
FatalException, ed, "Check G4LEVELGAMMADATA");
}
if(!(ReadDataItem(infile,ener) &&
ReadDataItem(infile,fTime) &&
ReadDataItem(infile,fSpin) &&
ReadDataItem(infile,ntrans))) {
if(fVerbose > 1) {
G4cout << "### End of file Z= " << Z << " A= " << A
<< " Nlevels= " << ii << G4endl;
<< " Nlevels= " << i << G4endl;
}
break;
}
fTime = std::max(fTime, 0.0);
fEnergy *= fkev;
fTime = std::max(fTime, 0.0f);
ener *= fkev;
for(k=0; k<nfloting; ++k) {
if(xf == fFloatingLevels[k]) {
break;
}
}
// if a previous level has not transitions it may be ignored
if(0 < ii) {
// do not store level without transitions
if(!allLevels && 0 == k && 0 == ntrans) { continue; }
if(0 < i) {
// protection
if(fEnergy < vEnergy[i-1]) {
G4cout << "### G4LevelReader: broken level " << ii
<< " E(MeV)= " << fEnergy << " < " << vEnergy[i-1]
if(ener < vEnergy[i-1]) {
G4cout << "### G4LevelReader: broken level " << i
<< " E(MeV)= " << ener << " < " << vEnergy[i-1]
<< " for isotope Z= " << Z << " A= "
<< A << " level energy increased" << G4endl;
fEnergy = vEnergy[i-1];
ener = vEnergy[i-1];
}
// upper limit
if(fEnergy > emax) { break; }
}
vEnergy[i] = (G4float)fEnergy;
vTime[i] = (G4float)(fTime*fTimeFactor);
vTimeg[i] = vTime[i];
if(fSpin > 20.0) { fSpin = 0.0; }
vSpin[i] = (G4int)(fSpin + fSpin);
vMeta[i] = k;
vIndexDB[ii] = i;
vEnergy[i] = ener;
fTime *= fTimeFactor;
if(fSpin > 20.0f) { fSpin = 0.0f; }
vSpin[i] = (G4int)(100 + fSpin + fSpin) + k*100000;
if(fVerbose > 1) {
G4cout << " Level #" << i1 << " E(MeV)= " << fEnergy/CLHEP::MeV
G4cout << " Level #" << i1 << " E(MeV)= " << ener/CLHEP::MeV
<< " LTime(s)= " << fTime << " 2S= " << vSpin[i]
<< " meta= " << vMeta[i] << " idx= " << i << " ii= " << ii
<< " meta= " << vSpin[i]/100000 << " idx= " << i
<< " ntr= " << ntrans << G4endl;
}
vLevel[i] = nullptr;
@@ -558,26 +565,23 @@ G4LevelReader::LevelManager(G4int Z, G4int A, G4int nlev,
// there are transitions
if(ntrans > fTransMax) {
fTransMax = ntrans;
vIndex.resize(fTransMax);
vTrans.resize(fTransMax);
vRatio.resize(fTransMax);
vGammaCumProbability.resize(fTransMax);
vGammaECumProbability.resize(fTransMax);
vGammaProbability.resize(fTransMax);
vShellProbability.resize(fTransMax);
vMpRatio.resize(fTransMax);
}
fNorm1 = fNorm2 = 0.0f;
j = 0;
for(G4int jj=0; jj<ntrans; ++jj) {
fNorm1 = 0.0f;
for(G4int j=0; j<ntrans; ++j) {
if(!(ReadDataItem(infile,i2) &&
ReadDataItem(infile,fTrEnergy) &&
ReadDataItem(infile,tener) &&
ReadDataItem(infile,fProb) &&
ReadDataItem(infile,vTrans[j]) &&
ReadDataItem(infile,fRatio) &&
ReadDataItem(infile,tnum) &&
ReadDataItem(infile,vRatio[j]) &&
ReadDataItem(infile,fAlpha))) {
//infile >>i2 >> fTrEnergy >> fProb >> vTrans[j] >> fRatio >> fAlpha;
//infile >>i2 >> tener >> fProb >> vTrans[j] >> fRatio >> fAlpha;
//if(infile.fail()) {
if(fVerbose > 0) {
G4cout << "### Fail to read transition j= " << j
@@ -585,38 +589,36 @@ G4LevelReader::LevelManager(G4int Z, G4int A, G4int nlev,
}
break;
}
if(i2 >= ii) {
if(i2 >= i) {
G4cout << "### G4LevelReader: broken transition " << j
<< " from level " << ii << " to " << i2
<< " for isotope Z= " << Z << " A= "
<< A << " - use ground level" << G4endl;
<< " from level " << i << " to " << i2
<< " for isotope Z= " << Z << " A= "
<< A << " - use ground level" << G4endl;
i2 = 0;
}
i3 = vIndexDB[std::abs(i2)];
if(i3 >= 0) {
vIndex[j] = i3;
x = 1.0f + std::max((G4float)fAlpha,0.0f);
x1= (G4float)fProb;
fNorm1 += x1;
fNorm2 += x*x1;
vTrans[j] = i2*10000 + tnum;
if(fAlpha < fAlphaMax) {
x = 1.0f + fAlpha;
fNorm1 += x*fProb;
vGammaCumProbability[j] = fNorm1;
vGammaECumProbability[j]= fNorm2;
vGammaProbability[j] = 1.0f/x;
vRatio[j] = (G4float)fRatio;
vShellProbability[j] = nullptr;
if(fVerbose > 1) {
fTrEnergy *= fkev;
G4int prec = G4cout.precision(4);
G4cout << "### Transition #" << j << " to level " << vIndex[j]
<< " i2= " << i2 << " Etrans(MeV)= " << fTrEnergy
<< " fProb= " << fProb << " MultiP= " << vTrans[j]
<< " fMpRatio= " << fRatio << " fAlpha= " << fAlpha
<< G4endl;
G4cout.precision(prec);
}
} else {
// only internal conversion case - no gamma conversion at all
fNorm1 += fProb;
vGammaCumProbability[j] = fNorm1;
vGammaProbability[j] = 0.0f;
}
vShellProbability[j] = nullptr;
if(fVerbose > 1) {
G4int prec = G4cout.precision(4);
G4cout << "### Transition #" << j << " to level " << i2
<< " i2= " << i2 << " Etrans(MeV)= " << tener*fkev
<< " fProb= " << fProb << " MultiP= " << tnum
<< " fMpRatio= " << fRatio << " fAlpha= " << fAlpha
<< G4endl;
G4cout.precision(prec);
}
if(fAlpha > 0.0) {
if(fAlpha > 0.0f) {
for(k=0; k<10; ++k) {
//infile >> fICC[k];
if(!ReadDataItem(infile,fICC[k])) {
@@ -629,66 +631,55 @@ G4LevelReader::LevelManager(G4int Z, G4int A, G4int nlev,
break;
}
}
if(i3 >= 0) {
if(allLevels) {
vShellProbability[j] = NormalizedICCProbability(Z);
if(!vShellProbability[j]) { vGammaProbability[j] = 1.0f; }
}
}
if(i3 >= 0) { ++j; }
}
if(j > 0) {
if(0.0f < fNorm1) {
fNorm1 = 1.0f/fNorm1;
vTimeg[i] *= fNorm2*fNorm1;
fNorm2 = 1.0f/fNorm2;
}
G4int nt = j - 1;
for(k=0; k<nt; ++k) {
vGammaCumProbability[k] *= fNorm1;
vGammaECumProbability[k] *= fNorm2;
if(fVerbose > 2) {
G4cout << "Probabilities[" << k
<< "]= " << vGammaCumProbability[k]
<< " " << vGammaECumProbability[k]
<< " idxTrans= " << vIndex[k]
<< G4endl;
}
}
vGammaCumProbability[nt] = 1.0f;
vGammaECumProbability[nt] = 1.0f;
if(0.0f < fNorm1) { fNorm1 = 1.0f/fNorm1; }
G4int nt = ntrans - 1;
for(k=0; k<nt; ++k) {
vGammaCumProbability[k] *= fNorm1;
if(fVerbose > 2) {
G4cout << "Probabilities[" << nt << "]= "
<< vGammaCumProbability[nt]
<< " " << vGammaECumProbability[nt]
<< " IdxTrans= " << vIndex[nt]
G4cout << "Probabilities[" << k
<< "]= " << vGammaCumProbability[k]
<< " " << vGammaProbability[k]
<< " idxTrans= " << vTrans[k]/10000
<< G4endl;
}
vLevel[i] = new G4NucLevel((size_t)j,
vIndex,
vTrans,
vGammaCumProbability,
vGammaECumProbability,
vGammaProbability,
vMpRatio,
vShellProbability);
}
vGammaCumProbability[nt] = 1.0f;
if(fVerbose > 2) {
G4cout << "Probabilities[" << nt << "]= "
<< vGammaCumProbability[nt]
<< " " << vGammaProbability[nt]
<< " IdxTrans= " << vTrans[nt]/10000
<< G4endl;
}
if(fVerbose > 1) {
G4cout << " New G4NucLevel: Ntrans= " << ntrans
<< " Time(ns)= " << fTime << G4endl;
}
vLevel[i] = new G4NucLevel((size_t)ntrans, fTime,
vTrans,
vGammaCumProbability,
vGammaProbability,
vMpRatio,
vShellProbability);
}
++i;
}
G4LevelManager* lman = nullptr;
if(1 < i) {
lman = new G4LevelManager((size_t)i,vEnergy,vTime,vTimeg,
vSpin,vMeta,vLevel);
lman = new G4LevelManager((size_t)i,vEnergy,vSpin,vLevel);
if(fVerbose > 0) {
G4cout << "=== Reader: new manager for Z= " << Z << " A= " << A
<< " Nlevels= " << i << " E[0]= "
<< vEnergy[0]/CLHEP::MeV << " MeV Emax= "
<< vEnergy[0]/CLHEP::MeV << " MeV E1= "
<< vEnergy[i-1]/CLHEP::MeV << " MeV "
<< G4endl;
}
}
for(G4int ii=0; ii<nlevels; ++ii) {
vIndexDB[ii] = -1;
}
return lman;
}
@@ -43,29 +43,23 @@
#include "G4NucLevel.hh"
#include "G4HadronicException.hh"
G4NucLevel::G4NucLevel(size_t ntrans,
const std::vector<size_t>& idxTrans,
G4NucLevel::G4NucLevel(size_t ntrans, G4float tgamma,
const std::vector<G4int>& vTrans,
const std::vector<G4float>& wLevelGamma,
const std::vector<G4float>& wLevelGammaE,
const std::vector<G4float>& wGamma,
const std::vector<G4float>& vRatio,
const std::vector<const std::vector<G4float>*>& wShell)
: length(ntrans)
: length(ntrans), fTimeGamma(tgamma)
{
if(0 < length) {
fFinalIndex.reserve(length);
fTrans.reserve(length);
fGammaCumProbability.reserve(length);
fGammaECumProbability.reserve(length);
fGammaProbability.reserve(length);
fMpRatio.reserve(length);
fShellProbability.reserve(length);
for(size_t i=0; i<length; ++i) {
fFinalIndex.push_back(idxTrans[i]);
fTrans.push_back(vTrans[i]);
fGammaCumProbability.push_back(wLevelGamma[i]);
fGammaECumProbability.push_back(wLevelGammaE[i]);
fGammaProbability.push_back(wGamma[i]);
fMpRatio.push_back(vRatio[i]);
fShellProbability.push_back(wShell[i]);
@@ -85,10 +79,9 @@ void G4NucLevel::PrintError(size_t idx, const G4String& ss) const
{
G4cout << "G4NucLevel::PrintError: length= " << length << G4endl;
for(size_t i=0; i<length; ++i) {
G4cout << i << ". " << fFinalIndex[i] << " " << fTrans[i]
<< fGammaCumProbability[i] << " "
<< fGammaECumProbability[i] << " "
<< fGammaProbability[i] << " "
G4cout << i << ". " /*<< fFinalIndex[i] << " "*/ << fTrans[i]
<< fGammaCumProbability[i] << " " << fTimeGamma << " "
<< fGammaProbability[i] << " "
<< fMpRatio[i] << G4endl;
}
G4String sss = "G4NucLevel::"+ss+"()";
@@ -64,16 +64,17 @@ public:
G4int JP1,
G4int JP2,
G4int MP,
size_t shell,
G4int shell,
G4bool isDiscrete,
G4bool isGamma,
G4bool isLongLived);
G4bool isGamma);
virtual void SampleDirection(G4Fragment* nuc, G4double ratio,
G4int twoJ1, G4int twoJ2, G4int mp);
inline void SetPolarizationFlag(G4bool val) { polarFlag = val; };
inline void SetVerbose(G4int val) { fVerbose = val; fPolTrans.SetVerbose(val); };
private:
G4GammaTransition(const G4GammaTransition &right) = delete;
@@ -87,12 +88,8 @@ protected:
G4ThreeVector fDirection;
G4PolarizationTransition fPolTrans;
G4int fVerbose;
};
#endif
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4PhotonEvaporation.hh 101756 2016-11-24 14:27:39Z gcosmo $
// $Id: G4PhotonEvaporation.hh 102590 2017-02-09 10:13:30Z gcosmo $
//
// -------------------------------------------------------------------
//
@@ -130,7 +130,6 @@ private:
G4double fExcEnergy;
G4double fProbability;
G4double fStep;
G4double fTimeLimit;
G4double fMaxLifeTime;
G4double LevelDensity;
@@ -84,6 +84,8 @@ class G4PolarizationTransition
void DumpTransitionData(const POLAR& pol) const;
inline void SetVerbose(G4int val) { fVerbose = val; };
private:
G4PolarizationTransition(const G4PolarizationTransition &right) = delete;
@@ -91,6 +93,7 @@ class G4PolarizationTransition
inline G4double LnFactorial(int k) const { return G4Pow::GetInstance()->logfactorial(k); }
G4int fVerbose;
G4int fTwoJ1, fTwoJ2;
G4int fLbar, fL;
G4double fDelta;
@@ -47,7 +47,7 @@
#include "G4PhysicalConstants.hh"
G4GammaTransition::G4GammaTransition()
: polarFlag(false), fDirection(0.,0.,0.)
: polarFlag(false), fDirection(0.,0.,0.), fVerbose(0)
{}
G4GammaTransition::~G4GammaTransition()
@@ -60,27 +60,30 @@ G4GammaTransition::SampleTransition(G4Fragment* nucleus,
G4int JP1,
G4int JP2,
G4int MP,
size_t shell,
G4int shell,
G4bool isDiscrete,
G4bool isGamma,
G4bool isLongLived)
G4bool isGamma)
{
G4Fragment* result = nullptr;
G4double bond_energy = 0.;
G4double bond_energy = 0.0;
if (!isGamma) {
G4int Z = nucleus->GetZ_asInt();
if(Z <= 100) {
G4int idx = (G4int)shell;
idx = std::min(idx, G4AtomicShells::GetNumberOfShells(Z)-1);
bond_energy = G4AtomicShells::GetBindingEnergy(Z, idx);
if(0 <= shell) {
G4int Z = nucleus->GetZ_asInt();
if(Z <= 100) {
G4int idx = (G4int)shell;
idx = std::min(idx, G4AtomicShells::GetNumberOfShells(Z)-1);
bond_energy = G4AtomicShells::GetBindingEnergy(Z, idx);
}
}
}
G4double etrans = nucleus->GetExcitationEnergy() - newExcEnergy
- bond_energy;
// G4cout << "G4GammaTransition::GenerateGamma - Etrans(MeV)= "
// << etrans << " Eexnew= " << newExcEnergy
// << " Ebond= " << bond_energy << G4endl;
if(fVerbose > 1) {
G4cout << "G4GammaTransition::GenerateGamma - Etrans(MeV)= "
<< etrans << " Eexnew= " << newExcEnergy
<< " Ebond= " << bond_energy << G4endl;
}
if(etrans <= 0.0) {
etrans += bond_energy;
bond_energy = 0.0;
@@ -89,6 +92,7 @@ G4GammaTransition::SampleTransition(G4Fragment* nucleus,
// Do complete Lorentz computation
G4LorentzVector lv = nucleus->GetMomentum();
G4double mass = nucleus->GetGroundStateMass() + newExcEnergy;
//G4double e0 = lv.e();
// select secondary
G4ParticleDefinition* part;
@@ -98,15 +102,9 @@ G4GammaTransition::SampleTransition(G4Fragment* nucleus,
part = G4Electron::Electron();
G4int ne = std::max(nucleus->GetNumberOfElectrons() - 1, 0);
nucleus->SetNumberOfElectrons(ne);
lv += G4LorentzVector(0.0,0.0,0.0,
CLHEP::electron_mass_c2 - bond_energy);
}
/*
G4cout << "New GammaTransition: polarFlag: " << polarFlag
<< " isDiscrete: " << isDiscrete << " isGamma: " << isGamma
<< " isLongLived: " << isLongLived << G4endl;
*/
if(polarFlag && isDiscrete && isGamma && !isLongLived) {
if(polarFlag && isDiscrete) {
SampleDirection(nucleus, mpRatio, JP1, JP2, MP);
} else {
fDirection = G4RandomDirection();
@@ -117,91 +115,87 @@ G4GammaTransition::SampleTransition(G4Fragment* nucleus,
// 2-body decay in rest frame
G4double ecm = lv.mag();
G4ThreeVector bst = lv.boostVector();
if(!isGamma) { ecm += (CLHEP::electron_mass_c2 - bond_energy); }
//G4cout << "Ecm= " << ecm << " mass= " << mass << " emass= " << emass
// << " isLongLived: " << isLongLived << G4endl;
//G4cout << "Ecm= " << ecm << " mass= " << mass << " emass= " << emass << G4endl;
ecm = std::max(ecm, mass + emass);
G4double energy = 0.5*((ecm - mass)*(ecm + mass) + emass*emass)/ecm;
energy = std::max(energy, emass);
G4double mom = std::sqrt((energy - emass)*(energy + emass));
G4double mom = (emass > 0.0) ? std::sqrt((energy - emass)*(energy + emass))
: energy;
// emitted gamma or e-
G4LorentzVector res4mom(mom * fDirection.x(),
mom * fDirection.y(),
mom * fDirection.z(), energy);
// residual
energy = std::max(ecm - energy, mass);
lv.set(-mom*fDirection.x(), -mom*fDirection.y(), -mom*fDirection.z(), energy);
// Lab system transform for short lived level
if(!isLongLived) {
res4mom.boost(bst);
lv -= res4mom;
} else {
// In exceptional case sample decay at rest at not correct position
// of stopping ion, 4-momentum balance is breaked but gamma energy
// is correct
lv -= res4mom;
G4double E = lv.e();
G4double P2= (E - mass)*(E + mass);
G4ThreeVector v = lv.vect().unit();
G4double p = 0.0;
if(P2 > 0.0) { p = std::sqrt(P2); }
else { E = mass; }
lv.set(v.x()*p, v.y()*p, v.z()*p, E);
}
lv.boost(bst);
// modified primary fragment
nucleus->SetMomentum(lv);
nucleus->SetExcEnergyAndMomentum(newExcEnergy, lv);
// gamma or e- are produced
res4mom.boost(bst);
result = new G4Fragment(res4mom, part);
// G4cout << " DeltaE= " << e0 - lv.e() - res4mom.e() << G4endl;
//G4cout << "G4GammaTransition::GenerateGamma : " << thePhoton << G4endl;
//G4cout << " Left nucleus: " << aNucleus << G4endl;
//G4cout << " DeltaE= " << e0 - lv.e() - res4mom.e() + emass
// << " Emass= " << emass << G4endl;
if(fVerbose > 1) {
G4cout << "G4GammaTransition::SampleTransition : " << result << G4endl;
G4cout << " Left nucleus: " << nucleus << G4endl;
}
return result;
}
void G4GammaTransition::SampleDirection(G4Fragment* nuc, G4double ratio,
G4int twoJ1, G4int twoJ2, G4int mp)
{
//G4cout << "G4GammaTransition::SampleDirection" << G4endl;
// PhotonEvaporation dataset:
// The multipolarity number with 1,2,3,4,5,6,7 representing E0,E1,M1,E2,M2,E3,M3
// monopole transition and 100*Nx+Ny representing multipolarity transition with
// Ny and Ny taking the value 1,2,3,4,5,6,7 referring to E0,E1,M1,E2,M2,E3,M3,..
// For example a M1+E2 transition would be written 304.
// M1 is the primary transition (L) and E2 is the secondary (L')
G4double mpRatio = ratio;
G4int L0 = 0, Lp = 0;
if (mp > 99) {
L0 = mp/200;
Lp = (mp%100)/2;
} else {
L0 = mp/2;
Lp = 0;
mpRatio = 0.;
}
fPolTrans.SetGammaTransitionData(twoJ1, twoJ2, L0, mpRatio, Lp);
G4NuclearPolarization* np = nuc->GetNuclearPolarization();
// initial state is non-polarized - create polarization
G4double cosTheta, phi;
if(!np) {
// initial state is non-polarized - create polarization
np = new G4NuclearPolarization();
nuc->SetNuclearPolarization(np);
fDirection = G4RandomDirection();
fPolTrans.UpdatePolarizationToFinalState(fDirection.z(), fDirection.phi(), nuc);
return;
}
// PhotonEvaporation dataset:
// The multipolarity number with 1,2,3,4,5,6,7 representing E1,M1,E2,M2,E3,M3
// monopole transition and 100*Nx+Ny representing multipolarity transition with
// Ny and Ny taking the value 1,2,3,4,5,6,7 referring to E1,M1,E2,M2,E3,M3,..
// For example a M1+E2 transition would be written 203.
//
// In M1+E2, M1 is the primary transition (L) and E2 is the secondary (L')
// So mp = 203 means L0 = 1, Lp = 2 while mp = 2 means L0 = 1, Lp = 0
G4int L0 = 0, Lp = 0;
if(mp >= 100) {
L0 = mp / 200;
Lp = (mp - 200*L0)/2;
cosTheta = 2*G4UniformRand() - 1.0;
phi = CLHEP::twopi*G4UniformRand();
} else {
L0 = mp / 2;
//if(ratio != 0.0) {
// G4cout << "Warning: Got ratio = " << ratio
// << " when 0 was expected... Setting to zero." << G4endl;
ratio = 0.;
// initial state is polarized - generate correlation
cosTheta = fPolTrans.GenerateGammaCosTheta(np->GetPolarization());
phi = fPolTrans.GenerateGammaPhi(cosTheta, np->GetPolarization());
}
fPolTrans.SetGammaTransitionData(twoJ1, twoJ2, L0, ratio, Lp);
G4double cosTheta = fPolTrans.GenerateGammaCosTheta(np->GetPolarization());
G4double phi = fPolTrans.GenerateGammaPhi(cosTheta, np->GetPolarization());
fPolTrans.UpdatePolarizationToFinalState(cosTheta, phi, nuc);
G4double sinTheta = std::sqrt((1.-cosTheta)*(1.+cosTheta));
fDirection.set(sinTheta*std::cos(phi),sinTheta*std::sin(phi),cosTheta);
if(fVerbose > 1) {
G4cout << "G4GammaTransition::SampleDirection : " << fDirection << G4endl;
G4cout << "Polarisation : " << *np << G4endl;
}
}
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4PhotonEvaporation.cc 101865 2016-12-02 13:06:50Z gcosmo $
// $Id: G4PhotonEvaporation.cc 102726 2017-02-20 13:15:29Z gcosmo $
//
// -------------------------------------------------------------------
//
@@ -59,7 +59,7 @@ G4float G4PhotonEvaporation::GRWidth[] = {0.0f};
G4PhotonEvaporation::G4PhotonEvaporation(G4GammaTransition* p)
: fLevelManager(nullptr), fTransition(p), fVerbose(0), fPoints(0),
vShellNumber(-1), fIndex(0), fTimeLimit(DBL_MAX), fMaxLifeTime(DBL_MAX),
vShellNumber(-1), fIndex(0), fMaxLifeTime(DBL_MAX),
fICM(false), fRDM(false), fSampleTime(true), isInitialised(false)
{
//G4cout << "### New G4PhotonEvaporation() " << this << G4endl;
@@ -69,9 +69,6 @@ G4PhotonEvaporation::G4PhotonEvaporation(G4GammaTransition* p)
if(!fTransition) { fTransition = new G4GammaTransition(); }
char* env = getenv("G4AddTimeLimitToPhotonEvaporation");
if(env) { fTimeLimit = 1.e-16*CLHEP::second; }
theA = theZ = fCode = 0;
fLevelEnergyMax = fStep = fExcEnergy = fProbability = 0.0;
@@ -96,12 +93,16 @@ void G4PhotonEvaporation::Initialise()
if(isInitialised) { return; }
isInitialised = true;
if(fVerbose > 0) {
G4cout << "### G4PhotonEvaporation is initialized " << this << G4endl;
}
G4DeexPrecoParameters* param = fNuclearLevelData->GetParameters();
LevelDensity = param->GetLevelDensity();
Tolerance = param->GetMinExcitation();
fMaxLifeTime = param->GetMaxLifeTime();
fTransition->SetPolarizationFlag(param->CorrelatedGamma());
fTransition->SetVerbose(fVerbose);
}
G4Fragment*
@@ -122,7 +123,9 @@ G4PhotonEvaporation::EmittedFragment(G4Fragment* nucleus)
G4FragmentVector*
G4PhotonEvaporation::BreakItUp(const G4Fragment& nucleus)
{
//G4cout << "G4PhotonEvaporation::BreakItUp" << G4endl;
if(fVerbose > 0) {
G4cout << "G4PhotonEvaporation::BreakItUp" << G4endl;
}
G4Fragment* aNucleus = new G4Fragment(nucleus);
G4FragmentVector* products = new G4FragmentVector();
BreakUpChain(products, aNucleus);
@@ -272,17 +275,15 @@ G4PhotonEvaporation::GenerateGamma(G4Fragment* nucleus)
G4double efinal = 0.0;
G4double ratio = 0.0;
vShellNumber = -1;
size_t shell = 0;
G4int JP1 = 0;
G4int JP2 = 0;
G4int multiP = 0;
G4bool isGamma = true;
G4bool isLongLived = false;
G4bool isDiscrete = false;
G4bool icm = fICM;
const G4NucLevel* level = nullptr;
size_t ntrans = 0;
if(fLevelManager && eexc <= fLevelEnergyMax + Tolerance) {
fIndex = fLevelManager->NearestLevelIndex(eexc, fIndex);
if(0 < fIndex) {
@@ -290,13 +291,13 @@ G4PhotonEvaporation::GenerateGamma(G4Fragment* nucleus)
level = fLevelManager->GetLevel(fIndex);
if(level) {
ntrans = level->NumberOfTransitions();
JP1 = fLevelManager->SpinParity(fIndex);
JP1 = fLevelManager->SpinTwo(fIndex);
if(ntrans > 0) { isDiscrete = true; }
else if(fLevelManager->IsFloatingLevel(fIndex)) {
else if(fLevelManager->FloatingLevel(fIndex) > 0) {
--fIndex;
level = fLevelManager->GetLevel(fIndex);
ntrans = level->NumberOfTransitions();
JP1 = fLevelManager->SpinParity(fIndex);
JP1 = fLevelManager->SpinTwo(fIndex);
if(ntrans > 0) { isDiscrete = true; }
}
}
@@ -343,6 +344,7 @@ G4PhotonEvaporation::GenerateGamma(G4Fragment* nucleus)
--fIndex;
efinal = (G4double)fLevelManager->LevelEnergy(fIndex);
}
nucleus->SetFloatingLevelNumber(fLevelManager->FloatingLevel(fIndex));
}
if(fVerbose > 1) {
G4cout << "Continues emission efinal(MeV)= " << efinal << G4endl;
@@ -358,34 +360,27 @@ G4PhotonEvaporation::GenerateGamma(G4Fragment* nucleus)
G4double ltime = 0.0;
if(fSampleTime) {
if(fICM) { ltime = (G4double)fLevelManager->LifeTime(fIndex); }
else { ltime = (G4double)fLevelManager->LifeTimeGamma(fIndex); }
ltime = (G4double)fLevelManager->LifeTime(fIndex);
if(!fRDM && ltime >= fMaxLifeTime) { return result; }
}
if(ltime >= fMaxLifeTime) { return result; }
if(ltime > fTimeLimit) {
icm = true;
isLongLived = true;
}
size_t idx = 0;
if(1 < ntrans) {
idx = level->SampleGammaTransition(G4UniformRand());
}
if(fVerbose > 1) {
G4cout << "Ntrans= " << ntrans << " idx= " << idx
<< " icm= " << icm << G4endl;
<< " ICM= " << fICM << G4endl;
}
if(1 < ntrans) {
G4double prob = (G4double)level->GammaProbability(idx);
// prob = 0 means that there is only internal conversion
// if((fICM && prob < 1.0) || prob == 0.0) {
if(prob < 1.0) {
G4double rndm = G4UniformRand();
if(icm) { idx = level->SampleGammaETransition(rndm); }
else { idx = level->SampleGammaTransition(rndm); }
//G4cout << "Sampled idx= " << idx << " rndm= " << rndm << G4endl;
}
if(icm) {
G4double rndm = G4UniformRand();
G4double prob = level->GammaProbability(idx);
if(rndm > prob) {
rndm = (rndm - prob)/(1.0 - prob);
shell = level->SampleShell(idx, rndm);
vShellNumber = shell;
isGamma = false;
rndm = (rndm - prob)/(1.0 - prob);
vShellNumber = level->SampleShell(idx, rndm);
}
}
// it is discrete transition with possible gamma correlation
@@ -393,37 +388,35 @@ G4PhotonEvaporation::GenerateGamma(G4Fragment* nucleus)
ratio = level->MixingRatio(idx);
multiP = level->TransitionType(idx);
fIndex = level->FinalExcitationIndex(idx);
JP2 = fLevelManager->SpinParity(fIndex);
JP2 = fLevelManager->SpinTwo(fIndex);
// final energy and time
efinal = (G4double)fLevelManager->LevelEnergy(fIndex);
if(fSampleTime && ltime > 0.0) {
time -= ltime*G4Log(G4UniformRand());
}
nucleus->SetFloatingLevelNumber(fLevelManager->FloatingLevel(fIndex));
}
// protection for floating levels
if(std::abs(efinal - eexc) <= Tolerance) { return result; }
result = fTransition->SampleTransition(nucleus, efinal, ratio, JP1,
JP2, multiP, shell, isDiscrete,
isGamma, isLongLived);
JP2, multiP, vShellNumber,
isDiscrete, isGamma);
if(result) { result->SetCreationTime(time); }
nucleus->SetCreationTime(time);
if(fVerbose > 1) {
G4cout << "Final level E= " << efinal << " time= " << time
<< " idxFinal= " << fIndex << " isDiscrete: " << isDiscrete
<< " isGamma: " << isGamma << " isLongLived: " << isLongLived
<< " multiP= " << multiP << " shell= " << shell << G4endl;
<< " isGamma: " << isGamma << " multiP= " << multiP
<< " shell= " << vShellNumber << G4endl;
}
return result;
}
void G4PhotonEvaporation::SetMaxHalfLife(G4double val)
{
static const G4double tfact = G4Pow::GetInstance()->logZ(2);
fMaxLifeTime = val/tfact;
}
void G4PhotonEvaporation::SetMaxHalfLife(G4double)
{}
void G4PhotonEvaporation::SetGammaTransition(G4GammaTransition* p)
{
@@ -42,11 +42,12 @@
#include "G4Fragment.hh"
#include "G4NuclearPolarization.hh"
#include "G4SystemOfUnits.hh"
#include "G4Exp.hh"
using namespace std;
G4PolarizationTransition::G4PolarizationTransition()
: fTwoJ1(0), fTwoJ2(0), fLbar(1), fL(0), fDelta(0), kEps(1.e-15),
: fVerbose(0), fTwoJ1(0), fTwoJ2(0), fLbar(1), fL(0), fDelta(0), kEps(1.e-15),
kPolyPDF(0, nullptr, -1, 1)
{}
@@ -56,7 +57,7 @@ G4PolarizationTransition::~G4PolarizationTransition()
G4double G4PolarizationTransition::FCoefficient(G4int K, G4int LL, G4int Lprime,
G4int twoJ2, G4int twoJ1) const
{
G4double fCoeff = G4Clebsch::Wigner3J(LL, Lprime, K, 1, -1, 0);
G4double fCoeff = G4Clebsch::Wigner3J(2*LL, 2, 2*Lprime, -2, 2*K, 0);
if(fCoeff == 0) return 0;
fCoeff *= G4Clebsch::Wigner6J(2*LL, 2*Lprime, 2*K, twoJ1, twoJ1, twoJ2);
if(fCoeff == 0) return 0;
@@ -68,7 +69,7 @@ G4double G4PolarizationTransition::F3Coefficient(G4int K, G4int K2, G4int K1,
G4int LL, G4int Lprime,
G4int twoJ2, G4int twoJ1) const
{
G4double fCoeff = G4Clebsch::Wigner3J(LL, Lprime, K, 1, -1, 0);
G4double fCoeff = G4Clebsch::Wigner3J(2*LL, 2, 2*Lprime, -2, 2*K, 0);
if(fCoeff == 0) return 0;
fCoeff *= G4Clebsch::Wigner9J(twoJ2, 2*LL, twoJ1, twoJ2, 2*Lprime, twoJ1,
2*K2, 2*K, 2*K1);
@@ -81,30 +82,34 @@ void G4PolarizationTransition::SetGammaTransitionData(G4int twoJ1, G4int twoJ2,
G4int Lbar, G4double delta,
G4int Lprime)
{
fTwoJ1 = twoJ1;
fTwoJ2 = twoJ2;
fTwoJ1 = std::abs(twoJ1); // add abs to remove negative J
fTwoJ2 = std::abs(twoJ2);
fLbar = Lbar;
fDelta = delta;
fL = Lprime;
if(fVerbose > 1) {
G4cout << "SET G4PolarizationTransition: J1= " << fTwoJ1 << " J2= " << fTwoJ2
<< " Lbar= " << fLbar << " delta= " << fDelta << " Lp= " << fL << G4endl;
}
}
G4double G4PolarizationTransition::GammaTransFCoefficient(G4int K) const
{
double transFCoeff = FCoefficient(K, fLbar, fLbar, fTwoJ2, fTwoJ1);
if(fDelta == 0) return transFCoeff;
transFCoeff += 2.*fDelta*FCoefficient(K, fLbar, fL, fTwoJ2, fTwoJ1);
transFCoeff += fDelta*fDelta*FCoefficient(K, fL, fL, fTwoJ2, fTwoJ1);
return transFCoeff;
double transFCoeff = FCoefficient(K, fLbar, fLbar, fTwoJ2, fTwoJ1);
if(fDelta == 0) return transFCoeff;
transFCoeff += 2.*fDelta*FCoefficient(K, fLbar, fL, fTwoJ2, fTwoJ1);
transFCoeff += fDelta*fDelta*FCoefficient(K, fL, fL, fTwoJ2, fTwoJ1);
return transFCoeff;
}
G4double G4PolarizationTransition::GammaTransF3Coefficient(G4int K, G4int K2,
G4int K1) const
{
double transF3Coeff = F3Coefficient(K, K2, K1, fLbar, fLbar, fTwoJ2, fTwoJ1);
if(fDelta == 0) return transF3Coeff;
transF3Coeff += 2.*fDelta*F3Coefficient(K, K2, K1, fLbar, fL, fTwoJ2, fTwoJ1);
transF3Coeff += fDelta*fDelta*F3Coefficient(K, K2, K1, fL, fL, fTwoJ2, fTwoJ1);
return transF3Coeff;
double transF3Coeff = F3Coefficient(K, K2, K1, fLbar, fLbar, fTwoJ2, fTwoJ1);
if(fDelta == 0) return transF3Coeff;
transF3Coeff += 2.*fDelta*F3Coefficient(K, K2, K1, fLbar, fL, fTwoJ2, fTwoJ1);
transF3Coeff += fDelta*fDelta*F3Coefficient(K, K2, K1, fL, fL, fTwoJ2, fTwoJ1);
return transF3Coeff;
}
G4double G4PolarizationTransition::GenerateGammaCosTheta(const POLAR& pol)
@@ -117,8 +122,10 @@ G4double G4PolarizationTransition::GenerateGammaCosTheta(const POLAR& pol)
// terms to generate cos theta distribution
vector<G4double> polyPDFCoeffs(length, 0.0);
for(size_t k = 0; k < length; k += 2) {
if(std::abs(((pol)[k])[0].imag()) > kEps) {
G4cout << "Warning: fPolarization[" << k << "][0] has imag component: = "
if(std::abs(((pol)[k])[0].imag()) > kEps && fVerbose > 0) {
G4cout << "G4PolarizationTransition::GenerateGammaCosTheta WARNING: \n"
<< " fPolarization["
<< k << "][0] has imag component: = "
<< ((pol)[k])[0].real() << " + "
<< ((pol)[k])[0].imag() << "*i" << G4endl;
}
@@ -147,38 +154,34 @@ G4double G4PolarizationTransition::GenerateGammaPhi(G4double cosTheta,
// Otherwise, P(phi) can be written as a sum of cos(kappa phi + phi_kappa).
// Calculate the amplitude and phase for each term
vector<G4double> amp(length, 0.0);
vector<G4double> phase(length, 0.0);
std::vector<G4double> amp(length, 0.0);
std::vector<G4double> phase(length, 0.0);
for(size_t kappa = 0; kappa < length; ++kappa) {
G4complex cAmpSum = 0.;
G4complex cAmpSum(0.,0.);
for(size_t k = kappa + (kappa % 2); k < length; k += 2) {
if(kappa >= length || std::abs(((pol)[k])[kappa]) < kEps) { continue; }
G4double tmpAmp = GammaTransFCoefficient(k);
if(tmpAmp == 0) { continue; }
tmpAmp *= sqrt(2*k+1) * fgLegendrePolys.EvalAssocLegendrePoly(k, kappa, cosTheta);
if(kappa > 0) tmpAmp *= 2.*exp(0.5*(LnFactorial(k-kappa) - LnFactorial(k+kappa)));
if(kappa > 0) tmpAmp *= 2.*G4Exp(0.5*(LnFactorial(k-kappa) - LnFactorial(k+kappa)));
cAmpSum += ((pol)[k])[kappa]*tmpAmp;
}
if(kappa == 0 && std::abs(cAmpSum.imag()) > kEps) {
G4cout << "G4PolarizationTransition::GenerateGammaPhi: WARNING "
<< " got complex amp for kappa = 0! A = " << cAmpSum.real()
if(kappa == 0 && std::abs(cAmpSum.imag()) > kEps && fVerbose > 0) {
G4cout << "G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
<< " Got complex amp for kappa = 0! A = " << cAmpSum.real()
<< " + " << cAmpSum.imag() << "*i" << G4endl;
}
amp[kappa] = std::abs(cAmpSum);
if(amp[kappa] < 0) {
G4cout << "G4PolarizationTransition::GenerateGammaPhi: WARNING "
<< "got negative abs for kappa = " << kappa << G4endl;
}
phase[kappa] = arg(cAmpSum);
}
// Normalize PDF and calc max (note: it's not the true max, but the max
// assuming that all of the phases line up at a max)
G4double pdfMax = 0;
G4double pdfMax = 0.;
for(size_t kappa = 0; kappa < amp.size(); ++kappa) { pdfMax += amp[kappa]; }
if(pdfMax < kEps) {
if(pdfMax < kEps && fVerbose > 0) {
G4cout << "G4PolarizationTransition::GenerateGammaPhi: WARNING "
<< "got pdfMax = 0 for ";
<< "got pdfMax = 0 for \n";
DumpTransitionData(pol);
G4cout << "I suspect a non-allowed transition! Returning isotropic phi..."
<< G4endl;
@@ -194,15 +197,16 @@ G4double G4PolarizationTransition::GenerateGammaPhi(G4double cosTheta,
pdfSum += amp[kappa]*cos(phi*kappa + phase[kappa]);
}
if(prob < pdfSum) return phi;
if(pdfSum > pdfMax) {
G4cout << "G4PolarizationTransition::GenerateGammaPhi: WARNING "
if(pdfSum > pdfMax && fVerbose > 0) {
G4cout << "G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
<< "got pdfSum (" << pdfSum << ") > pdfMax ("
<< pdfMax << ") at phi = " << phi << G4endl;
}
}
G4cout << "G4PolarizationTransition::GenerateGammaPhi: WARNING "
<< "no phi generated in 1000 throws! Returning isotropic phi..." << G4endl;
if(fVerbose > 0) {
G4cout << "G4PolarizationTransition::GenerateGammaPhi: WARNING: \n"
<< "no phi generated in 1000 throws! Returning isotropic phi..." << G4endl;
}
return G4UniformRand()*CLHEP::twopi;
}
@@ -210,23 +214,27 @@ void G4PolarizationTransition::UpdatePolarizationToFinalState(G4double cosTheta,
G4double phi,
G4Fragment* frag)
{
if(fTwoJ2 == 0) {
frag->SetNuclearPolarization(nullptr);
G4NuclearPolarization* nucpol = frag->GetNuclearPolarization();
if(nucpol == nullptr) {
if(fVerbose > 0) {
G4cout << "G4PolarizationTransition::UpdatePolarizationToFinalState ERROR: "
<< "cannot update NULL nuclear polarization" << G4endl;
}
return;
}
POLAR pol;
G4NuclearPolarization* nucpol = frag->GetNuclearPolarization();
if(nucpol) { pol = nucpol->GetPolarization(); }
size_t length = pol.size();
if(fTwoJ2 == 0) {
nucpol->Unpolarize();
return;
}
const POLAR& pol = nucpol->GetPolarization();
size_t newlength = fTwoJ2+1;
POLAR newPol;
newPol.resize(newlength);
POLAR newPol(newlength);
for(size_t k2=0; k2<newlength; ++k2) {
(newPol[k2]).assign(k2+1, 0);
for(size_t k1=0; k1<length; ++k1) {
for(size_t k1=0; k1<pol.size(); ++k1) {
for(size_t k=0; k<=k1+k2; k+=2) {
// TransF3Coefficient takes the most time. Only calculate it once per
// (k, k1, k2) triplet, and wait until the last possible moment to do
@@ -241,14 +249,14 @@ void G4PolarizationTransition::UpdatePolarizationToFinalState(G4double cosTheta,
conj((pol[k1])[-kappa1])*(kappa1 % 2 ? -1.: 1.) : (pol[k1])[kappa1];
if(std::abs(tmpAmp) < kEps) continue;
G4int kappa = kappa1-(G4int)kappa2;
tmpAmp *= G4Clebsch::Wigner3J(k1, k, k2, -kappa1, kappa, kappa2);
tmpAmp *= G4Clebsch::Wigner3J(2*k1, -2*kappa1, 2*k, 2*kappa, 2*k2, 2*kappa2);
if(std::abs(tmpAmp) < kEps) continue;
if(recalcTF3) {
tF3 = GammaTransF3Coefficient(k, k2, k1);
recalcTF3 = false;
}
if(std::abs(tF3) < kEps) break;
tmpAmp *= GammaTransF3Coefficient(k, k2, k1);
tmpAmp *= tF3;
if(std::abs(tmpAmp) < kEps) continue;
tmpAmp *= ((kappa1+(G4int)k1)%2 ? -1. : 1.)
* sqrt((2.*k+1.)*(2.*k1+1.)/(2.*k2+1.));
@@ -267,14 +275,19 @@ void G4PolarizationTransition::UpdatePolarizationToFinalState(G4double cosTheta,
}
// sanity checks
if(0.0 == newPol[0][0]) {
frag->SetNuclearPolarization(nullptr);
if(0.0 == newPol[0][0] && fVerbose > 1) {
G4cout << "G4PolarizationTransition::UpdatePolarizationToFinalState WARNING:"
<< " P[0][0] is zero!" << G4endl;
G4cout << "Old pol is: " << *nucpol << G4endl;
DumpTransitionData(newPol);
G4cout << "Unpolarizing..." << G4endl;
nucpol->Unpolarize();
return;
}
if(std::abs((newPol[0])[0].imag()) > kEps) {
G4cout << "G4PolarizationTransition::UpdatePolarizationToFinalState WWARNING:"
if(std::abs((newPol[0])[0].imag()) > kEps && fVerbose > 1) {
G4cout << "G4PolarizationTransition::UpdatePolarizationToFinalState WARNING: \n"
<< " P[0][0] has a non-zero imaginary part! Unpolarizing..." << G4endl;
frag->SetNuclearPolarization(nullptr);
nucpol->Unpolarize();
return;
}
@@ -295,24 +308,20 @@ void G4PolarizationTransition::UpdatePolarizationToFinalState(G4double cosTheta,
while((newPol[k2]).size() != size_t (lastNonZero+1)) (newPol[k2]).pop_back();
if((newPol[k2]).size() > 0) lastNonEmptyK2 = k2;
}
// Remove zero-value entries
while(newPol.size() != lastNonEmptyK2+1) { newPol.pop_back(); }
(newPol[0])[0] = 1.0;
if(!nucpol) {
nucpol = new G4NuclearPolarization();
nucpol->SetPolarization(newPol);
frag->SetNuclearPolarization(nucpol);
} else {
nucpol->SetPolarization(newPol);
}
nucpol->SetPolarization(newPol);
}
void G4PolarizationTransition::DumpTransitionData(const POLAR& pol) const
{
G4cout << "G4PolarizationTransition transition: ";
G4cout << "G4PolarizationTransition: ";
(fTwoJ1 % 2) ? G4cout << fTwoJ1 << "/2" : G4cout << fTwoJ1/2;
G4cout << " --(" << fLbar;
if(fDelta > 0) G4cout << " + " << fDelta << "*" << fL;
if(fDelta != 0) G4cout << " + " << fDelta << "*" << fL;
G4cout << ")--> ";
(fTwoJ2 % 2) ? G4cout << fTwoJ2 << "/2" : G4cout << fTwoJ2/2;
G4cout << ", P = [ { ";
@@ -14,6 +14,9 @@ code and to keep track of all tags.
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
21-December 2016 Gunter Folger had-im_r-V10-02-00
- G4VScatteringCollision: Fix memory leak in MT, bug report 1905
13-November 2015 Gunter Folger had-im_r-V10-01-05
- Revert back to G4float, add 'f' for initialisation.
@@ -180,5 +180,6 @@ double G4VScatteringCollision::SampleResonanceMass(const double poleMass,
void G4VScatteringCollision::establish_G4MT_TLS_G4VScatteringCollision()
{
establish_G4MT_TLS_G4VCollision();
if ( theAngularDistribution ) delete theAngularDistribution;
theAngularDistribution = new G4AngularDistribution(true);
}
@@ -14,6 +14,53 @@ track of all tags.
* Reverse chronological order (last date on top), please *
----------------------------------------------------------
21 February 2017 V.Ivanchenko radioactive_decay-V10-02-18
------------------------------------------------------------
- G4ITDecay: make daughterNucleus a pointer and store previous
state of the G4Fragment there
- G4RadioactiveDecay - removed G4ThreadLocal G4Fragment
20 February 2017 A. Ribon radioactive_decay-V10-02-17
------------------------------------------------------------
- G4RadioactiveDecay: switch off temporarily the correlated gamma emission,
to limit the non-reproducibility violations.
16 February 2017 V.Ivanchenko
------------------------------------------------------------
- G4ITDecay: fixed old mass variable
14 February 2017 Dennis Wright
------------------------------------------------------------
- G4ITDecay: Vladimir's changes from trunk which fix warnings:
added check on Z, A, excitation energy in order to be
sure that correlated gamma may be sampled; reset 4-momentum at rest
when previous nucleaus is reused; use floating level index
when a new ion is created
- G4RadioactiveDecay: use Laurent's level tolerence level of 10 eV
10 February 2017 Dennis Wright
------------------------------------------------------------
- G4RadioactiveDecay: add static G4ThreadLocal G4Fragment polarizedNucleus
to serve as cache for polarized nucleus
- G4RadioactiveDecay::BuildPhysicsTable: added lines
G4DeexPrecoParameters* param = G4NuclearLevelData::GetInstance()->GetParameters();
param->SetUseFilesNEW(true);
param->SetCorrelatedGamma(true);
in order to enable correlated gamma emission
- G4ITDecay: use G4RadioactiveDecay::polarizedNucleus as a cache to enable
chain decay with polarization
20 December 2016 Dennis Wright radioactive_decay-V10-02-16
------------------------------------------------------------
- G4ITDecay::G4ITDecay(): make G4PhotonEvaporation a class member
and intialize only once to avoid memory churn
- G4ITDecay::DecayIt(): make G4Fragment a data member to avoid its
deletion at end of this method and keep polarization information
7 November 2016 Dennis Wright radioactive_decay-V10-02-15
-----------------------------------------------------------
@@ -39,7 +39,9 @@
#define G4ITDecay_h 1
#include "G4NuclearDecay.hh"
#include "G4Fragment.hh"
class G4PhotonEvaporation;
class G4ITDecay : public G4NuclearDecay
{
@@ -61,6 +63,9 @@ class G4ITDecay : public G4NuclearDecay
G4int parentZ;
G4int parentA;
G4bool applyARM;
G4Fragment* daughterNucleus;
G4PhotonEvaporation* photoEvap;
};
#endif
@@ -70,6 +70,7 @@
#include "G4ThreeVector.hh"
#include "G4Threading.hh"
class G4Fragment;
class G4RadioactiveDecaymessenger;
typedef std::vector<G4RadioactiveDecayRateVector> G4RadioactiveDecayRateTable;
@@ -236,6 +237,8 @@ class G4RadioactiveDecay : public G4VRestDiscreteProcess
G4VParticleChange* DecayIt(const G4Track& theTrack,
const G4Step& theStep);
// static G4ThreadLocal G4Fragment* polarizedNucleus;
protected:
G4DecayProducts* DoDecay(const G4ParticleDefinition& theParticleDef);
@@ -38,6 +38,7 @@
#include "G4DynamicParticle.hh"
#include "G4DecayProducts.hh"
#include "G4PhotonEvaporation.hh"
#include "G4RadioactiveDecay.hh"
#include "G4VAtomDeexcitation.hh"
#include "G4AtomicShells.hh"
#include "G4Electron.hh"
@@ -51,7 +52,7 @@ G4ITDecay::G4ITDecay(const G4ParticleDefinition* theParentNucleus,
const G4double& branch, const G4double& Qvalue,
const G4double& excitationE)
: G4NuclearDecay("IT decay", IT, excitationE, noFloat), transitionQ(Qvalue),
applyARM(true)
applyARM(true), daughterNucleus(nullptr), photoEvap(0)
{
SetParent(theParentNucleus); // Store name of parent nucleus, delete G4MT_parent
SetBR(branch);
@@ -63,11 +64,18 @@ G4ITDecay::G4ITDecay(const G4ParticleDefinition* theParentNucleus,
G4IonTable* theIonTable =
(G4IonTable*)(G4ParticleTable::GetParticleTable()->GetIonTable());
SetDaughter(0, theIonTable->GetIon(parentZ, parentA, excitationE, noFloat) );
// Let G4PhotonEvaporation do the decay
photoEvap = new G4PhotonEvaporation;
photoEvap->RDMForced(true);
photoEvap->SetICM(true);
}
G4ITDecay::~G4ITDecay()
{}
{
delete photoEvap;
}
G4DecayProducts* G4ITDecay::DecayIt(G4double)
@@ -83,25 +91,59 @@ G4DecayProducts* G4ITDecay::DecayIt(G4double)
G4DynamicParticle parentParticle(G4MT_parent, atRest);
G4DecayProducts* products = new G4DecayProducts(parentParticle);
// Let G4PhotonEvaporation do the decay
G4PhotonEvaporation* photoEvap = new G4PhotonEvaporation;
photoEvap->RDMForced(true);
photoEvap->SetICM(true);
// Let G4PhotonEvaporation do the decay
G4Fragment parentNucleus(parentA, parentZ, atRest);
// G4cout << " START of G4ITDecay::DecayIt: " << G4endl;
G4Fragment* nucleus = new G4Fragment(parentA, parentZ, atRest);
G4Fragment* eOrGamma = photoEvap->EmittedFragment(nucleus);
// Check if the old nuclear polarization can be used
G4NuclearPolarization* nucPol(nullptr);
G4int oldZ(0), oldA(0);
G4double oldMass(0.0);
if(daughterNucleus) {
nucPol = daughterNucleus->GetNuclearPolarization();
if(nucPol) {
oldZ = daughterNucleus->GetZ_asInt();
oldA = daughterNucleus->GetA_asInt();
oldMass = daughterNucleus->GetGroundStateMass() +
daughterNucleus->GetExcitationEnergy();
}
}
static const G4double mlimit = 10*CLHEP::eV;
if (nucPol && oldZ == parentZ && oldA == parentA
&& std::abs(atRest.e() - oldMass) < mlimit) {
// Continue with existing chain
parentNucleus = *daughterNucleus;
parentNucleus.SetMomentum(atRest);
}
// Daughter nuclide is returned in nucleus pointer
G4double finalDaughterExcitation = nucleus->GetExcitationEnergy();
if (finalDaughterExcitation < 1*keV) finalDaughterExcitation = 0.0;
G4LorentzVector daughterMomentum = nucleus->GetMomentum();
// G4cout << " BEFORE TRANSITION fragment = " << G4endl;
// G4cout << parentNucleus << G4endl;
G4Fragment* eOrGamma = photoEvap->EmittedFragment(&parentNucleus);
// G4cout << " AFTER TRANSITION " << G4endl;
// G4cout << parentNucleus << G4endl;
// Check if IT chain has ended with excited isomere
// Take care for deletion of cached G4Fragment
if (parentNucleus.GetExcitationEnergy() > mlimit) {
// G4cout << " IT chain is continue " << G4endl;
delete daughterNucleus;
daughterNucleus = new G4Fragment(parentNucleus);
} else if(daughterNucleus) {
// G4cout << " End of IT chain " << G4endl;
delete daughterNucleus;
daughterNucleus = nullptr;
}
// Modified nuclide is returned as dynDaughter
G4IonTable* theIonTable =
(G4IonTable*)(G4ParticleTable::GetParticleTable()->GetIonTable() );
G4ParticleDefinition* daughterIon =
theIonTable->GetIon(parentZ, parentA, finalDaughterExcitation);
theIonTable->GetIon(parentZ, parentA, parentNucleus.GetExcitationEnergy(),
G4Ions::FloatLevelBase(parentNucleus.GetFloatingLevelNumber()));
G4DynamicParticle* dynDaughter = new G4DynamicParticle(daughterIon,
daughterMomentum);
delete nucleus;
parentNucleus.GetMomentum());
if (eOrGamma) {
G4DynamicParticle* eOrGammaDyn =
@@ -111,7 +153,7 @@ G4DecayProducts* G4ITDecay::DecayIt(G4double)
products->PushProducts(eOrGammaDyn);
delete eOrGamma;
// Now do atomic relaxation
// Now do atomic relaxation if e- is emitted
if (applyARM) {
G4int shellIndex = photoEvap->GetVacantShellNumber();
if (shellIndex > -1) {
@@ -126,7 +168,6 @@ G4DecayProducts* G4ITDecay::DecayIt(G4double)
// VI, SI
// Allows fixing of Bugzilla 1727
//const G4double deexLimit = 0.1*keV;
G4double deexLimit = 0.1*keV;
if (G4EmParameters::Instance()->DeexcitationIgnoreCut()) deexLimit =0.;
//
@@ -181,8 +222,8 @@ G4DecayProducts* G4ITDecay::DecayIt(G4double)
G4double eCons = G4MT_parent->GetPDGMass() - dynDaughter->GetMass() - KEsum;
G4cout << " IT check: Ediff (keV) = " << eCons/keV << G4endl;
*/
delete photoEvap;
// delete photoEvap;
// G4cout << " END G4ITDecay::DecayIt " << G4endl;
return products;
}
@@ -117,12 +117,14 @@
#include "G4VDecayChannel.hh"
#include "G4NuclearDecay.hh"
#include "G4RadioactiveDecayMode.hh"
#include "G4Fragment.hh"
#include "G4Ions.hh"
#include "G4IonTable.hh"
#include "G4BetaDecayType.hh"
#include "Randomize.hh"
#include "G4LogicalVolumeStore.hh"
#include "G4NuclearLevelData.hh"
#include "G4DeexPrecoParameters.hh"
#include "G4LevelManager.hh"
#include "G4ThreeVector.hh"
#include "G4Electron.hh"
@@ -146,8 +148,10 @@
using namespace CLHEP;
const G4double G4RadioactiveDecay::levelTolerance = 0.1*keV;
// const G4double G4RadioactiveDecay::levelTolerance = 0.1*keV;
const G4double G4RadioactiveDecay::levelTolerance = 10.0*eV;
const G4ThreeVector G4RadioactiveDecay::origin(0.,0.,0.);
//G4ThreadLocal G4Fragment G4RadioactiveDecay::polarizedNucleus=nullptr;
#ifdef G4MULTITHREADED
#include "G4AutoLock.hh"
@@ -413,7 +417,7 @@ G4RadioactiveDecay::ConvolveSourceTimeProfile(const G4double t, const G4double t
}
long double lt = t ;
long double ltau = tau;
// G4cout << " Convolve: tau = " << tau << G4endl;
if (nbin > 0) {
for (G4int i = 0; i < nbin; i++) {
convolvedTime += (long double)SProfile[i] *
@@ -734,6 +738,10 @@ void G4RadioactiveDecay::BuildPhysicsTable(const G4ParticleDefinition&)
theManager->SetAtomDeexcitation(p);
*/
}
G4DeexPrecoParameters* param = G4NuclearLevelData::GetInstance()->GetParameters();
param->SetUseFilesNEW(true);
//param->SetCorrelatedGamma(true); //AR-20Feb2017: Temporary, to fix non-reproducibility problems
}
}
@@ -1235,6 +1243,9 @@ G4RadioactiveDecay::AddDecayRateTable(const G4ParticleDefinition& theParentNucle
<< ") are being calculated, generation = " << nGeneration
<< G4endl;
}
// G4cout << " Taus = " << G4endl;
// for (G4int ii = 0; ii < TP.size(); ii++) G4cout << TP[ii] << ", " ;
// G4cout << G4endl;
aParentNucleus = theIonTable->GetIon(ZP,AP,EP);
parentDecayTable = GetDecayTable(aParentNucleus);
@@ -1785,9 +1796,10 @@ G4RadioactiveDecay::DecayIt(const G4Track& theTrack, const G4Step&)
// it will be used to calculate the statistical weight of the
// decay products of this isotope
// G4cout <<"PA= "<< PA << " PZ= " << PZ << " PE= "<< PE <<G4endl;
// G4cout <<"PA= "<< PA << " PZ= " << PZ << " PE= "<< PE <<G4endl;
decayRate = 0.L;
for (j = 0; j < PT.size(); j++) {
// G4cout << " RDM::DecayIt: tau input to Convolve: " << PT[j] << G4endl;
taotime = ConvolveSourceTimeProfile(theDecayTime,PT[j]);
// taotime = GetTaoTime(theDecayTime,PT[j]);
decayRate -= PR[j] * (long double)taotime;
+15 -1
View File
@@ -1,4 +1,4 @@
$Id: History 100680 2016-10-31 10:52:13Z gcosmo $
$Id: History 102724 2017-02-20 13:00:39Z gcosmo $
-------------------------------------------------------------------
==========================================================
@@ -14,6 +14,20 @@ code and to keep track of all tags.
---------------------------------------------------------------
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
16 February 2017 Vladimir Ivanchenko (hadr-mod-util-V10-02-10)
- G4PolynomialPDF - added control on printout
14 February 2017 Vladimir Ivanchenko
- G4Fragment - added method SetExcEnergyAndMomentum(...) allowing preserve
excitation energy value without any precision lost, 4-momentum
is recomputed; added class member and Get/Set method for floating
levels number which was missing before
16 December 2016 Vladimir Ivanchenko (hadr-mod-util-V10-02-09)
- G4Fragment - minor cleanup of check on excitation energy of
a ground state
25 October 2016 V. Uzhinsky (hadr-mod-util-V10-02-08)
- New method - void SetDefinition(G4ParticleDefinition * aDefinition);
was added to G4Parton class. It is needed for an implementation of
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4Fragment.hh 96383 2016-04-11 09:06:57Z gcosmo $
// $Id: G4Fragment.hh 102724 2017-02-20 13:00:39Z gcosmo $
//
//---------------------------------------------------------------------
//
@@ -105,6 +105,7 @@ public:
inline void SetZandA_asInt(G4int Znew, G4int Anew);
inline G4double GetExcitationEnergy() const;
inline void SetExcEnergyAndMomentum(G4double eexc, const G4LorentzVector&);
inline G4double GetGroundStateMass() const;
@@ -151,6 +152,9 @@ public:
inline G4int GetNumberOfElectrons() const;
inline void SetNumberOfElectrons(G4int value);
inline G4int GetFloatingLevelNumber() const;
inline void SetFloatingLevelNumber(G4int value);
inline const G4ParticleDefinition * GetParticleDefinition() const;
inline void SetParticleDefinition(const G4ParticleDefinition * p);
@@ -160,7 +164,7 @@ public:
inline G4NuclearPolarization* GetNuclearPolarization() const;
inline void SetNuclearPolarization(G4NuclearPolarization*);
void SetAngularMomentum(G4ThreeVector&);
void SetAngularMomentum(const G4ThreeVector&);
G4ThreeVector GetAngularMomentum() const;
// ============= PRIVATE METHODS ==============================
@@ -201,11 +205,14 @@ private:
// Gamma evaporation data members
G4int numberOfShellElectrons;
G4int xLevel;
const G4ParticleDefinition* theParticleDefinition;
G4double spin;
G4double theCreationTime;
static const G4double minFragExcitation;
};
// ============= INLINE METHOD IMPLEMENTATIONS ===================
@@ -239,7 +246,10 @@ inline void G4Fragment::operator delete(void * aFragment)
inline void G4Fragment::CalculateExcitationEnergy()
{
theExcitationEnergy = theMomentum.mag() - theGroundStateMass;
if(theExcitationEnergy < 0.0) { ExcitationEnergyWarning(); }
if(theExcitationEnergy < minFragExcitation) {
if(theExcitationEnergy < -minFragExcitation) { ExcitationEnergyWarning(); }
theExcitationEnergy = 0.0;
}
}
inline G4double
@@ -280,6 +290,14 @@ inline G4double G4Fragment::GetGroundStateMass() const
return theGroundStateMass;
}
inline void G4Fragment::SetExcEnergyAndMomentum(G4double eexc,
const G4LorentzVector& v)
{
theExcitationEnergy = eexc;
theMomentum.set(0.0, 0.0, 0.0, theGroundStateMass + eexc);
theMomentum.boost(v.boostVector());
}
inline G4double G4Fragment::GetBindingEnergy() const
{
return (theA-theZ)*CLHEP::neutron_mass_c2 + theZ*CLHEP::proton_mass_c2
@@ -406,6 +424,16 @@ inline void G4Fragment::SetSpin(G4double value)
spin = value;
}
inline G4int G4Fragment::GetFloatingLevelNumber() const
{
return xLevel;
}
inline void G4Fragment::SetFloatingLevelNumber(G4int value)
{
xLevel = value;
}
inline
const G4ParticleDefinition* G4Fragment::GetParticleDefinition(void) const
{
@@ -51,8 +51,8 @@ class G4PolynomialPDF
public:
G4PolynomialPDF(size_t n = 0, const double* coeffs = nullptr,
G4double x1=0, G4double x2=1);
~G4PolynomialPDF() {};
~G4PolynomialPDF();
// Setters and Getters for coefficients
inline void SetNCoefficients(size_t n) { fCoefficients.resize(n); fChanged = true; }
inline size_t GetNCoefficients() const { return fCoefficients.size(); }
@@ -94,7 +94,8 @@ class G4PolynomialPDF
// Beware that if x1 and x2 are not set carefully there may be multiple
// solutions, and care is not taken to select a particular one among them.
// Returns x2 on error
G4double GetX( G4double p, G4double x1, G4double x2, G4int ddxPower = 0, G4double guess = 1.e99, G4bool bisect = true );
G4double GetX( G4double p, G4double x1, G4double x2, G4int ddxPower = 0,
G4double guess = 1.e99, G4bool bisect = true );
inline G4double EvalInverseCDF(G4double p) { return GetX(p, fX1, fX2, -1, fX1 + p*(fX2-fX1)); }
G4double Bisect( G4double p, G4double x1, G4double x2 );
@@ -107,8 +108,9 @@ class G4PolynomialPDF
G4double fX1;
G4double fX2;
std::vector<G4double> fCoefficients;
G4bool fChanged;
G4bool fChanged;
G4double fTolerance;
G4int fVerbose;
};
#endif
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4Fragment.cc 97799 2016-06-13 12:13:11Z gcosmo $
// $Id: G4Fragment.cc 102724 2017-02-20 13:00:39Z gcosmo $
//
//---------------------------------------------------------------------
//
@@ -43,9 +43,8 @@
#include "G4ios.hh"
#include <iomanip>
//#define debug_G4Fragment
G4ThreadLocal G4Allocator<G4Fragment> *pFragmentAllocator = nullptr;
const G4double G4Fragment::minFragExcitation = 10.*CLHEP::eV;
// Default constructor
G4Fragment::G4Fragment() :
@@ -61,6 +60,7 @@ G4Fragment::G4Fragment() :
numberOfHoles(0),
numberOfChargedHoles(0),
numberOfShellElectrons(0),
xLevel(0),
theParticleDefinition(nullptr),
spin(0.0),
theCreationTime(0.0)
@@ -80,6 +80,7 @@ G4Fragment::G4Fragment(const G4Fragment &right) :
numberOfHoles(right.numberOfHoles),
numberOfChargedHoles(right.numberOfChargedHoles),
numberOfShellElectrons(right.numberOfShellElectrons),
xLevel(right.xLevel),
theParticleDefinition(right.theParticleDefinition),
spin(right.spin),
theCreationTime(right.theCreationTime)
@@ -92,6 +93,7 @@ G4Fragment::G4Fragment(const G4Fragment &right) :
G4Fragment::~G4Fragment()
{
delete thePolarization;
thePolarization = nullptr;
}
G4Fragment::G4Fragment(G4int A, G4int Z, const G4LorentzVector& aMomentum) :
@@ -107,6 +109,7 @@ G4Fragment::G4Fragment(G4int A, G4int Z, const G4LorentzVector& aMomentum) :
numberOfHoles(0),
numberOfChargedHoles(0),
numberOfShellElectrons(0),
xLevel(0),
theParticleDefinition(nullptr),
spin(0.0),
theCreationTime(0.0)
@@ -131,6 +134,7 @@ G4Fragment::G4Fragment(const G4LorentzVector& aMomentum,
numberOfHoles(0),
numberOfChargedHoles(0),
numberOfShellElectrons(0),
xLevel(0),
theParticleDefinition(aParticleDefinition),
spin(0.0),
theCreationTime(0.0)
@@ -163,6 +167,7 @@ G4Fragment & G4Fragment::operator=(const G4Fragment &right)
numberOfHoles = right.numberOfHoles;
numberOfChargedHoles = right.numberOfChargedHoles;
numberOfShellElectrons = right.numberOfShellElectrons;
xLevel = right.xLevel;
theParticleDefinition = right.theParticleDefinition;
spin = right.spin;
theCreationTime = right.theCreationTime;
@@ -214,6 +219,9 @@ std::ostream& operator << (std::ostream &out, const G4Fragment *theFragment)
<< ") MeV E = "
<< theFragment->GetMomentum().t()/CLHEP::MeV << " MeV"
<< G4endl;
out << " #spin= " << theFragment->GetSpin()
<< " #floatLevelNo= " << theFragment->GetFloatingLevelNumber();
if(theFragment->GetNuclearPolarization()) {
out << theFragment->GetNuclearPolarization();
@@ -224,10 +232,9 @@ std::ostream& operator << (std::ostream &out, const G4Fragment *theFragment)
<< "#Particles= " << theFragment->GetNumberOfParticles()
<< ", #Charged= " << theFragment->GetNumberOfCharged()
<< ", #Holes= " << theFragment->GetNumberOfHoles()
<< ", #ChargedHoles= " << theFragment->GetNumberOfChargedHoles()
<< ", #spin= " << theFragment->GetSpin()
<< G4endl;
<< ", #ChargedHoles= " << theFragment->GetNumberOfChargedHoles();
}
out << G4endl;
out.setf(old_floatfield,std::ios::floatfield);
out.precision(floatPrec);
@@ -242,22 +249,10 @@ std::ostream& operator << (std::ostream &out, const G4Fragment &theFragment)
void G4Fragment::ExcitationEnergyWarning()
{
const G4double exclimit = -10*CLHEP::eV;
if (theExcitationEnergy < exclimit) {
#ifdef G4VERBOSE
G4cout << "G4Fragment::CalculateExcitationEnergy(): WARNING "<<G4endl;
G4cout << *this << G4endl;
G4cout << "G4Fragment::CalculateExcitationEnergy(): WARNING "<<G4endl;
G4cout << *this << G4endl;
#endif
#ifdef debug_G4Fragment
G4ExceptionDescription ed;
ed << *this << G4endl;
G4Exception("G4Fragment::ExcitationEnergyWarning()", "had777",
FatalException,ed);
#endif
}
theExcitationEnergy = 0.0;
}
void G4Fragment::NumberOfExitationWarning(const G4String& value)
@@ -269,7 +264,7 @@ void G4Fragment::NumberOfExitationWarning(const G4String& value)
throw G4HadronicException(__FILE__, __LINE__, text);
}
void G4Fragment::SetAngularMomentum(G4ThreeVector& v)
void G4Fragment::SetAngularMomentum(const G4ThreeVector& v)
{
spin = v.mag();
}
@@ -37,21 +37,24 @@
#include "G4PolynomialPDF.hh"
#include "Randomize.hh"
//#include <time.h>
using namespace std;
G4PolynomialPDF::G4PolynomialPDF(size_t n, const G4double* coeffs,
G4double x1, G4double x2) :
fX1(x1), fX2(x2), fChanged(true), fTolerance(1.e-8)
fX1(x1), fX2(x2), fChanged(true), fTolerance(1.e-8), fVerbose(0)
{
if(coeffs != NULL) SetCoefficients(n, coeffs);
if(coeffs != nullptr) SetCoefficients(n, coeffs);
else if(n > 0) SetNCoefficients(n);
}
G4PolynomialPDF::~G4PolynomialPDF()
{}
void G4PolynomialPDF::SetCoefficient(size_t i, G4double value)
{
while(i >= fCoefficients.size()) fCoefficients.push_back(0); /* Loop checking, 30-Oct-2015, G.Folger */
while(i >= fCoefficients.size()) fCoefficients.push_back(0);
/* Loop checking, 30-Oct-2015, G.Folger */
fCoefficients[i] = value;
fChanged = true;
}
@@ -69,8 +72,10 @@ void G4PolynomialPDF::SetCoefficients(size_t nCoeffs,
void G4PolynomialPDF::SetDomain(G4double x1, G4double x2)
{
if(x2 <= x1) {
G4cout << "G4PolynomialPDF::SetDomain(): Invalide domain! "
<< "(x1 = " << x1 << ", x2 = " << x2 << ")." << G4endl;
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::SetDomain() WARNING: Invalide domain! "
<< "(x1 = " << x1 << ", x2 = " << x2 << ")." << G4endl;
}
return;
}
fX1 = x1;
@@ -95,9 +100,11 @@ void G4PolynomialPDF::Normalize()
x2N*=fX2;
}
if(sum <= 0) {
G4cout << "G4PolynomialPDF::Normalize() PDF has non-positive area: "
<< sum << G4endl;
Dump();
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::Normalize() WARNING: PDF has non-positive area: "
<< sum << G4endl;
Dump();
}
return;
}
@@ -114,14 +121,16 @@ G4double G4PolynomialPDF::Evaluate(G4double x, G4int ddxPower)
/// ddxPower = 1: f = (d/dx) PDF
/// ddxPower = 2: f = (d2/dx2) PDF
if(ddxPower < -1 || ddxPower > 2) {
G4cout << "G4PolynomialPDF::GetX(): ddxPower " << ddxPower
<< " not implemented" << G4endl;
return 0;
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::GetX() WARNING: ddxPower " << ddxPower
<< " not implemented" << G4endl;
}
return 0.0;
}
double f = 0; // return value
double xN = 1; // x to the power N
double x1N = 1; // endpoint x1 to the power N; only used by CDF
double f = 0.; // return value
double xN = 1.; // x to the power N
double x1N = 1.; // endpoint x1 to the power N; only used by CDF
for(size_t i=0; i<=GetNCoefficients(); ++i) {
if(ddxPower == -1) { // CDF
if(i>0) f += GetCoefficient(i-1)*(xN - x1N)/i;
@@ -145,8 +154,10 @@ G4bool G4PolynomialPDF::HasNegativeMinimum(G4double x1, G4double x2)
// p': 2ax + b = 0 -> = 0 at min: x_extreme = -b/2a
if(x1 < fX1 || x2 > fX2 || x2 < x1) {
G4cout << "G4PolynomialPDF::HasNegativeMinimum(): Invalid range "
<< x1 << " - " << x2 << G4endl;
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::HasNegativeMinimum() WARNING: Invalid range "
<< x1 << " - " << x2 << G4endl;
}
return false;
}
@@ -183,8 +194,11 @@ G4double G4PolynomialPDF::GetRandomX()
if(fChanged) {
Normalize();
if(HasNegativeMinimum(fX1, fX2)) {
G4cout << "G4PolynomialPDF::GetRandomX(): PDF has negative values, returning 0..." << G4endl;
return 0;
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::GetRandomX() WARNING: PDF has negative values, returning 0..."
<< G4endl;
}
return 0.0;
}
fChanged = false;
}
@@ -203,23 +217,31 @@ G4double G4PolynomialPDF::GetX(G4double p, G4double x1, G4double x2,
// input range checking
if(GetNCoefficients() == 0) {
G4cout << "G4PolynomialPDF::GetX(): no PDF defined!" << G4endl;
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::GetX() WARNING: no PDF defined!" << G4endl;
}
return x2;
}
if(ddxPower < -1 || ddxPower > 1) {
G4cout << "G4PolynomialPDF::GetX(): ddxPower " << ddxPower
<< " not implemented" << G4endl;
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::GetX() WARNING: ddxPower " << ddxPower
<< " not implemented" << G4endl;
}
return x2;
}
if(ddxPower == -1 && (p<0 || p>1)) {
G4cout << "G4PolynomialPDF::GetX(): p is out of range" << G4endl;
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::GetX() WARNING: p is out of range" << G4endl;
}
return fX2;
}
// check limits
if(x2 <= x1 || x1 < fX1 || x2 > fX2) {
G4cout << "G4PolynomialPDF::GetX(): domain must have fX1 <= x1 < x2 <= fX2. "
<< "You sent x1 = " << x1 << ", x2 = " << x2 << "." << G4endl;
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::GetX() WARNING: domain must have fX1 <= x1 < x2 <= fX2. "
<< "You sent x1 = " << x1 << ", x2 = " << x2 << "." << G4endl;
}
return x2;
}
@@ -298,8 +320,10 @@ G4double G4PolynomialPDF::GetX(G4double p, G4double x1, G4double x2,
}
if(f == 0) return guess;
if(dfdx == 0) {
G4cout << "G4PolynomialPDF::GetX(): got f != 0 but slope = 0 for ddxPower = "
<< ddxPower << G4endl;
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::GetX() WARNING: got f != 0 but slope = 0 for ddxPower = "
<< ddxPower << G4endl;
}
return x2;
}
lastChange = - f/dfdx;
@@ -316,13 +340,18 @@ G4double G4PolynomialPDF::GetX(G4double p, G4double x1, G4double x2,
++iterations;
if(iterations > 50) {
if(p!=0) {
G4cout << "G4PolynomialPDF::GetX(): got stuck searching for " << p
<< " between " << x1 << " and " << x2 << " with ddxPower = "
<< ddxPower
<< ". Last guess was " << guess << "." << G4endl;
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::GetX() WARNING: got stuck searching for " << p
<< " between " << x1 << " and " << x2 << " with ddxPower = "
<< ddxPower
<< ". Last guess was " << guess << "." << G4endl;
}
}
if(ddxPower==-1 && bisect) {
G4cout << "Bisceting and trying again..." << G4endl;
if(fVerbose > 0) {
G4cout << "G4PolynomialPDF::GetX() WARNING: Bisceting and trying again..."
<< G4endl;
}
return Bisect(p, x1, x2);
}
else return guess;