This commit is contained in:
207
geant4/LEMuSR/src/F04ElementField.cc
Normal file
207
geant4/LEMuSR/src/F04ElementField.cc
Normal file
@ -0,0 +1,207 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#include "G4GeometryManager.hh"
|
||||
#include "F04ElementField.hh"
|
||||
#include "F04GlobalField.hh"
|
||||
#include "lem4Parameters.hh"
|
||||
#include "lem4ErrorMessage.hh"
|
||||
|
||||
G4Navigator* F04ElementField::aNavigator;
|
||||
|
||||
F04ElementField::F04ElementField(G4ThreeVector c, G4LogicalVolume* lv)
|
||||
{
|
||||
elementFieldName="NAME_NOT_DEFINED";
|
||||
center = c;
|
||||
|
||||
minX = minY = minZ = -DBL_MAX;
|
||||
maxX = maxY = maxZ = DBL_MAX;
|
||||
|
||||
///G4cout<<"Kamil: F04GlobalField: addElementField() will be called: "<<G4endl;
|
||||
F04GlobalField::getObject()->addElementField(this);
|
||||
|
||||
color = "1,1,1";
|
||||
|
||||
userLimits = new G4UserLimits();
|
||||
|
||||
lvolume = lv;
|
||||
lvolume->SetVisAttributes(getVisAttribute(color));
|
||||
|
||||
maxStep = 1*mm;
|
||||
|
||||
userLimits->SetMaxAllowedStep(maxStep);
|
||||
|
||||
userLimits->SetUserMaxTrackLength(500.*m);
|
||||
userLimits->SetUserMaxTime(10*ms);
|
||||
// userLimits->SetUserMinEkine(0.1*MeV);
|
||||
// userLimits->SetUserMinRange(1*mm);
|
||||
|
||||
lvolume->SetUserLimits(userLimits);
|
||||
}
|
||||
|
||||
void F04ElementField::construct()
|
||||
{
|
||||
G4Navigator* theNavigator =
|
||||
G4TransportationManager::GetTransportationManager()->
|
||||
GetNavigatorForTracking();
|
||||
|
||||
if (!aNavigator) {
|
||||
aNavigator = new G4Navigator();
|
||||
if ( theNavigator->GetWorldVolume() )
|
||||
aNavigator->SetWorldVolume(theNavigator->GetWorldVolume());
|
||||
}
|
||||
|
||||
G4GeometryManager* geomManager = G4GeometryManager::GetInstance();
|
||||
|
||||
if (!geomManager->IsGeometryClosed()) {
|
||||
geomManager->OpenGeometry();
|
||||
geomManager->CloseGeometry(true);
|
||||
}
|
||||
|
||||
///G4cout<<"F04ElementField: center="<<center.x()/mm<<", "<<center.y()/mm<<", "<<center.z()/mm<<G4endl;
|
||||
aNavigator->LocateGlobalPointAndSetup(center,0,false);
|
||||
|
||||
G4TouchableHistoryHandle fTouchable = aNavigator->CreateTouchableHistoryHandle();
|
||||
|
||||
G4int depth = fTouchable->GetHistoryDepth();
|
||||
for (G4int i = 0; i<depth; ++i) {
|
||||
if(fTouchable->GetVolume()->GetLogicalVolume() == lvolume)break;
|
||||
fTouchable->MoveUpHistory();
|
||||
}
|
||||
|
||||
// Check that the point of origin of the field matches that of the logical volume, to which it is assigned:
|
||||
G4String volumeName=lvolume->GetName();
|
||||
if (fTouchable->GetVolume()->GetLogicalVolume() != lvolume) {
|
||||
char eMessage[200];
|
||||
sprintf(eMessage,"F04ElementField.cc::construct(): Origin of the field outside the respective logical volume!! \"%s\".",
|
||||
volumeName.c_str());
|
||||
/// NOTE: Cannot apply fields to non simply connected bodies, as e.g. rings, tori, etc. !
|
||||
lem4ErrorMessage::GetInstance()->lem4Error(FATAL,eMessage,false);
|
||||
}
|
||||
|
||||
// G4cout<<"+!+!+! global2local VOLUME NAME: "<<fTouchable->GetVolume()->GetName()<<G4endl;
|
||||
// Set global2local transform. The centre of the transformation is set to the centre of the volume, not
|
||||
// to the point "center", as one could naively expect! This is corrected a few lines later.
|
||||
global2local = fTouchable->GetHistory()->GetTopTransform();
|
||||
G4ThreeVector local_center = global2local.TransformPoint(center);
|
||||
|
||||
G4cout<<"F04ElementField: " << elementFieldName << " in \""<<volumeName<<"\". "
|
||||
<<"Field origin: Global ("<<center.x()/mm<<", "<<center.y()/mm<<", "<<center.z()/mm<<") mm, "
|
||||
<<"Local ("<<local_center.x()/mm<<", "<<local_center.y()/mm<<", "<<local_center.z()/mm<<") mm."<<G4endl;
|
||||
|
||||
// Print out the point of the origin of the field in the local coordinate system of the logical volume:
|
||||
/// G4ThreeVector local_center = global2local.TransformPoint(center);
|
||||
/// G4cout<<"\t==> "<<elementFieldName<<" (Volume = \""<<volumeName<<"\". Origin of the field in the local coord. system: "
|
||||
/// <<local_center.x()/mm<<", "<<local_center.y()/mm<<", "<<local_center.z()/mm<<" mm.)"<<G4endl;
|
||||
|
||||
// Now move the centre of the transformation such that it coincides with the point "center":
|
||||
global2local*=G4AffineTransform(-local_center);
|
||||
|
||||
// After moving the centre of the transformation, the point "local_center" should be set to 0., 0., 0. in
|
||||
// the following print-out message:
|
||||
// local_center = global2local.TransformPoint(center);
|
||||
// G4cout<<"\t==> "<<elementFieldName<<" (volume=\""<<volumeName<<"\", centre of the field in local coordinate syst 2: "
|
||||
// <<local_center.x()/mm<<", "<<local_center.y()/mm<<", "<<local_center.z()/mm<<" mm.)"<<G4endl;
|
||||
|
||||
// set global bounding box
|
||||
G4double local[4], global[4];
|
||||
|
||||
G4ThreeVector globalPosition;
|
||||
local[3] = 0.0;
|
||||
for (int i=0; i<2; ++i) {
|
||||
local[0] = (i==0 ? -1.0 : 1.0) * getWidth()/2.;
|
||||
for (int j=0; j<2; ++j) {
|
||||
local[1] = (j==0 ? -1.0 : 1.0) * getHeight()/2.;
|
||||
for (int k=0; k<2; ++k) {
|
||||
local[2] = (k==0 ? -1.0 : 1.0) * getLength()/2.;
|
||||
G4ThreeVector localPosition(local[0],local[1],local[2]);
|
||||
globalPosition =
|
||||
global2local.Inverse().TransformPoint(localPosition);
|
||||
global[0] = globalPosition.x();
|
||||
global[1] = globalPosition.y();
|
||||
global[2] = globalPosition.z();
|
||||
setGlobalPoint(global);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4VisAttributes* F04ElementField::getVisAttribute(G4String color)
|
||||
{
|
||||
G4VisAttributes* p = NULL;
|
||||
if(color.size() > 0 &&
|
||||
(isdigit(color.c_str()[0]) || color.c_str()[0] == '.')) {
|
||||
G4double red=0.0, green=0.0, blue=0.0;
|
||||
if (sscanf(color.c_str(),"%lf,%lf,%lf",&red,&green,&blue) == 3) {
|
||||
p = new G4VisAttributes(true,G4Color(red,green,blue));
|
||||
} else {
|
||||
G4cout << " Invalid color " << color << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (!p) p = new G4VisAttributes(G4VisAttributes::Invisible);
|
||||
p->SetDaughtersInvisible(false);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void F04ElementField::SetEventNrDependentField(G4double initialField, G4double finalField, G4int nrOfSteps) {
|
||||
G4double eventNrStep = float(lem4Parameters::nrOfEventsToBeGenerated)/(nrOfSteps);
|
||||
G4double fieldStep = (finalField-initialField)/(nrOfSteps-1);
|
||||
// G4cout<<"lem4Parameters::nrOfEventsToBeGenerated="<<lem4Parameters::nrOfEventsToBeGenerated<<G4endl;
|
||||
// G4cout<<"fieldStep="<<fieldStep<<" eventNrStep="<<eventNrStep<<G4endl;
|
||||
for (G4int i=1; i<=nrOfSteps; i++) {
|
||||
G4int eventNumber = int(i*eventNrStep);
|
||||
G4double field = initialField + i*fieldStep;
|
||||
changeFieldInStepsMap[eventNumber]=field;
|
||||
}
|
||||
|
||||
G4cout << "Setting field in steps for field "<<elementFieldName<<G4endl;
|
||||
std::map<G4int,G4double>::iterator it;
|
||||
for ( it=changeFieldInStepsMap.begin() ; it != changeFieldInStepsMap.end(); it++ ) {
|
||||
G4cout << "Field will be changed at event "<< (*it).first << " to the value of " << (*it).second/tesla<<" T" << G4endl;
|
||||
// G4double nominalFieldValue=it->second;
|
||||
// it->SetNominalFieldValue(nominalFieldValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void F04ElementField::SetElementFieldValueIfNeeded(G4int eventNr) {
|
||||
std::map<G4int,G4double>::iterator itr;
|
||||
itr = changeFieldInStepsMap.find(eventNr);
|
||||
if (itr==F04ElementField::changeFieldInStepsMap.end()) {
|
||||
// eventNr was not found in the map ==> field is not going to change at this eventNr
|
||||
}
|
||||
else {
|
||||
G4double newFieldValue = itr->second;
|
||||
SetNominalFieldValue(newFieldValue);
|
||||
// G4cout<<"Nominal Field changed for "<<G4endl;
|
||||
}
|
||||
}
|
147
geant4/LEMuSR/src/F04FieldMessenger.cc
Normal file
147
geant4/LEMuSR/src/F04FieldMessenger.cc
Normal file
@ -0,0 +1,147 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#include "F04FieldMessenger.hh"
|
||||
|
||||
#include "F04GlobalField.hh"
|
||||
#include "G4UIdirectory.hh"
|
||||
#include "G4UIcmdWithAString.hh"
|
||||
#include "G4UIcmdWithAnInteger.hh"
|
||||
#include "G4UIcmdWithADoubleAndUnit.hh"
|
||||
#include "G4UIcmdWithoutParameter.hh"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
F04FieldMessenger::F04FieldMessenger(F04GlobalField* pEMfield)
|
||||
: fGlobalField(pEMfield)
|
||||
{
|
||||
detDir = new G4UIdirectory("/field/");
|
||||
detDir->SetGuidance(" Field tracking control ");
|
||||
|
||||
fStepperCMD = new G4UIcmdWithAnInteger("/field/setStepperType",this);
|
||||
fStepperCMD->SetGuidance("Select stepper type for field");
|
||||
fStepperCMD->SetParameterName("choice",true);
|
||||
fStepperCMD->SetDefaultValue(4);
|
||||
fStepperCMD->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
fUpdateCMD = new G4UIcmdWithoutParameter("/field/update",this);
|
||||
fUpdateCMD->SetGuidance("Update Field");
|
||||
fUpdateCMD->SetGuidance("This command MUST be applied before \"beamOn\" ");
|
||||
fUpdateCMD->SetGuidance("if you changed field settings.");
|
||||
fUpdateCMD->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
fMinStepCMD = new G4UIcmdWithADoubleAndUnit("/field/setMinStep",this);
|
||||
fMinStepCMD->SetGuidance("Define minimal step");
|
||||
fMinStepCMD->SetParameterName("min step",false,false);
|
||||
fMinStepCMD->SetDefaultUnit("mm");
|
||||
fMinStepCMD->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
fDeltaChordCMD = new G4UIcmdWithADoubleAndUnit("/field/setDeltaChord",this);
|
||||
fDeltaChordCMD->SetGuidance("Define delta chord");
|
||||
fDeltaChordCMD->SetParameterName("delta chord",false,false);
|
||||
fDeltaChordCMD->SetDefaultUnit("mm");
|
||||
fDeltaChordCMD->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
fDeltaOneStepCMD =
|
||||
new G4UIcmdWithADoubleAndUnit("/field/setDeltaOneStep",this);
|
||||
fDeltaOneStepCMD->SetGuidance("Define delta one step");
|
||||
fDeltaOneStepCMD->SetParameterName("delta one step",false,false);
|
||||
fDeltaOneStepCMD->SetDefaultUnit("mm");
|
||||
fDeltaOneStepCMD->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
fDeltaIntersectionCMD =
|
||||
new G4UIcmdWithADoubleAndUnit("/field/setDeltaIntersection",this);
|
||||
fDeltaIntersectionCMD->SetGuidance("Define delta intersection");
|
||||
fDeltaIntersectionCMD->SetParameterName("delta intersection",false,false);
|
||||
fDeltaIntersectionCMD->SetDefaultUnit("mm");
|
||||
fDeltaIntersectionCMD->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
fEpsMinCMD = new G4UIcmdWithADoubleAndUnit("/field/setEpsMin",this);
|
||||
fEpsMinCMD->SetGuidance("Define eps min");
|
||||
fEpsMinCMD->SetParameterName("eps min",false,false);
|
||||
fEpsMinCMD->SetDefaultUnit("mm");
|
||||
fEpsMinCMD->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
fEpsMaxCMD = new G4UIcmdWithADoubleAndUnit("/field/setEpsMax",this);
|
||||
fEpsMaxCMD->SetGuidance("Define eps max");
|
||||
fEpsMaxCMD->SetParameterName("eps max",false,false);
|
||||
fEpsMaxCMD->SetDefaultUnit("mm");
|
||||
fEpsMaxCMD->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
}
|
||||
|
||||
F04FieldMessenger::~F04FieldMessenger()
|
||||
{
|
||||
delete detDir;
|
||||
|
||||
delete fStepperCMD;
|
||||
delete fMinStepCMD;
|
||||
delete fDeltaChordCMD;
|
||||
delete fDeltaOneStepCMD;
|
||||
delete fDeltaIntersectionCMD;
|
||||
delete fEpsMinCMD;
|
||||
delete fEpsMaxCMD;
|
||||
delete fUpdateCMD;
|
||||
}
|
||||
|
||||
void F04FieldMessenger::SetNewValue( G4UIcommand* command, G4String newValue)
|
||||
{
|
||||
if( command == fStepperCMD )
|
||||
{
|
||||
fGlobalField->SetStepperType(fStepperCMD->GetNewIntValue(newValue));
|
||||
}
|
||||
if( command == fUpdateCMD )
|
||||
{
|
||||
fGlobalField->updateField();
|
||||
}
|
||||
if( command == fMinStepCMD )
|
||||
{
|
||||
fGlobalField->SetMinStep(fMinStepCMD->GetNewDoubleValue(newValue));
|
||||
}
|
||||
if( command == fDeltaChordCMD )
|
||||
{
|
||||
fGlobalField->SetDeltaChord(fDeltaChordCMD->GetNewDoubleValue(newValue));
|
||||
}
|
||||
if( command == fDeltaOneStepCMD )
|
||||
{
|
||||
fGlobalField->
|
||||
SetDeltaOneStep(fDeltaOneStepCMD->GetNewDoubleValue(newValue));
|
||||
}
|
||||
if( command == fDeltaIntersectionCMD )
|
||||
{
|
||||
fGlobalField->
|
||||
SetDeltaIntersection(fDeltaIntersectionCMD->GetNewDoubleValue(newValue));
|
||||
}
|
||||
if( command == fEpsMinCMD )
|
||||
{
|
||||
fGlobalField->SetEpsMin(fEpsMinCMD->GetNewDoubleValue(newValue));
|
||||
}
|
||||
if( command == fEpsMaxCMD )
|
||||
{
|
||||
fGlobalField->SetEpsMax(fEpsMaxCMD->GetNewDoubleValue(newValue));
|
||||
}
|
||||
}
|
313
geant4/LEMuSR/src/F04GlobalField.cc
Normal file
313
geant4/LEMuSR/src/F04GlobalField.cc
Normal file
@ -0,0 +1,313 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "Randomize.hh"
|
||||
#include "G4TransportationManager.hh"
|
||||
|
||||
#include "G4ExplicitEuler.hh"
|
||||
#include "G4ImplicitEuler.hh"
|
||||
#include "G4SimpleRunge.hh"
|
||||
#include "G4SimpleHeum.hh"
|
||||
#include "G4ClassicalRK4.hh"
|
||||
#include "G4CashKarpRKF45.hh"
|
||||
|
||||
#include "F04GlobalField.hh"
|
||||
#include "lem4RootOutput.hh"
|
||||
|
||||
F04GlobalField* F04GlobalField::object = 0;
|
||||
|
||||
F04GlobalField::F04GlobalField() : G4ElectroMagneticField(),
|
||||
minStep(0.01*mm), deltaChord(3.0*mm),
|
||||
deltaOneStep(0.01*mm), deltaIntersection(0.1*mm),
|
||||
epsMin(2.5e-7*mm), epsMax(0.05*mm),
|
||||
fEquation(0), fFieldManager(0),
|
||||
fFieldPropagator(0), fStepper(0), fChordFinder(0)
|
||||
//F04GlobalField::F04GlobalField() : G4MagneticField(),
|
||||
// minStep(0.01*mm), deltaChord(3.0*mm),
|
||||
// deltaOneStep(0.01*mm), deltaIntersection(0.1*mm),
|
||||
// epsMin(2.5e-7*mm), epsMax(0.05*mm),
|
||||
// fEquation(0), fFieldManager(0),
|
||||
// fFieldPropagator(0), fStepper(0), fChordFinder(0)
|
||||
{
|
||||
fFieldMessenger = new F04FieldMessenger(this);
|
||||
|
||||
fields = new FieldList();
|
||||
|
||||
fStepperType = 4 ; // ClassicalRK4 is default stepper
|
||||
|
||||
// set object
|
||||
|
||||
object = this;
|
||||
|
||||
updateField();
|
||||
}
|
||||
|
||||
F04GlobalField::~F04GlobalField()
|
||||
{
|
||||
clear();
|
||||
|
||||
delete fFieldMessenger;
|
||||
|
||||
if (fEquation) delete fEquation;
|
||||
if (fFieldManager) delete fFieldManager;
|
||||
if (fFieldPropagator) delete fFieldPropagator;
|
||||
if (fStepper) delete fStepper;
|
||||
if (fChordFinder) delete fChordFinder;
|
||||
}
|
||||
|
||||
void F04GlobalField::updateField()
|
||||
{
|
||||
first = true;
|
||||
|
||||
nfp = 0;
|
||||
fp = 0;
|
||||
|
||||
clear();
|
||||
|
||||
// Construct equ. of motion of particles through B fields
|
||||
// fEquation = new G4Mag_EqRhs(this);
|
||||
// Construct equ. of motion of particles through e.m. fields
|
||||
// fEquation = new G4EqMagElectricField(this);
|
||||
// Construct equ. of motion of particles including spin through B fields
|
||||
// fEquation = new G4Mag_SpinEqRhs(this);
|
||||
// Construct equ. of motion of particles including spin through e.m. fields
|
||||
fEquation = new G4EqEMFieldWithSpin(this);
|
||||
|
||||
// Get transportation, field, and propagator managers
|
||||
G4TransportationManager* fTransportManager =
|
||||
G4TransportationManager::GetTransportationManager();
|
||||
|
||||
fFieldManager = GetGlobalFieldManager();
|
||||
|
||||
fFieldPropagator = fTransportManager->GetPropagatorInField();
|
||||
|
||||
// Need to SetFieldChangesEnergy to account for a time varying electric
|
||||
// field (r.f. fields)
|
||||
fFieldManager->SetFieldChangesEnergy(true);
|
||||
|
||||
// Set the field
|
||||
fFieldManager->SetDetectorField(this);
|
||||
|
||||
// Choose a stepper for integration of the equation of motion
|
||||
SetStepper();
|
||||
|
||||
// Create a cord finder providing the (global field, min step length,
|
||||
// a pointer to the stepper)
|
||||
fChordFinder = new G4ChordFinder((G4MagneticField*)this,minStep,fStepper);
|
||||
|
||||
// Set accuracy parameters
|
||||
fChordFinder->SetDeltaChord( deltaChord );
|
||||
|
||||
fFieldManager->SetAccuraciesWithDeltaOneStep(deltaOneStep);
|
||||
|
||||
fFieldManager->SetDeltaIntersection(deltaIntersection);
|
||||
|
||||
fFieldPropagator->SetMinimumEpsilonStep(epsMin);
|
||||
fFieldPropagator->SetMaximumEpsilonStep(epsMax);
|
||||
|
||||
G4cout << "Accuracy Parameters:" <<
|
||||
" MinStep=" << minStep <<
|
||||
", DeltaChord=" << deltaChord <<
|
||||
", DeltaOneStep=" << deltaOneStep << G4endl;
|
||||
G4cout << " " <<
|
||||
" DeltaIntersection=" << deltaIntersection <<
|
||||
", EpsMin=" << epsMin <<
|
||||
", EpsMax=" << epsMax << G4endl;
|
||||
|
||||
fFieldManager->SetChordFinder(fChordFinder);
|
||||
|
||||
}
|
||||
|
||||
F04GlobalField* F04GlobalField::getObject()
|
||||
{
|
||||
if (!object) new F04GlobalField();
|
||||
return object;
|
||||
}
|
||||
|
||||
void F04GlobalField::SetStepper()
|
||||
{
|
||||
if(fStepper) delete fStepper;
|
||||
|
||||
G4cout << G4endl;
|
||||
switch ( fStepperType )
|
||||
{
|
||||
case 0:
|
||||
// fStepper = new G4ExplicitEuler( fEquation, 8 ); // no spin tracking
|
||||
fStepper = new G4ExplicitEuler( fEquation, 12 ); // with spin tracking
|
||||
G4cout << "G4ExplicitEuler is called" << G4endl;
|
||||
break;
|
||||
case 1:
|
||||
// fStepper = new G4ImplicitEuler( fEquation, 8 ); // no spin tracking
|
||||
fStepper = new G4ImplicitEuler( fEquation, 12 ); // with spin tracking
|
||||
G4cout << "G4ImplicitEuler is called" << G4endl;
|
||||
break;
|
||||
case 2:
|
||||
// fStepper = new G4SimpleRunge( fEquation, 8 ); // no spin tracking
|
||||
fStepper = new G4SimpleRunge( fEquation, 12 ); // with spin tracking
|
||||
G4cout << "G4SimpleRunge is called" << G4endl;
|
||||
break;
|
||||
case 3:
|
||||
// fStepper = new G4SimpleHeum( fEquation, 8 ); // no spin tracking
|
||||
fStepper = new G4SimpleHeum( fEquation, 12 ); // with spin tracking
|
||||
G4cout << "G4SimpleHeum is called" << G4endl;
|
||||
break;
|
||||
case 4:
|
||||
// fStepper = new G4ClassicalRK4( fEquation, 8 ); // no spin tracking
|
||||
fStepper = new G4ClassicalRK4( fEquation, 12 ); // with spin tracking
|
||||
G4cout << "G4ClassicalRK4 (default) is called" << G4endl;
|
||||
break;
|
||||
case 5:
|
||||
// fStepper = new G4CashKarpRKF45( fEquation, 8 ); // no spin tracking
|
||||
fStepper = new G4CashKarpRKF45( fEquation, 12 ); // with spin tracking
|
||||
G4cout << "G4CashKarpRKF45 is called" << G4endl;
|
||||
break;
|
||||
default: fStepper = 0;
|
||||
}
|
||||
}
|
||||
|
||||
G4FieldManager* F04GlobalField::GetGlobalFieldManager()
|
||||
{
|
||||
return G4TransportationManager::GetTransportationManager()
|
||||
->GetFieldManager();
|
||||
}
|
||||
|
||||
void F04GlobalField::GetFieldValue(const G4double* point, G4double* field) const
|
||||
{
|
||||
// NOTE: this routine dominates the CPU time for tracking.
|
||||
// Using the simple array fp[] instead of fields[]
|
||||
// directly sped it up
|
||||
|
||||
field[0] = field[1] = field[2] = field[3] = field[4] = field[5] = 0.0;
|
||||
|
||||
// protect against Geant4 bug that calls us with point[] NaN.
|
||||
if(point[0] != point[0]) return;
|
||||
|
||||
// (can't use nfp or fp, as they may change)
|
||||
if (first) ((F04GlobalField*)this)->setupArray(); // (cast away const)
|
||||
|
||||
for (int i=0; i<nfp; ++i) {
|
||||
const F04ElementField* p = fp[i];
|
||||
if (p->isInBoundingBox(point)) {
|
||||
p->addFieldValue(point,field);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// cks NOT SURE WHETHER THE FOLLOWING IS STILL NEEDED, HOWEVER ADDED HERE JUST
|
||||
// FOR THE CASE:
|
||||
// Set some small field if field is almost zero (to avoid internal problems of Geant).
|
||||
///if (sqrt(field[0]*field[0]+field[1]*field[1]+field[2]*field[2])<0.00001*tesla) {
|
||||
/// field[2] = 0.00001*tesla;
|
||||
///}
|
||||
// csk
|
||||
|
||||
|
||||
void F04GlobalField::clear()
|
||||
{
|
||||
if (fields) {
|
||||
if (fields->size()>0) {
|
||||
FieldList::iterator i;
|
||||
for (i=fields->begin(); i!=fields->end(); ++i) delete *i;
|
||||
fields->clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (fp) delete[] fp;
|
||||
|
||||
first = true;
|
||||
|
||||
nfp = 0;
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
void F04GlobalField::setupArray()
|
||||
{
|
||||
first = false;
|
||||
nfp = fields->size();
|
||||
fp = new const F04ElementField* [nfp+1]; // add 1 so it's never 0
|
||||
for (int i=0; i<nfp; ++i) {
|
||||
fp[i] = (*fields)[i];
|
||||
// cks
|
||||
// Find the event numbers, for which the field changes, for each Element Field.
|
||||
// Then mark these event numbers in the Global Field, such that it can be efficiently
|
||||
// find out during the run-time, at which event number the field may change.
|
||||
std::map<G4int,G4double> localChangeFieldInStepsMap = fp[i] ->GetEventNrDependentField();
|
||||
std::map<G4int,G4double>::iterator it;
|
||||
for ( it=localChangeFieldInStepsMap.begin() ; it != localChangeFieldInStepsMap.end(); it++ ) {
|
||||
G4int eventNr = it->first;
|
||||
G4cout<<"globalChangeFieldInStepsMap set for event number "<<eventNr<<G4endl;
|
||||
globalChangeFieldInStepsMap[eventNr]=true;
|
||||
}
|
||||
}
|
||||
lem4RootOutput::GetRootInstance()->SetNrFieldNomVal(nfp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void F04GlobalField::CheckWhetherAnyNominalFieldValueNeedsToBeChanged(G4int eventNumber) {
|
||||
if (globalChangeFieldInStepsMap[eventNumber]) {
|
||||
// G4cout<<"We should check each Element Field Object whether its field needs to be changed:"<<G4endl;
|
||||
G4int jjj=0;
|
||||
FieldList::iterator i;
|
||||
for (i=fields->begin(); i!=fields->end(); ++i) {
|
||||
|
||||
// Set the nominal field value for the given field, if that has been requested for the given field
|
||||
(*i)->SetElementFieldValueIfNeeded(eventNumber);
|
||||
|
||||
// Get the nominal field value for the given field and store it in the Root output
|
||||
G4double nomFieldValue = (*i)->GetNominalFieldValue();
|
||||
lem4RootOutput::GetRootInstance()->SetFieldNomVal(jjj,nomFieldValue);
|
||||
jjj++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Print field value at all points requested by the user:
|
||||
void F04GlobalField::PrintFieldAtRequestedPoints() const {
|
||||
G4ThreeVector p;
|
||||
G4double point[4];
|
||||
G4double EMfield[6]; //={0,0,0,0,0,0};
|
||||
for (unsigned int i=0; i < pointsAtWhichUserWantsToPrintFieldValue.size(); i++) {
|
||||
p = pointsAtWhichUserWantsToPrintFieldValue[i];
|
||||
point[0] = p.x();
|
||||
point[1] = p.y();
|
||||
point[2] = p.z();
|
||||
point[3] = 0.;
|
||||
object->GetFieldValue(point,EMfield);
|
||||
// [MV/m] = [10^3 kV / 10^3 mm] = [kV/mm]. But MV and mm are the BASE units in Geant4 => Fact. = 0.001
|
||||
///printf (" EM field value at (%.f, %.f, %.f) mm is: B = (%.f, %.f, %.f) T, E = (%.10f, %.10f, %.10f) kV/mm\n",
|
||||
printf (" EM field value at (%.f, %.f, %.f) mm is: B = (%0.3g, %0.3g, %0.3g) T, E = (%0.3g, %0.3g, %0.3g) kV/mm\n",
|
||||
point[0]/mm, point[1]/mm, point[2]/mm,
|
||||
EMfield[0]/tesla, EMfield[1]/tesla, EMfield[2]/tesla,
|
||||
EMfield[3]/(kilovolt/mm), EMfield[4]/(kilovolt/mm), EMfield[5]/(kilovolt/mm));
|
||||
}
|
||||
}
|
175
geant4/LEMuSR/src/G4DecayWithSpin.cc
Normal file
175
geant4/LEMuSR/src/G4DecayWithSpin.cc
Normal file
@ -0,0 +1,175 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
// GEANT 4 class header file
|
||||
//
|
||||
// History:
|
||||
// 17 August 2004 P. Gumplinger, T. MacPhail
|
||||
// ------------------------------------------------------------
|
||||
//
|
||||
#include "G4DecayWithSpin.hh"
|
||||
|
||||
#include "G4Step.hh"
|
||||
#include "G4Track.hh"
|
||||
#include "G4DecayTable.hh"
|
||||
#include "G4MuonDecayChannelWithSpin.hh"
|
||||
|
||||
#include "G4Vector3D.hh"
|
||||
|
||||
#include "G4TransportationManager.hh"
|
||||
#include "G4PropagatorInField.hh"
|
||||
#include "G4FieldManager.hh"
|
||||
#include "G4Field.hh"
|
||||
|
||||
#include "G4Transform3D.hh"
|
||||
|
||||
G4DecayWithSpin::G4DecayWithSpin(const G4String& processName):G4Decay(processName){}
|
||||
|
||||
G4DecayWithSpin::~G4DecayWithSpin(){}
|
||||
|
||||
G4VParticleChange* G4DecayWithSpin::DecayIt(const G4Track& aTrack, const G4Step& aStep)
|
||||
{
|
||||
// get particle
|
||||
const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
|
||||
G4ParticleDefinition* aParticleDef = aParticle->GetDefinition();
|
||||
|
||||
// get parent_polarization
|
||||
G4ThreeVector parent_polarization = aParticle->GetPolarization();
|
||||
|
||||
if(parent_polarization == G4ThreeVector(0,0,0))
|
||||
{
|
||||
// Generate random polarization direction
|
||||
|
||||
G4double cost = 1. - 2.*G4UniformRand();
|
||||
G4double sint = std::sqrt((1.-cost)*(1.+cost));
|
||||
|
||||
G4double phi = twopi*G4UniformRand();
|
||||
G4double sinp = std::sin(phi);
|
||||
G4double cosp = std::cos(phi);
|
||||
|
||||
G4double px = sint*cosp;
|
||||
G4double py = sint*sinp;
|
||||
G4double pz = cost;
|
||||
|
||||
parent_polarization.setX(px);
|
||||
parent_polarization.setY(py);
|
||||
parent_polarization.setZ(pz);
|
||||
|
||||
}else{
|
||||
|
||||
G4FieldManager* fieldMgr = aStep.GetTrack()->GetVolume()->
|
||||
GetLogicalVolume()->GetFieldManager();
|
||||
|
||||
if (!fieldMgr) {
|
||||
G4TransportationManager *transportMgr =
|
||||
G4TransportationManager::GetTransportationManager();
|
||||
G4PropagatorInField* fFieldPropagator =
|
||||
transportMgr->GetPropagatorInField();
|
||||
if (fFieldPropagator) fieldMgr =
|
||||
fFieldPropagator->GetCurrentFieldManager();
|
||||
}
|
||||
|
||||
const G4Field* field = NULL;
|
||||
if(fieldMgr)field = fieldMgr->GetDetectorField();
|
||||
|
||||
// if (field && !(fieldMgr->DoesFieldChangeEnergy())) {
|
||||
if (field) {
|
||||
// G4cout << "++++ LOCAL VERSION OF G4 DECAY WITH SPIN !!!! ++++"<< G4endl;
|
||||
G4double point[4];
|
||||
point[0] = (aStep.GetPostStepPoint()->GetPosition())[0];
|
||||
point[1] = (aStep.GetPostStepPoint()->GetPosition())[1];
|
||||
point[2] = (aStep.GetPostStepPoint()->GetPosition())[2];
|
||||
point[3] = aTrack.GetGlobalTime();
|
||||
|
||||
G4double fieldValue[3];
|
||||
field -> GetFieldValue(point,fieldValue);
|
||||
|
||||
G4ThreeVector B(fieldValue[0],fieldValue[1],fieldValue[2]);
|
||||
|
||||
if ((B.mag2())>0) { // Call the spin precession only for non-zero mag. field
|
||||
parent_polarization = Spin_Precession(aStep,B,fRemainderLifeTime);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// decay table
|
||||
G4DecayTable *decaytable = aParticleDef->GetDecayTable();
|
||||
|
||||
if (decaytable) {
|
||||
G4MuonDecayChannelWithSpin *decaychannel;
|
||||
decaychannel = (G4MuonDecayChannelWithSpin*)decaytable->SelectADecayChannel();
|
||||
if (decaychannel) decaychannel->SetPolarization(parent_polarization);
|
||||
}
|
||||
|
||||
G4ParticleChangeForDecay* pParticleChangeForDecay;
|
||||
|
||||
pParticleChangeForDecay = (G4ParticleChangeForDecay*)G4Decay::DecayIt(aTrack,aStep);
|
||||
|
||||
pParticleChangeForDecay->ProposePolarization(parent_polarization);
|
||||
|
||||
return pParticleChangeForDecay;
|
||||
|
||||
}
|
||||
|
||||
G4ThreeVector G4DecayWithSpin::Spin_Precession( const G4Step& aStep,
|
||||
G4ThreeVector B, G4double deltatime )
|
||||
{
|
||||
G4double Bnorm = std::sqrt(sqr(B[0]) + sqr(B[1]) +sqr(B[2]) );
|
||||
|
||||
G4double q = aStep.GetTrack()->GetDefinition()->GetPDGCharge();
|
||||
G4double a = 1.165922e-3;
|
||||
G4double s_omega = 8.5062e+7*rad/(s*kilogauss);
|
||||
|
||||
G4double omega = -(q*s_omega)*(1.+a) * Bnorm;
|
||||
|
||||
G4double rotationangle = deltatime * omega;
|
||||
|
||||
G4Transform3D SpinRotation = G4Rotate3D(rotationangle,B.unit());
|
||||
|
||||
G4Vector3D Spin = aStep.GetTrack() -> GetPolarization();
|
||||
|
||||
G4Vector3D newSpin = SpinRotation * Spin;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if (GetVerboseLevel()>2) {
|
||||
G4double normspin = std::sqrt(Spin*Spin);
|
||||
G4double normnewspin = std::sqrt(newSpin*newSpin);
|
||||
//G4double cosalpha = Spin*newSpin/normspin/normnewspin;
|
||||
//G4double alpha = std::acos(cosalpha);
|
||||
|
||||
G4cout << "AT REST::: PARAMETERS " << G4endl;
|
||||
G4cout << "Initial spin : " << Spin << G4endl;
|
||||
G4cout << "Delta time : " << deltatime << G4endl;
|
||||
G4cout << "Rotation angle: " << rotationangle/rad << G4endl;
|
||||
G4cout << "New spin : " << newSpin << G4endl;
|
||||
G4cout << "Checked norms : " << normspin <<" " << normnewspin << G4endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
return newSpin;
|
||||
|
||||
}
|
197
geant4/LEMuSR/src/MuDecayChannel.cc
Normal file
197
geant4/LEMuSR/src/MuDecayChannel.cc
Normal file
@ -0,0 +1,197 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: MuDecayChannel.cc,v 1.17 2006/06/29 19:25:34 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-09-00 $
|
||||
//
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
// GEANT 4 class header file
|
||||
//
|
||||
// History: first implementation, based on object model of
|
||||
// 30 May 1997 H.Kurashige
|
||||
//
|
||||
// Fix bug in calcuration of electron energy in DecayIt 28 Feb. 01 H.Kurashige
|
||||
//2005
|
||||
// M. Melissas ( melissas AT cppm.in2p3.fr)
|
||||
// J. Brunner ( brunner AT cppm.in2p3.fr)
|
||||
// Adding V-A fluxes for neutrinos using a new algortithm :
|
||||
// ------------------------------------------------------------
|
||||
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "G4DecayProducts.hh"
|
||||
#include "G4VDecayChannel.hh"
|
||||
#include "MuDecayChannel.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4LorentzVector.hh"
|
||||
#include "G4LorentzRotation.hh"
|
||||
#include "G4RotationMatrix.hh"
|
||||
|
||||
MuDecayChannel::MuDecayChannel(const G4String& theParentName,
|
||||
G4double theBR)
|
||||
:G4VDecayChannel("Muonium Decay",1)
|
||||
{
|
||||
// set names for daughter particles
|
||||
if (theParentName == "Mu") {
|
||||
SetBR(theBR);
|
||||
SetParent("Mu");
|
||||
SetNumberOfDaughters(3);
|
||||
SetDaughter(0, "e+");
|
||||
SetDaughter(1, "nu_e");
|
||||
SetDaughter(2, "anti_nu_mu");
|
||||
} else {
|
||||
#ifdef G4VERBOSE
|
||||
if (GetVerboseLevel()>0) {
|
||||
G4cout << "MuDecayChannel:: constructor :";
|
||||
G4cout << " parent particle is not muon but ";
|
||||
G4cout << theParentName << G4endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
MuDecayChannel::~MuDecayChannel()
|
||||
{
|
||||
}
|
||||
|
||||
G4DecayProducts *MuDecayChannel::DecayIt(G4double)
|
||||
{
|
||||
// this version neglects muon polarization,and electron mass
|
||||
// assumes the pure V-A coupling
|
||||
// the Neutrinos are correctly V-A.
|
||||
#ifdef G4VERBOSE
|
||||
if (GetVerboseLevel()>1) G4cout << "MuDecayChannel::DecayIt ";
|
||||
#endif
|
||||
|
||||
if (parent == 0) FillParent();
|
||||
if (daughters == 0) FillDaughters();
|
||||
|
||||
// parent mass
|
||||
G4double parentmass = parent->GetPDGMass();
|
||||
|
||||
//daughters'mass
|
||||
G4double daughtermass[3];
|
||||
G4double sumofdaughtermass = 0.0;
|
||||
for (G4int index=0; index<3; index++){
|
||||
daughtermass[index] = daughters[index]->GetPDGMass();
|
||||
sumofdaughtermass += daughtermass[index];
|
||||
}
|
||||
|
||||
//create parent G4DynamicParticle at rest
|
||||
G4ThreeVector dummy;
|
||||
G4DynamicParticle * parentparticle = new G4DynamicParticle( parent, dummy, 0.0);
|
||||
//create G4Decayproducts
|
||||
G4DecayProducts *products = new G4DecayProducts(*parentparticle);
|
||||
delete parentparticle;
|
||||
|
||||
// calculate daughter momentum
|
||||
G4double daughtermomentum[3];
|
||||
// calcurate electron energy
|
||||
G4double xmax = (1.0+daughtermass[0]*daughtermass[0]/parentmass/parentmass);
|
||||
G4double x;
|
||||
|
||||
G4double Ee,Ene;
|
||||
|
||||
G4double gam;
|
||||
G4double EMax=parentmass/2-daughtermass[0];
|
||||
|
||||
|
||||
//Generating Random Energy
|
||||
do {
|
||||
Ee=G4UniformRand();
|
||||
do{
|
||||
x=xmax*G4UniformRand();
|
||||
gam=G4UniformRand();
|
||||
}while (gam >x*(1.-x));
|
||||
Ene=x;
|
||||
} while ( Ene < (1.-Ee));
|
||||
G4double Enm=(2.-Ee-Ene);
|
||||
|
||||
|
||||
//initialisation of rotation parameters
|
||||
|
||||
G4double costheta,sintheta,rphi,rtheta,rpsi;
|
||||
costheta= 1.-2./Ee-2./Ene+2./Ene/Ee;
|
||||
sintheta=std::sqrt(1.-costheta*costheta);
|
||||
|
||||
|
||||
rphi=twopi*G4UniformRand()*rad;
|
||||
rtheta=(std::acos(2.*G4UniformRand()-1.));
|
||||
rpsi=twopi*G4UniformRand()*rad;
|
||||
|
||||
G4RotationMatrix rot;
|
||||
rot.set(rphi,rtheta,rpsi);
|
||||
|
||||
//electron 0
|
||||
daughtermomentum[0]=std::sqrt(Ee*Ee*EMax*EMax+2.0*Ee*EMax * daughtermass[0]);
|
||||
G4ThreeVector direction0(0.0,0.0,1.0);
|
||||
|
||||
direction0 *= rot;
|
||||
|
||||
G4DynamicParticle * daughterparticle = new G4DynamicParticle ( daughters[0], direction0 * daughtermomentum[0]);
|
||||
|
||||
products->PushProducts(daughterparticle);
|
||||
|
||||
//electronic neutrino 1
|
||||
|
||||
daughtermomentum[1]=std::sqrt(Ene*Ene*EMax*EMax+2.0*Ene*EMax * daughtermass[1]);
|
||||
G4ThreeVector direction1(sintheta,0.0,costheta);
|
||||
|
||||
direction1 *= rot;
|
||||
|
||||
G4DynamicParticle * daughterparticle1 = new G4DynamicParticle ( daughters[1], direction1 * daughtermomentum[1]);
|
||||
products->PushProducts(daughterparticle1);
|
||||
|
||||
//muonic neutrino 2
|
||||
|
||||
daughtermomentum[2]=std::sqrt(Enm*Enm*EMax*EMax +2.0*Enm*EMax*daughtermass[2]);
|
||||
G4ThreeVector direction2(-Ene/Enm*sintheta,0,-Ee/Enm-Ene/Enm*costheta);
|
||||
|
||||
direction2 *= rot;
|
||||
|
||||
G4DynamicParticle * daughterparticle2 = new G4DynamicParticle ( daughters[2],
|
||||
direction2 * daughtermomentum[2]);
|
||||
products->PushProducts(daughterparticle2);
|
||||
|
||||
|
||||
|
||||
|
||||
// output message
|
||||
#ifdef G4VERBOSE
|
||||
if (GetVerboseLevel()>1) {
|
||||
G4cout << "MuDecayChannel::DecayIt ";
|
||||
G4cout << " create decay products in rest frame " <<G4endl;
|
||||
products->DumpInfo();
|
||||
}
|
||||
#endif
|
||||
return products;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
266
geant4/LEMuSR/src/MuDecayChannelWithSpin.cc
Normal file
266
geant4/LEMuSR/src/MuDecayChannelWithSpin.cc
Normal file
@ -0,0 +1,266 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
// GEANT 4 class header file
|
||||
//
|
||||
// History:
|
||||
// 17 August 2004 P.Gumplinger and T.MacPhail
|
||||
// samples Michel spectrum including 1st order
|
||||
// radiative corrections
|
||||
// Reference: Florian Scheck "Muon Physics", in Physics Reports
|
||||
// (Review Section of Physics Letters) 44, No. 4 (1978)
|
||||
// 187-248. North-Holland Publishing Company, Amsterdam
|
||||
// at page 210 cc.
|
||||
//
|
||||
// W.E. Fisher and F. Scheck, Nucl. Phys. B83 (1974) 25.
|
||||
//
|
||||
// ------------------------------------------------------------
|
||||
//
|
||||
#include "MuDecayChannelWithSpin.hh"
|
||||
|
||||
#include "Randomize.hh"
|
||||
#include "G4DecayProducts.hh"
|
||||
#include "G4LorentzVector.hh"
|
||||
|
||||
MuDecayChannelWithSpin::MuDecayChannelWithSpin(const G4String& theParentName,
|
||||
G4double theBR)
|
||||
: MuDecayChannel(theParentName,theBR)
|
||||
{
|
||||
}
|
||||
|
||||
MuDecayChannelWithSpin::~MuDecayChannelWithSpin()
|
||||
{
|
||||
}
|
||||
|
||||
G4DecayProducts *MuDecayChannelWithSpin::DecayIt(G4double)
|
||||
{
|
||||
// This version assumes V-A coupling with 1st order radiative correctons,
|
||||
// the standard model Michel parameter values, but
|
||||
// gives incorrect energy spectrum for neutrinos
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if (GetVerboseLevel()>1) G4cout << "MuDecayChannelWithSpin::DecayIt ";
|
||||
#endif
|
||||
|
||||
if (parent == 0) FillParent();
|
||||
if (daughters == 0) FillDaughters();
|
||||
|
||||
// parent mass
|
||||
G4double parentmass = parent->GetPDGMass();
|
||||
|
||||
EMMU = parentmass;
|
||||
|
||||
//daughters'mass
|
||||
G4double daughtermass[3];
|
||||
G4double sumofdaughtermass = 0.0;
|
||||
for (G4int index=0; index<3; index++){
|
||||
daughtermass[index] = daughters[index]->GetPDGMass();
|
||||
sumofdaughtermass += daughtermass[index];
|
||||
}
|
||||
|
||||
EMASS = daughtermass[0];
|
||||
|
||||
//create parent G4DynamicParticle at rest
|
||||
G4ThreeVector dummy;
|
||||
G4DynamicParticle * parentparticle = new G4DynamicParticle( parent, dummy, 0.0);
|
||||
//create G4Decayproducts
|
||||
G4DecayProducts *products = new G4DecayProducts(*parentparticle);
|
||||
delete parentparticle;
|
||||
|
||||
// calcurate electron energy
|
||||
|
||||
G4double michel_rho = 0.75; //Standard Model Michel rho
|
||||
G4double michel_delta = 0.75; //Standard Model Michel delta
|
||||
G4double michel_xsi = 1.00; //Standard Model Michel xsi
|
||||
G4double michel_eta = 0.00; //Standard Model eta
|
||||
|
||||
G4double rndm, x, ctheta;
|
||||
|
||||
G4double FG;
|
||||
G4double FG_max = 2.00;
|
||||
|
||||
G4double W_mue = (EMMU*EMMU+EMASS*EMASS)/(2.*EMMU);
|
||||
G4double x0 = EMASS/W_mue;
|
||||
|
||||
G4double x0_squared = x0*x0;
|
||||
|
||||
// ***************************************************
|
||||
// x0 <= x <= 1. and -1 <= y <= 1
|
||||
//
|
||||
// F(x,y) = f(x)*g(x,y); g(x,y) = 1.+g(x)*y
|
||||
// ***************************************************
|
||||
|
||||
// ***** sampling F(x,y) directly (brute force) *****
|
||||
|
||||
do{
|
||||
|
||||
// Sample the positron energy by sampling from F
|
||||
|
||||
rndm = G4UniformRand();
|
||||
|
||||
x = x0 + rndm*(1.-x0);
|
||||
|
||||
G4double x_squared = x*x;
|
||||
|
||||
G4double F_IS, F_AS, G_IS, G_AS;
|
||||
|
||||
F_IS = 1./6.*(-2.*x_squared+3.*x-x0_squared);
|
||||
F_AS = 1./6.*std::sqrt(x_squared-x0_squared)*(2.*x-2.+std::sqrt(1.-x0_squared));
|
||||
|
||||
G_IS = 2./9.*(michel_rho-0.75)*(4.*x_squared-3.*x-x0_squared);
|
||||
G_IS = G_IS + michel_eta*(1.-x)*x0;
|
||||
|
||||
G_AS = 3.*(michel_xsi-1.)*(1.-x);
|
||||
G_AS = G_AS+2.*(michel_xsi*michel_delta-0.75)*(4.*x-4.+std::sqrt(1.-x0_squared));
|
||||
G_AS = 1./9.*std::sqrt(x_squared-x0_squared)*G_AS;
|
||||
|
||||
F_IS = F_IS + G_IS;
|
||||
F_AS = F_AS + G_AS;
|
||||
|
||||
// *** Radiative Corrections ***
|
||||
|
||||
G4double R_IS = F_c(x,x0);
|
||||
|
||||
G4double F = 6.*F_IS + R_IS/std::sqrt(x_squared-x0_squared);
|
||||
|
||||
// *** Radiative Corrections ***
|
||||
|
||||
G4double R_AS = F_theta(x,x0);
|
||||
|
||||
rndm = G4UniformRand();
|
||||
|
||||
ctheta = 2.*rndm-1.;
|
||||
|
||||
G4double G = 6.*F_AS - R_AS/std::sqrt(x_squared-x0_squared);
|
||||
|
||||
FG = std::sqrt(x_squared-x0_squared)*F*(1.+(G/F)*ctheta);
|
||||
|
||||
if(FG>FG_max){
|
||||
G4cout<<"***Problem in Muon Decay *** : FG > FG_max"<<G4endl;
|
||||
FG_max = FG;
|
||||
}
|
||||
|
||||
rndm = G4UniformRand();
|
||||
|
||||
}while(FG<rndm*FG_max);
|
||||
|
||||
G4double energy = x * W_mue;
|
||||
|
||||
rndm = G4UniformRand();
|
||||
|
||||
G4double phi = twopi * rndm;
|
||||
|
||||
if(energy < EMASS) energy = EMASS;
|
||||
|
||||
// calculate daughter momentum
|
||||
G4double daughtermomentum[3];
|
||||
|
||||
daughtermomentum[0] = std::sqrt(energy*energy - EMASS*EMASS);
|
||||
|
||||
G4double stheta = std::sqrt(1.-ctheta*ctheta);
|
||||
G4double cphi = std::cos(phi);
|
||||
G4double sphi = std::sin(phi);
|
||||
|
||||
//Coordinates of the decay positron with respect to the muon spin
|
||||
|
||||
G4double px = stheta*cphi;
|
||||
G4double py = stheta*sphi;
|
||||
G4double pz = ctheta;
|
||||
|
||||
G4ThreeVector direction0(px,py,pz);
|
||||
|
||||
direction0.rotateUz(parent_polarization);
|
||||
|
||||
G4DynamicParticle * daughterparticle0
|
||||
= new G4DynamicParticle( daughters[0], daughtermomentum[0]*direction0);
|
||||
|
||||
products->PushProducts(daughterparticle0);
|
||||
|
||||
|
||||
// daughter 1 ,2 (neutrinos)
|
||||
// create neutrinos in the C.M frame of two neutrinos
|
||||
G4double energy2 = parentmass*(1.0 - x/2.0);
|
||||
G4double vmass = std::sqrt((energy2-daughtermomentum[0])*(energy2+daughtermomentum[0]));
|
||||
G4double beta = -1.0*daughtermomentum[0]/energy2;
|
||||
G4double costhetan = 2.*G4UniformRand()-1.0;
|
||||
G4double sinthetan = std::sqrt((1.0-costhetan)*(1.0+costhetan));
|
||||
G4double phin = twopi*G4UniformRand()*rad;
|
||||
G4double sinphin = std::sin(phin);
|
||||
G4double cosphin = std::cos(phin);
|
||||
|
||||
G4ThreeVector direction1(sinthetan*cosphin,sinthetan*sinphin,costhetan);
|
||||
G4DynamicParticle * daughterparticle1
|
||||
= new G4DynamicParticle( daughters[1], direction1*(vmass/2.));
|
||||
G4DynamicParticle * daughterparticle2
|
||||
= new G4DynamicParticle( daughters[2], direction1*(-1.0*vmass/2.));
|
||||
|
||||
// boost to the muon rest frame
|
||||
G4LorentzVector p4;
|
||||
p4 = daughterparticle1->Get4Momentum();
|
||||
p4.boost( direction0.x()*beta, direction0.y()*beta, direction0.z()*beta);
|
||||
daughterparticle1->Set4Momentum(p4);
|
||||
p4 = daughterparticle2->Get4Momentum();
|
||||
p4.boost( direction0.x()*beta, direction0.y()*beta, direction0.z()*beta);
|
||||
daughterparticle2->Set4Momentum(p4);
|
||||
products->PushProducts(daughterparticle1);
|
||||
products->PushProducts(daughterparticle2);
|
||||
daughtermomentum[1] = daughterparticle1->GetTotalMomentum();
|
||||
daughtermomentum[2] = daughterparticle2->GetTotalMomentum();
|
||||
|
||||
// output message
|
||||
#ifdef G4VERBOSE
|
||||
if (GetVerboseLevel()>1) {
|
||||
G4cout << "MuDecayChannelWithSpin::DecayIt ";
|
||||
G4cout << " create decay products in rest frame " <<G4endl;
|
||||
products->DumpInfo();
|
||||
}
|
||||
#endif
|
||||
return products;
|
||||
}
|
||||
|
||||
G4double MuDecayChannelWithSpin::R_c(G4double x){
|
||||
|
||||
G4int n_max = (int)(100.*x);
|
||||
|
||||
if(n_max<10)n_max=10;
|
||||
|
||||
G4double L2 = 0.0;
|
||||
|
||||
for(G4int n=1; n<=n_max; n++){
|
||||
L2 += std::pow(x,n)/(n*n);
|
||||
}
|
||||
|
||||
G4double omega = std::log(EMMU/EMASS);
|
||||
|
||||
G4double r_c;
|
||||
|
||||
r_c = 2.*L2-(pi*pi/3.)-2.;
|
||||
r_c = r_c + omega * (1.5+2.*std::log((1.-x)/x));
|
||||
r_c = r_c - std::log(x)*(2.*std::log(x)-1.);
|
||||
r_c = r_c + (3.*std::log(x)-1.-1./x)*std::log(1.-x);
|
||||
|
||||
return r_c;
|
||||
}
|
341
geant4/LEMuSR/src/lem4Axial2DElField.cc
Normal file
341
geant4/LEMuSR/src/lem4Axial2DElField.cc
Normal file
@ -0,0 +1,341 @@
|
||||
#include "lem4Axial2DElField.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
//#include "lem4Parameters.hh"
|
||||
|
||||
lem4Axial2DElField::lem4Axial2DElField(const char* filename, G4double fieldValue, G4double lenUnit, G4double fieldNormalisation, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter) : F04ElementField(positionOfTheCenter, logVolume),
|
||||
ffieldValue(fieldValue)
|
||||
|
||||
//lem4Axial2DElField::lem4Axial2DElField(const G4String filename, double fieldValue, double lenUnit, double fieldNormalisation, double offset) : ffieldValue(fieldValue/1000.0), zOffset(offset), invertR(false), invertZ(false)
|
||||
{
|
||||
// double lenUnit = decimeter; = 100 // Base unit mm
|
||||
// double fieldUnit = kV; = 0.001 // Base unit MV
|
||||
// double fieldNorm = 0.00001 = 1E-5 // = 0.001/100
|
||||
G4cout << "\n-----------------------------------------------------------"
|
||||
<< "\n Electric field"
|
||||
<< "\n-----------------------------------------------------------"
|
||||
<< G4endl;
|
||||
// G4cout << " kilovolt = "<< kilovolt << G4endl; // = 1e-3 MV - default G4 unit
|
||||
///G4cout << "\n Potential set to "<< fieldValue/1000.0/kilovolt << " kV"<< G4endl;
|
||||
G4cout << "\n Potential set to "<< fieldValue/kilovolt << " kV"<< G4endl;
|
||||
G4cout << "\n ---> " "Reading 2D E-field map from " << filename << " ... " << G4endl;
|
||||
std::ifstream file(filename); // Open the file for reading
|
||||
|
||||
// Start reading file content
|
||||
char buffer[256];
|
||||
|
||||
// Read table dimensions first
|
||||
file >> nr >> nz; // r - radial, z - longitudinal coordinate
|
||||
|
||||
G4cout << " 2D field table dimensions (r-z): ["
|
||||
<< nr << ", " << nz << "] "
|
||||
<< G4endl;
|
||||
|
||||
// Set up storage space for table
|
||||
rField.resize(nr);
|
||||
zField.resize(nr);
|
||||
int ir, iz;
|
||||
|
||||
for (ir = 0; ir < nr; ir++) {
|
||||
rField[ir].resize(nz);
|
||||
zField[ir].resize(nz);
|
||||
}
|
||||
|
||||
// Ignore header information. All lines whose first character
|
||||
// is '%' are considered to be part of the header.
|
||||
do {
|
||||
file.getline(buffer, 256);
|
||||
} while (buffer[0] != '%');
|
||||
|
||||
// Read in the data: [r, z, Er, Ez]
|
||||
double rval, zval, er, ez;
|
||||
for (ir = 0; ir < nr; ir++) {
|
||||
for (iz = 0; iz < nz; iz++) {
|
||||
file >> rval >> zval >> er >> ez;
|
||||
if (ir == 0 && iz == 0) {
|
||||
minr = rval * lenUnit;
|
||||
minz = zval * lenUnit;
|
||||
}
|
||||
rField[ir][iz] = er*fieldNormalisation;
|
||||
zField[ir][iz] = ez*fieldNormalisation;
|
||||
}
|
||||
}
|
||||
G4cout << " Normalisation coeff.: " << fieldNormalisation << G4endl;
|
||||
file.close();
|
||||
|
||||
maxr = rval * lenUnit;
|
||||
maxz = zval * lenUnit;
|
||||
|
||||
G4cout << "\n ---> ... done reading (assumed order: r, z, Er, Ez)." << G4endl;
|
||||
G4cout << "\n ---> Min values r, z: "
|
||||
<< minr/cm << " " << minz/cm << " cm "
|
||||
<< "\n ---> Max values r, z: "
|
||||
<< maxr/cm << " " << maxz/cm << " cm " << G4endl;
|
||||
|
||||
// Should really check that the limits are not the wrong way around.
|
||||
if (maxr < minr) {Invert("x");} ///{std::swap(maxr, minr); invertR = true;}
|
||||
if (maxz < minz) {Invert("z");} ///{std::swap(maxz, minz); invertZ = true;}
|
||||
if (maxr < minr || maxz < minz){ ///(invertR == true || invertZ == true){
|
||||
G4cout << "\n After reordering:"
|
||||
<< "\n ---> Min values r, z: "
|
||||
<< minr/cm << " " << minz/cm << " cm "
|
||||
<< "\n ---> Max values r, z: "
|
||||
<< maxr/cm << " " << maxz/cm << " cm " << G4endl;
|
||||
}
|
||||
|
||||
dr = maxr - minr;
|
||||
dz = maxz - minz;
|
||||
|
||||
G4cout << " ---> Range of values: "
|
||||
<< dr/cm << " cm (in r) and " << dz/cm << " cm (in z)."
|
||||
<< "\n-----------------------------------------------------------\n" << G4endl;
|
||||
}
|
||||
|
||||
|
||||
///lem4Axial2DElField::~lem4Axial2DElField() /// Made virtual!
|
||||
///{
|
||||
/// delete [] &rField ;
|
||||
/// delete [] &zField ;
|
||||
///}
|
||||
|
||||
|
||||
void lem4Axial2DElField::addFieldValue(const G4double point[4],
|
||||
G4double *field) const
|
||||
{
|
||||
G4double B[3]; // Field value obtained from the field table
|
||||
///TS
|
||||
///G4cout<<"TTfileTT Global coord. ("<<point[0]/mm<<", "<<point[1]/mm<<", "<<point[2]/mm<<")."<<G4endl;
|
||||
G4ThreeVector global(point[0],point[1],point[2]);
|
||||
G4ThreeVector local;
|
||||
|
||||
local = global2local.TransformPoint(global);
|
||||
///TS
|
||||
///G4cout<<"TTfileTT Local coord. ("<<local[0]/mm<<", "<<local[1]/mm<<", "<<local[2]/mm<<")."<<G4endl;
|
||||
///G4cout<<"The LOGICAL volume is named "<<lvolume->GetName()<<G4endl;
|
||||
|
||||
double r = sqrt(local.x()*local.x()+local.y()*local.y());
|
||||
double z = fabs(local.z());
|
||||
double z_sign = (local.z()>0) ? 1.:-1.;
|
||||
|
||||
// Check that the point is within the defined region
|
||||
if ( r < maxr && z < maxz ) {
|
||||
// Relative point position within region, normalized to [0,1].
|
||||
double rfraction = (r - minr) / dr;
|
||||
double zfraction = (z - minz) / dz;
|
||||
|
||||
// Need addresses of these to pass to modf below.
|
||||
// modf uses its second argument as an OUTPUT argument.
|
||||
double rdindex, zdindex;
|
||||
|
||||
// Position of the point within the cuboid defined by the
|
||||
// nearest surrounding tabulated points
|
||||
double rlocal = ( modf(rfraction*(nr-1), &rdindex));
|
||||
double zlocal = ( modf(zfraction*(nz-1), &zdindex));
|
||||
|
||||
// The indices of the nearest tabulated point whose coordinates
|
||||
// are all less than those of the given point
|
||||
int rindex = static_cast<int>(rdindex);
|
||||
int zindex = static_cast<int>(zdindex);
|
||||
|
||||
//cks The following check is necessary - even though xindex and zindex should never be out of range,
|
||||
// it may happen (due to some rounding error ?). It is better to leave the check here.
|
||||
if ((rindex<0)||(rindex>(nr-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: rindex out of range! rindex="<<rindex<<" r="<<r<<" rfraction="<<rfraction<<std::endl;
|
||||
if (rindex<0) rindex=0;
|
||||
else rindex=nr-2;
|
||||
}
|
||||
if ((zindex<0)||(zindex>(nz-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: zindex out of range! zindex="<<zindex<<" z="<<z<<" zfraction="<<zfraction<<std::endl;
|
||||
if (zindex<0) zindex=0;
|
||||
else zindex=nz-2;
|
||||
}
|
||||
|
||||
// G4cout<<"xField["<<xindex<<"]["<<zindex<<"]="<<xField[xindex ][zindex ]<<G4endl;
|
||||
// G4cout<<"zField["<<xindex<<"]["<<zindex<<"]="<<zField[xindex ][zindex ]<<G4endl;
|
||||
|
||||
// Interpolate between the neighbouring points
|
||||
double Bfield_R =
|
||||
rField[rindex ][zindex ] * (1-rlocal) * (1-zlocal) +
|
||||
rField[rindex ][zindex+1] * (1-rlocal) * zlocal +
|
||||
rField[rindex+1][zindex ] * rlocal * (1-zlocal) +
|
||||
rField[rindex+1][zindex+1] * rlocal * zlocal ;
|
||||
B[0] = (r>0) ? Bfield_R * (local.x() /r) : 0.;
|
||||
B[1] = (r>0) ? Bfield_R * (local.y() /r) : 0.;
|
||||
B[2] =
|
||||
zField[rindex ][zindex ] * (1-rlocal) * (1-zlocal) +
|
||||
zField[rindex ][zindex+1] * (1-rlocal) * zlocal +
|
||||
zField[rindex+1][zindex ] * rlocal * (1-zlocal) +
|
||||
zField[rindex+1][zindex+1] * rlocal * zlocal ;
|
||||
|
||||
B[0] *= ffieldValue * z_sign;
|
||||
B[1] *= ffieldValue * z_sign;
|
||||
B[2] *= ffieldValue;
|
||||
|
||||
G4ThreeVector finalField(B[0],B[1],B[2]);
|
||||
finalField = global2local.Inverse().TransformAxis(finalField);
|
||||
|
||||
field[0] += finalField.x();
|
||||
field[1] += finalField.y();
|
||||
field[2] += finalField.z();
|
||||
}
|
||||
// G4cout<<"Kamil: Field: ("<<field[0]/tesla<<","<<field[1]/tesla<<","<<field[2]/tesla<<")"<<G4endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* OLD IMPLEMENTATION - CHANGED WITH GLOBALFIELD! TS
|
||||
void lem4Axial2DElField::GetFieldValue(const double point[4], double *Efield) const
|
||||
{
|
||||
// musrEventAction* myEventAction= musrEventAction::GetInstance();
|
||||
// G4int evNr=myEventAction->GetLatestEventNr();
|
||||
// G4int evNrKriz=6795; //457; //14250
|
||||
// if (evNr==evNrKriz) {
|
||||
// std::cout<<"evNr="<<evNr<<std::endl;
|
||||
// printf ("for point= %f %f %f B= %10.10f %10.10f %10.10f \n",
|
||||
// point[0],point[1],point[2],Bfield[0]/tesla,Bfield[1]/tesla,Bfield[2]/tesla);
|
||||
// }
|
||||
Efield[0]=0.; Efield[1]=0.; Efield[2]=0.;
|
||||
|
||||
double r = sqrt(point[0]*point[0]+point[1]*point[1]);
|
||||
//Apply a fixed offset (in mm) to the z - coordinate.
|
||||
double rel_z = (point[2] - zOffset)/mm;
|
||||
double z = fabs(rel_z);
|
||||
double z_sign = (rel_z>0) ? 1.:-1.;
|
||||
//if (evNr==evNrKriz) std::cout<<"r ="<<r<<" maxr="<<maxr<<std::endl;
|
||||
|
||||
#ifdef DEBUG_INTERPOLATING_FIELD
|
||||
double dst = sqrt(point[0]*point[0] + point[1]*point[1]);
|
||||
G4cout<<"POSITION: "<< G4BestUnit(point[0], "Length")<<" "<< G4BestUnit(point[1], "Length") <<" "<< G4BestUnit(dst, "Length") <<" "<< G4BestUnit(point[2], "Length") <<G4endl;
|
||||
G4cout<<"POSITION in field map: "<< G4BestUnit(r, "Length") <<" "<< G4BestUnit(z, "Length")<<G4endl;
|
||||
#endif
|
||||
|
||||
|
||||
// Check that the point is within the defined region
|
||||
if ( r<maxr && z<maxz ) {
|
||||
// if (evNr>evNrKriz) std::cout<<"bol som tu"<<std::endl;
|
||||
|
||||
// Position of given point within region, normalized to the range
|
||||
// [0,1]
|
||||
double rfraction = (r - minr) / dr;
|
||||
double zfraction = (z - minz) / dz;
|
||||
|
||||
if (invertR) { rfraction = 1 - rfraction;}
|
||||
if (invertZ) { zfraction = 1 - zfraction;}
|
||||
// Need addresses of these to pass to modf below.
|
||||
// modf uses its second argument as an OUTPUT argument.
|
||||
double rdindex, zdindex;
|
||||
|
||||
// Position of the point within the cuboid defined by the
|
||||
// nearest surrounding tabulated points
|
||||
double rlocal = ( modf(rfraction*(nr-1), &rdindex));
|
||||
double zlocal = ( modf(zfraction*(nz-1), &zdindex));
|
||||
|
||||
// The indices of the nearest tabulated point whose coordinates
|
||||
// are all less than those of the given point
|
||||
int rindex = static_cast<int>(rdindex);
|
||||
int zindex = static_cast<int>(zdindex);
|
||||
|
||||
//cks The following check is necessary - even though xindex and zindex should never be out of range,
|
||||
// it may happen (due to some rounding error ?). It is better to leave the check here.
|
||||
if ((rindex<0)||(rindex>(nr-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: rindex out of range! rindex="<<rindex<<" r="<<r<<" rfraction="<<rfraction<<std::endl;
|
||||
if (rindex<0) rindex=0;
|
||||
else rindex=nr-2;
|
||||
}
|
||||
if ((zindex<0)||(zindex>(nz-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: zindex out of range! zindex="<<zindex<<" z="<<z<<" zfraction="<<zfraction<<std::endl;
|
||||
if (zindex<0) zindex=0;
|
||||
else zindex=nz-2;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_INTERPOLATING_FIELD
|
||||
G4cout << "Local r, z: " << rlocal << " " << zlocal << G4endl;
|
||||
G4cout << "Index r, z: " << rindex << " " << zindex << G4endl;
|
||||
#endif
|
||||
|
||||
// Interpolate between the neighbouring points
|
||||
double Efield_R =
|
||||
rField[rindex ][zindex ] * (1-rlocal) * (1-zlocal) +
|
||||
rField[rindex ][zindex+1] * (1-rlocal) * zlocal +
|
||||
rField[rindex+1][zindex ] * rlocal * (1-zlocal) +
|
||||
rField[rindex+1][zindex+1] * rlocal * zlocal ;
|
||||
Efield[0] = (r>0) ? Efield_R * (point[0]/r) : 0.;
|
||||
Efield[1] = (r>0) ? Efield_R * (point[1]/r) : 0.;
|
||||
Efield[2] =
|
||||
zField[rindex ][zindex ] * (1-rlocal) * (1-zlocal) +
|
||||
zField[rindex ][zindex+1] * (1-rlocal) * zlocal +
|
||||
zField[rindex+1][zindex ] * rlocal * (1-zlocal) +
|
||||
zField[rindex+1][zindex+1] * rlocal * zlocal ;
|
||||
// ATTENTION if dealing with MAGNETIC FIELDS reverse x, y and z signs!!
|
||||
Efield[0] = Efield[0] * ffieldValue; // * z_sign;
|
||||
Efield[1] = Efield[1] * ffieldValue; // * z_sign;
|
||||
Efield[2] = Efield[2] * ffieldValue * z_sign;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Set some small field if field is almost zero (to avoid internal problems of Geant).
|
||||
if (sqrt(Efield[0]*Efield[0]+Efield[1]*Efield[1]+Efield[2]*Efield[2])<1.0E-12*volt) {
|
||||
// if (evNr>evNrKriz) std::cout<<"bol som tuna"<<std::endl;
|
||||
// Bfield[0] = 0.0;
|
||||
// Bfield[1] = 0.0;
|
||||
// Bfield[2] = Bfield[2] + 0.00001*tesla;
|
||||
#ifdef DEBUG_INTERPOLATING_FIELD
|
||||
G4cout<<"Zero field case"<<G4endl;
|
||||
#endif
|
||||
Efield[2] = 1.0E-12*volt;
|
||||
}
|
||||
// Print the field (for debugging)
|
||||
// if ((point[2]>-1*cm)&&(point[2]<1*cm)) {
|
||||
// printf ("for point= %f %f %f B= %10.10f %10.10f %10.10f \n",
|
||||
// point[0],point[1],point[2],Bfield[0]/tesla,Bfield[1]/tesla,Bfield[2]/tesla);
|
||||
// }
|
||||
// if (evNr>evNrKriz) std::cout<<"this is the end"<<std::endl;
|
||||
|
||||
#ifdef DEBUG_INTERPOLATING_FIELD
|
||||
//G4cout << " Volt/meter factor = "<< volt/meter << G4endl; // = 1e-9
|
||||
G4cout<<"Field Value " << G4BestUnit(Efield[0]*meter,"Electric potential") <<"/m " <<Efield[1]/volt*meter <<" V/m "<< Efield[2]/volt*meter <<" V/m " <<G4endl;
|
||||
G4cout<<"FieldVal " << ffieldValue/kilovolt << G4endl;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
G4double lem4Axial2DElField::GetNominalFieldValue() {
|
||||
return ffieldValue;
|
||||
}
|
||||
|
||||
void lem4Axial2DElField::SetNominalFieldValue(G4double newFieldValue) {
|
||||
// Rescale the EM field to account for the new applied field value
|
||||
ffieldValue=newFieldValue;
|
||||
G4cout<<"lem4Axial2DElField.cc: ffieldValue changed to = "<< ffieldValue/kilovolt<<" kV."<<G4endl;
|
||||
}
|
||||
|
||||
void lem4Axial2DElField::Invert(const char* indexToInvert) {
|
||||
// This function inverts the field table indices along a given axis (r or z).
|
||||
// It should be called whenever x or z coordinates in the initial field table
|
||||
// are ordered in a decreasing order.
|
||||
std::vector< std::vector< double > > rFieldTemp(rField);
|
||||
std::vector< std::vector< double > > zFieldTemp(zField);
|
||||
G4bool invertR=false;
|
||||
G4bool invertZ=false;
|
||||
|
||||
G4cout<<"Check that the lem4Axial2DElField::Invert() function works properly!"<<G4endl;
|
||||
G4cout<<"It has not been tested yet!"<<G4endl;
|
||||
|
||||
if (strcmp(indexToInvert,"r")==0) {invertR=true; std::swap(maxr, minr);}
|
||||
if (strcmp(indexToInvert,"z")==0) {invertZ=true; std::swap(maxz, minz);}
|
||||
|
||||
for (int ir=0; ir<nr; ir++) {
|
||||
for (int iz=0; iz<nz; iz++) {
|
||||
if (invertR) {
|
||||
rField[ir][iz] = rFieldTemp[nr-1-ir][iz];
|
||||
}
|
||||
else if(invertZ) {
|
||||
rField[ir][iz] = rFieldTemp[ir][nz-1-iz];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1492
geant4/LEMuSR/src/lem4DetectorConstruction.cc
Normal file
1492
geant4/LEMuSR/src/lem4DetectorConstruction.cc
Normal file
File diff suppressed because it is too large
Load Diff
210
geant4/LEMuSR/src/lem4DetectorMessenger.cc
Normal file
210
geant4/LEMuSR/src/lem4DetectorMessenger.cc
Normal file
@ -0,0 +1,210 @@
|
||||
#include "lem4DetectorMessenger.hh"
|
||||
#include "lem4DetectorConstruction.hh"
|
||||
#include "G4UIdirectory.hh"
|
||||
#include "G4UIcmdWithAString.hh"
|
||||
#include "G4UIcmdWithADoubleAndUnit.hh"
|
||||
#include "G4UIcmdWithAnInteger.hh"
|
||||
#include "G4UIcmdWithoutParameter.hh"
|
||||
#include "G4UIcmdWith3Vector.hh"
|
||||
#include "G4UIcmdWith3VectorAndUnit.hh"
|
||||
|
||||
#include "G4RunManager.hh" //cks included in order to be able to change run ID
|
||||
#include "Randomize.hh" //cks included in order to initialise the random nr. generator by time
|
||||
#include <time.h> //cks -----------------------------||-------------------------------
|
||||
#include "lem4EventAction.hh" // cks needed for the initialisation of the random nr. generator by event nr.
|
||||
//#include <fstream>
|
||||
//#include <vector>
|
||||
#include "globals.hh"
|
||||
//#include "lem4Parameters.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
lem4DetectorMessenger::lem4DetectorMessenger(lem4DetectorConstruction* myDet)
|
||||
:myDetector(myDet)
|
||||
{
|
||||
lem4Dir = new G4UIdirectory("/lem4/");
|
||||
lem4Dir->SetGuidance("UI commands specific to this example.");
|
||||
|
||||
CommandCmd = new G4UIcmdWithAString("/lem4/command",this);
|
||||
CommandCmd->SetGuidance("This command will be used for the detector construction (and ignored by the default messenger.");
|
||||
// CommandCmd->SetParameterName("choice",false);
|
||||
CommandCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
runDir = new G4UIdirectory("/lem4/run/");
|
||||
runDir->SetGuidance("lem4 run control");
|
||||
|
||||
RunIDSetCmd = new G4UIcmdWithAnInteger("/lem4/run/runID",this);
|
||||
RunIDSetCmd->SetGuidance("Set the run number");
|
||||
RunIDSetCmd->SetParameterName("something",false);
|
||||
RunIDSetCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
RandomOptionCmd = new G4UIcmdWithAnInteger("/lem4/run/randomOption",this);
|
||||
RandomOptionCmd->SetGuidance("Specify the random number generator initialisation");
|
||||
RandomOptionCmd->SetGuidance(" 0 ... no initialisation (default)");
|
||||
RandomOptionCmd->SetGuidance(" 1 ... use actual computer time to initialise now");
|
||||
RandomOptionCmd->SetGuidance(" 2 ... use event number to initialise at the beginning of each event");
|
||||
RandomOptionCmd->SetGuidance(" 3 ... read in the random no. initial values for each event from a file");
|
||||
RandomOptionCmd->SetParameterName("randomOpt",false);
|
||||
RandomOptionCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
HowOftenToPrintEventCmd = new G4UIcmdWithAnInteger("/lem4/run/howOftenToPrintEvent",this);
|
||||
HowOftenToPrintEventCmd->SetGuidance("Each n-th event will be notified. Set _n_ by this command.");
|
||||
HowOftenToPrintEventCmd->SetParameterName("howOftenToPrintEv",false);
|
||||
HowOftenToPrintEventCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
detDir = new G4UIdirectory("/lem4/det/");
|
||||
detDir->SetGuidance("detector control.");
|
||||
|
||||
// WhichProcessesCmd = new G4UIcmdWithAString("/lem4/det/processes",this);
|
||||
// WhichProcessesCmd ->SetGuidance("Select Standard, Low Energy or Penelope processes");
|
||||
// WhichProcessesCmd ->SetParameterName("mes_processes",false);
|
||||
// WhichProcessesCmd ->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
UpdateCmd = new G4UIcmdWithoutParameter("/lem4/det/update",this);
|
||||
UpdateCmd->SetGuidance("Update calorimeter geometry.");
|
||||
UpdateCmd->SetGuidance("This command MUST be applied before \"beamOn\" ");
|
||||
UpdateCmd->SetGuidance("if you changed geometrical value(s).");
|
||||
UpdateCmd->AvailableForStates(G4State_Idle);
|
||||
|
||||
// FieldCmd = new G4UIcmdWithADoubleAndUnit("/lem4/det/setField",this);
|
||||
// FieldCmd->SetGuidance("Define magnetic field.");
|
||||
// FieldCmd->SetGuidance("Magnetic field will be in Z direction.");
|
||||
// FieldCmd->SetParameterName("Bz",false);
|
||||
// FieldCmd->SetUnitCategory("Magnetic flux density");
|
||||
// FieldCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
UFieldCmd = new G4UIcmdWithADoubleAndUnit("/lem4/det/setUniformField",this);
|
||||
UFieldCmd->SetGuidance("Define uniform magnetic field.");
|
||||
UFieldCmd->SetGuidance("Magnetic field will be in Z direction.");
|
||||
UFieldCmd->SetParameterName("Bz",false);
|
||||
UFieldCmd->SetUnitCategory("Magnetic flux density");
|
||||
UFieldCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
// GFieldCmd = new G4UIcmdWithADoubleAndUnit("/lem4/det/setGaussianField",this);
|
||||
// GFieldCmd = new G4UIcmdWith3VectorAndUnit("/lem4/det/setGaussianField",this);
|
||||
GFieldCmd = new G4UIcmdWith3Vector("/lem4/det/setGaussianField",this);
|
||||
GFieldCmd->SetGuidance("Define gaussian magnetic field: intensity in T, sigma in mm, and a dummy variable.");
|
||||
GFieldCmd->SetGuidance("Magnetic field will be in Z direction.");
|
||||
GFieldCmd->SetParameterName("Bz","sigmaBz","dummy",true,false);
|
||||
// GFieldCmd->SetUnitCategory("Magnetic flux density");
|
||||
GFieldCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
/// UEFieldCmd = new G4UIcmdWithADoubleAndUnit("/lem4/det/setUnifEField",this);
|
||||
/// UEFieldCmd->SetGuidance("Define uniform electric field.");
|
||||
/// UEFieldCmd->SetGuidance("Electric field will be in Z direction.");
|
||||
/// UEFieldCmd->SetParameterName("Ez",false);
|
||||
/// UEFieldCmd->SetUnitCategory("Electric field");
|
||||
/// UEFieldCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4DetectorMessenger::~lem4DetectorMessenger()
|
||||
{
|
||||
// delete WhichProcessesCmd;
|
||||
delete UpdateCmd;
|
||||
delete detDir;
|
||||
delete lem4Dir;
|
||||
delete CommandCmd;
|
||||
// delete FieldCmd;
|
||||
delete UFieldCmd;
|
||||
delete GFieldCmd;
|
||||
/// delete UEFieldCmd;
|
||||
delete RunIDSetCmd;
|
||||
delete RandomOptionCmd;
|
||||
delete HowOftenToPrintEventCmd;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4DetectorMessenger::SetNewValue(G4UIcommand* command,G4String newValue) {
|
||||
|
||||
// if( command == WhichProcessesCmd )
|
||||
// { lem4Parameters* myParameters = lem4Parameters::GetInstance();
|
||||
// lem4Parameters -> SetMyProcesses(newValue); }
|
||||
// lem4Parameters* myParameters = lem4Parameters::GetInstance();
|
||||
// myParameters -> strcnpy(lem4Parameters::myProcesses,newValue,99);
|
||||
// lem4Parameters::myProcesses[99]='\0';
|
||||
|
||||
if( command == UpdateCmd )
|
||||
{ myDetector->UpdateGeometry(); }
|
||||
|
||||
// if( command == FieldCmd )
|
||||
// { myDetector->SetMagField("fieldprofiles/input.dat",FieldCmd->GetNewDoubleValue(newValue));}
|
||||
|
||||
if( command == UFieldCmd )
|
||||
{ myDetector->SetUniformMagField(UFieldCmd->GetNewDoubleValue(newValue));}
|
||||
|
||||
if( command == GFieldCmd )
|
||||
{ myDetector->SetGaussianMagField(GFieldCmd->GetNew3VectorValue(newValue));}
|
||||
|
||||
/// if( command == UEFieldCmd )
|
||||
/// { myDetector->SetUniformElField(UEFieldCmd->GetNewDoubleValue(newValue));}
|
||||
|
||||
if( command == RunIDSetCmd )
|
||||
{ (G4RunManager::GetRunManager())->SetRunIDCounter(RunIDSetCmd->GetNewIntValue(newValue));}
|
||||
|
||||
if( command == RandomOptionCmd )
|
||||
{
|
||||
G4int RandomOption=RandomOptionCmd->GetNewIntValue(newValue);
|
||||
if (RandomOption == 1) {
|
||||
// G4long seed=time(0); //returns time in seconds as an integer
|
||||
// HepRandom::setTheSeed(seed);//changes the seed of the random engine
|
||||
G4cout << "******************************************" << G4endl;
|
||||
G4cout << "*** Random Seed set by the system time ***" << G4endl;
|
||||
G4cout << "******************************************" << G4endl;
|
||||
long seeds[2];
|
||||
time_t systime = time(NULL);
|
||||
seeds[0] = (long) systime;
|
||||
seeds[1] = (long) (systime*G4UniformRand());
|
||||
G4cout << "seed1: " << seeds[0] << "; seed2: " << seeds[1] << G4endl;
|
||||
CLHEP::HepRandom::setTheSeeds(seeds);
|
||||
CLHEP::HepRandom::showEngineStatus();
|
||||
}
|
||||
else if (RandomOption == 2) {
|
||||
G4cout << "*******************************************" << G4endl;
|
||||
G4cout << "*** Random Seed set by the event number ***" << G4endl;
|
||||
G4cout << "*******************************************" << G4endl;
|
||||
lem4EventAction::setRandomNrSeedAccordingEventNr=1;
|
||||
// lem4EventAction::setMyEventNr(70);
|
||||
}
|
||||
else if (RandomOption == 3) {
|
||||
G4cout << "*******************************************" << G4endl;
|
||||
G4cout << "*** Random Seed set from external file ***" << G4endl;
|
||||
G4cout << "*******************************************" << G4endl;
|
||||
lem4EventAction::setRandomNrSeedFromFile=1;
|
||||
|
||||
std::ifstream indata;
|
||||
int num;
|
||||
|
||||
indata.open("randomNum.dat"); // opens the file
|
||||
if(!indata) { // file couldn't be opened
|
||||
G4cout << "Error: file could not be opened" << G4endl;
|
||||
exit(1);
|
||||
}
|
||||
// vector<int> * seedVector = new vector<int>;
|
||||
vector<int> * seedVector = lem4EventAction::GetPointerToSeedVector();
|
||||
indata >> num;
|
||||
while ( !indata.eof() ) { // keep reading until end-of-file
|
||||
G4cout << "The next number is " << num << G4endl;
|
||||
seedVector->push_back(num);
|
||||
indata >> num; // sets EOF flag if no value found
|
||||
|
||||
// lem4EventAction::RandomNrInitialisers->push_back(num);
|
||||
}
|
||||
indata.close();
|
||||
G4cout << "End-of-file reached.." << seedVector->size()<<G4endl;
|
||||
// lem4EventAction::RandomNrInitialisers=seedVector;
|
||||
}
|
||||
}
|
||||
if ( command == HowOftenToPrintEventCmd )
|
||||
{
|
||||
G4int n = HowOftenToPrintEventCmd->GetNewIntValue(newValue);
|
||||
lem4EventAction::nHowOftenToPrintEvent=n;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
62
geant4/LEMuSR/src/lem4ErrorMessage.cc
Normal file
62
geant4/LEMuSR/src/lem4ErrorMessage.cc
Normal file
@ -0,0 +1,62 @@
|
||||
#include "lem4ErrorMessage.hh"
|
||||
|
||||
lem4ErrorMessage::lem4ErrorMessage():nErrors(1)
|
||||
{
|
||||
pointerToErrors=this;
|
||||
severityWord[INFO]="INFO";
|
||||
severityWord[WARNING]="WARNING";
|
||||
severityWord[SERIOUS]="SERIOUS";
|
||||
severityWord[FATAL]="FATAL";
|
||||
}
|
||||
|
||||
lem4ErrorMessage::~lem4ErrorMessage() {}
|
||||
|
||||
lem4ErrorMessage* lem4ErrorMessage::pointerToErrors=NULL;
|
||||
lem4ErrorMessage* lem4ErrorMessage::GetInstance() {
|
||||
return pointerToErrors;
|
||||
}
|
||||
|
||||
void lem4ErrorMessage::lem4Error(SEVERITY severity, G4String message, G4bool silent) {
|
||||
std::map<G4String,ErrorStruct>::iterator it;
|
||||
it = ErrorMapping.find(message);
|
||||
if (it == ErrorMapping.end()) { // The error message is called for the first time
|
||||
ErrorStruct actualErrorMessage;
|
||||
actualErrorMessage.mesSeverity = severity;
|
||||
actualErrorMessage.nTimes = 1;
|
||||
ErrorMapping[message]=actualErrorMessage;
|
||||
G4cout<<"!!!"<<severityWord[severity]<<"!!! "<<message<<" (First time occurrence)"<<G4endl;
|
||||
nErrors++;
|
||||
}
|
||||
else { // The error message is called for more than the first time
|
||||
(*it).second.nTimes++;
|
||||
}
|
||||
|
||||
// Print out the error message if required
|
||||
if ((!silent)||(severity==FATAL)) {
|
||||
if ((*it).second.nTimes>1) {
|
||||
G4cout<<"!!!"<<severityWord[severity]<<"!!! "<<message
|
||||
<<" ("<<(*it).second.nTimes<<" occurences)"<<G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (severity==FATAL) {
|
||||
G4cout<<"S T O P F O R C E D!"<<G4endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void lem4ErrorMessage::PrintErrorSummary() {
|
||||
std::map<G4String,ErrorStruct>::iterator it;
|
||||
G4cout<<"------ ERROR SUMMARY: -------------------------------------------------------"<<G4endl;
|
||||
for (G4int i=0; i<4; i++) {
|
||||
for ( it=ErrorMapping.begin() ; it != ErrorMapping.end(); it++ ) {
|
||||
if ((*it).second.mesSeverity==i) {
|
||||
G4cout<<severityWord[(*it).second.mesSeverity]<<" ("<<(*it).second.nTimes<<" times):"
|
||||
<< (*it).first <<G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
G4cout<<"--------------------------------------------------------------------------------"<<G4endl;
|
||||
}
|
182
geant4/LEMuSR/src/lem4EventAction.cc
Normal file
182
geant4/LEMuSR/src/lem4EventAction.cc
Normal file
@ -0,0 +1,182 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "lem4EventAction.hh"
|
||||
#include "G4Event.hh"
|
||||
#include "G4EventManager.hh"
|
||||
#include "G4TrajectoryContainer.hh"
|
||||
#include "G4Trajectory.hh"
|
||||
#include "G4VVisManager.hh"
|
||||
#include "G4ios.hh"
|
||||
#include "G4TransportationManager.hh"
|
||||
#include "G4FieldManager.hh"
|
||||
#include "lem4MagneticField.hh"
|
||||
#include "lem4TabulatedField3D.hh"
|
||||
#include "lem4TabulatedField2D.hh"
|
||||
#include "lem4RootOutput.hh"
|
||||
#include "lem4ErrorMessage.hh"
|
||||
#include "lem4SteppingAction.hh" ///
|
||||
#include "F04GlobalField.hh" /// Are these two really needed ??
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool lem4EventAction::setRandomNrSeedAccordingEventNr=0;
|
||||
G4bool lem4EventAction::setRandomNrSeedFromFile=0;
|
||||
G4int lem4EventAction::nHowOftenToPrintEvent=10000;
|
||||
//vector<int> * lem4EventAction::RandomNrInitialisers=NULL;
|
||||
|
||||
//long lem4EventAction::myEventNr=0;
|
||||
|
||||
lem4EventAction::lem4EventAction() {
|
||||
pointer=this;
|
||||
fieldValueStart=0;
|
||||
pointerToSeedVector = new vector<int>;
|
||||
timeDependentField=false;
|
||||
lastFieldValue=-10000*tesla;
|
||||
pointerToMusrUniformField=NULL;
|
||||
pointerToTabulatedField3D=NULL;
|
||||
pointerToTabulatedField2D=NULL;
|
||||
latestEventNr=-1;
|
||||
}
|
||||
lem4EventAction* lem4EventAction::pointer=0;
|
||||
lem4EventAction* lem4EventAction::GetInstance() {
|
||||
return pointer;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4EventAction::~lem4EventAction()
|
||||
{
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4EventAction::BeginOfEventAction(const G4Event* evt) {
|
||||
// test error
|
||||
// lem4ErrorMessage::GetInstance()->lem4Error(SERIOUS,"test error",true);
|
||||
//
|
||||
|
||||
lem4SteppingAction::GetInstance()->DoAtTheBeginningOfEvent();
|
||||
|
||||
long thisEventNr = (long) (evt->GetEventID());
|
||||
|
||||
if (F04GlobalField::Exists()) {
|
||||
F04GlobalField::getObject() -> CheckWhetherAnyNominalFieldValueNeedsToBeChanged(thisEventNr);
|
||||
}
|
||||
|
||||
|
||||
///?long thisEventNr = (long) (evt->GetEventID());
|
||||
latestEventNr = thisEventNr;
|
||||
G4double actualFieldValue;
|
||||
if (timeDependentField) {
|
||||
// actualFieldValue=fieldAtEnd-fieldAtBeginning
|
||||
G4int i=int(double(thisEventNr)/double(maxEventNr)*fieldNrOfSteps); // i ... nr of actual step in the field
|
||||
actualFieldValue=fieldValueStart+fieldStep*i;
|
||||
if (actualFieldValue!=lastFieldValue) {
|
||||
lastFieldValue=actualFieldValue;
|
||||
// G4FieldManager* fieldMgr = G4TransportationManager::GetTransportationManager()->GetFieldManager();
|
||||
// // fieldMgr->SetFieldValue(actualFieldValue); //did not work
|
||||
// const G4Field* pointerToField = NULL;
|
||||
// pointerToField=fieldMgr->GetDetectorField();
|
||||
// pointerToField->GetFieldValue(0,0,0,0,
|
||||
if (pointerToMusrUniformField) {
|
||||
pointerToMusrUniformField->SetFieldValue(actualFieldValue);
|
||||
// pointerToField->SetFieldValue(actualFieldValue); does not work
|
||||
G4cout<<"Event "<<thisEventNr<<": Uniform field value changed to ";
|
||||
G4cout<<(actualFieldValue/tesla)<<"Tesla."<<G4endl;
|
||||
}
|
||||
else if (pointerToTabulatedField3D) {
|
||||
pointerToTabulatedField3D->SetFieldValue(actualFieldValue);
|
||||
G4cout<<"Event "<<thisEventNr<<": Tabulated Field (3D) value changed to ";
|
||||
G4cout<<(actualFieldValue/tesla)<<"Tesla."<<G4endl;
|
||||
}
|
||||
else if (pointerToTabulatedField2D) {
|
||||
pointerToTabulatedField2D->SetFieldValue(actualFieldValue);
|
||||
G4cout<<"Event "<<thisEventNr<<": Tabulated Field (2D) value changed to ";
|
||||
G4cout<<(actualFieldValue/tesla)<<"Tesla."<<G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {actualFieldValue=fieldValueStart;}
|
||||
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
myRootOutput->SetFieldValue(actualFieldValue);
|
||||
|
||||
// if (lem4DetectorMessenger::setRandomNrSeedAccordingEventNr) {
|
||||
if (setRandomNrSeedFromFile) {
|
||||
// G4cout<<"RandomNrInitialisers.size()="<<RandomNrInitialisers->size()<<G4endl;
|
||||
if (thisEventNr < (long) pointerToSeedVector->size()) {
|
||||
G4cout <<"lem4EventAction.cc: seed will be set to="<< pointerToSeedVector->at(thisEventNr)<<G4endl;
|
||||
CLHEP::HepRandom::setTheSeed(pointerToSeedVector->at(thisEventNr));
|
||||
}
|
||||
}
|
||||
else if (setRandomNrSeedAccordingEventNr) {
|
||||
// long seeds[2];
|
||||
// seeds[0] = (long) 234567890+thisEventNr*117;
|
||||
// seeds[1] = (long) 333222111+thisEventNr*173;
|
||||
//
|
||||
// // seeds[1] = (long) (evt->GetEventID());
|
||||
// // seeds[0] = (long) 123456789; // This leads to a gap in the decay time histogram fro N=100000 events
|
||||
// // seeds[1] = (long) 333222111+thisEventNr; // ----------------------------||------------------------------------
|
||||
// thisEventNr++;
|
||||
// CLHEP::HepRandom::setTheSeeds(seeds);
|
||||
// // G4cout << "seed1: " << seeds[0] << "; seed2: " << seeds[1] << G4endl;
|
||||
//
|
||||
// G4cout <<" thisEventNr="<<thisEventNr;
|
||||
CLHEP::HepRandom::setTheSeed(thisEventNr);
|
||||
// G4cout <<" getTheSeed="<<CLHEP::HepRandom::getTheSeed()<< G4endl;
|
||||
CLHEP::RandGauss::setFlag(false);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4EventAction::EndOfEventAction(const G4Event* evt) {
|
||||
// cout << ":." << flush;
|
||||
long thisEventNr = (long) evt->GetEventID();
|
||||
|
||||
// get number of stored trajectories
|
||||
//
|
||||
G4TrajectoryContainer* trajectoryContainer = evt->GetTrajectoryContainer();
|
||||
G4int n_trajectories = 0;
|
||||
if (trajectoryContainer) n_trajectories = trajectoryContainer->entries();
|
||||
|
||||
// G4cout << ">>> Event " << evt->GetEventID() << G4endl;
|
||||
|
||||
// periodic printing
|
||||
//
|
||||
// if (thisEventNr != 0 and thisEventNr%10000 == 0) {
|
||||
if (thisEventNr != 0 and thisEventNr%nHowOftenToPrintEvent == 0) {
|
||||
time_t curr=time(0);
|
||||
//char * ctime(const time_t * tp);
|
||||
G4cout << ">>> Event " << evt->GetEventID() <<"\t at "<< ctime(&curr);
|
||||
G4cout.flush();
|
||||
// G4cout << " seed set to "<< CLHEP::HepRandom::getTheSeed();//<< G4endl;
|
||||
}
|
||||
|
||||
// extract the trajectories and draw them
|
||||
//
|
||||
if (G4VVisManager::GetConcreteInstance()) {
|
||||
for (G4int i=0; i<n_trajectories; i++)
|
||||
{ G4Trajectory* trj = (G4Trajectory*)
|
||||
((*(evt->GetTrajectoryContainer()))[i]);
|
||||
trj->DrawTrajectory(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
vector<int> * lem4EventAction::pointerToSeedVector=NULL;
|
||||
vector<int> * lem4EventAction::GetPointerToSeedVector() {
|
||||
return pointerToSeedVector;
|
||||
}
|
||||
|
||||
|
||||
void lem4EventAction::SetTimeDependentField(G4bool setFieldToBeTimeDependend, G4double initialField,
|
||||
G4double finalField, G4int nrOfSteps) {
|
||||
timeDependentField = setFieldToBeTimeDependend;
|
||||
fieldValueStart = initialField;
|
||||
fieldValueEnd = finalField;
|
||||
fieldNrOfSteps = nrOfSteps;
|
||||
fieldStep = (finalField-initialField)/(nrOfSteps-1);
|
||||
G4cout<<"---&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&---"<<G4endl;
|
||||
}
|
28
geant4/LEMuSR/src/lem4GaussianField.cc
Normal file
28
geant4/LEMuSR/src/lem4GaussianField.cc
Normal file
@ -0,0 +1,28 @@
|
||||
#include "lem4GaussianField.hh"
|
||||
|
||||
|
||||
lem4GaussianField::lem4GaussianField(double fieldValue, double sigma):ffieldValue(fieldValue) {
|
||||
fieldMagnitude=fieldValue;
|
||||
RMS=sigma;
|
||||
G4cout << "\n-----------------------------------------------------------"
|
||||
<< "\n Magnetic field ON"
|
||||
<< "\n-----------------------------------------------------------"
|
||||
<< G4endl;
|
||||
// G4cout << " Gaussian magnetic field set to "<< fieldValue*1000 << " T, with sigma in R="<< sigma<<" mm"<< G4endl;
|
||||
G4cout << "Gaussian magnetic field set to "<< fieldValue/tesla << " Tesla, with a radial sigma "<< sigma/mm<<" mm.\n"<< G4endl;
|
||||
}
|
||||
|
||||
void lem4GaussianField::GetFieldValue(const double point[4], double *Bfield ) const {
|
||||
double x = point[0];
|
||||
double y = point[1];
|
||||
// double z = point[2];
|
||||
double r = sqrt(x*x+y*y);
|
||||
Bfield[0] = 0;
|
||||
Bfield[1] = 0;
|
||||
Bfield[2] = fieldMagnitude*exp(-r*r/(2*RMS*RMS));
|
||||
// G4cout<<"z="<<z<<" r="<<r<<" B[2]="<<Bfield[2]<<G4endl;
|
||||
}
|
||||
|
||||
G4double lem4GaussianField::GetFieldSetValue() {
|
||||
return ffieldValue;
|
||||
}
|
70
geant4/LEMuSR/src/lem4MagneticField.cc
Normal file
70
geant4/LEMuSR/src/lem4MagneticField.cc
Normal file
@ -0,0 +1,70 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "lem4MagneticField.hh"
|
||||
#include "G4FieldManager.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4MagneticField::lem4MagneticField()
|
||||
: G4UniformMagField(G4ThreeVector())
|
||||
{
|
||||
GetGlobalFieldManager()->SetDetectorField(this);
|
||||
GetGlobalFieldManager()->CreateChordFinder(this);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4MagneticField::lem4MagneticField(G4ThreeVector fieldVector)
|
||||
: G4UniformMagField(fieldVector)
|
||||
{
|
||||
GetGlobalFieldManager()->SetDetectorField(this);
|
||||
GetGlobalFieldManager()->CreateChordFinder(this);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
// Set the value of the Global Field to fieldValue along Z
|
||||
//
|
||||
void lem4MagneticField::SetFieldValue(G4double fieldValue)
|
||||
{
|
||||
G4UniformMagField::SetFieldValue(G4ThreeVector(0,0,fieldValue));
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
// Set the value of the Global Field
|
||||
//
|
||||
void lem4MagneticField::SetFieldValue(G4ThreeVector fieldVector)
|
||||
{
|
||||
// Find the Field Manager for the global field
|
||||
G4FieldManager* fieldMgr= GetGlobalFieldManager();
|
||||
|
||||
if(fieldVector!=G4ThreeVector(0.,0.,0.))
|
||||
{
|
||||
G4UniformMagField::SetFieldValue(fieldVector);
|
||||
fieldMgr->SetDetectorField(this);
|
||||
} else {
|
||||
// If the new field's value is Zero, then it is best to
|
||||
// insure that it is not used for propagation.
|
||||
G4MagneticField* magField = NULL;
|
||||
fieldMgr->SetDetectorField(magField);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4MagneticField::~lem4MagneticField()
|
||||
{
|
||||
// GetGlobalFieldManager()->SetDetectorField(0);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "G4TransportationManager.hh"
|
||||
|
||||
G4FieldManager* lem4MagneticField::GetGlobalFieldManager()
|
||||
{
|
||||
return G4TransportationManager::GetTransportationManager()->GetFieldManager();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
106
geant4/LEMuSR/src/lem4MuFormation.cc
Normal file
106
geant4/LEMuSR/src/lem4MuFormation.cc
Normal file
@ -0,0 +1,106 @@
|
||||
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||
// Muonium Formation according to yield.cc function (through GetYields method).
|
||||
// Id : lem4MuFormation.cc, v 1.4
|
||||
// Author: Taofiq PARAISO, T. Shiroka
|
||||
// Date : 2007-12
|
||||
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||
|
||||
#include "lem4MuFormation.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
lem4MuFormation::lem4MuFormation(const G4String& name, G4ProcessType aType)
|
||||
: G4VDiscreteProcess(name, aType){}
|
||||
|
||||
lem4MuFormation::~lem4MuFormation(){}
|
||||
|
||||
G4VParticleChange* lem4MuFormation::PostStepDoIt(const G4Track& trackData,
|
||||
const G4Step& aStep)
|
||||
{ // Initialize ParticleChange (by setting all its members equal to
|
||||
// the corresponding members in G4Track)
|
||||
fParticleChange.Initialize(trackData);
|
||||
|
||||
G4Track theNewTrack;
|
||||
if(CheckCondition(aStep))
|
||||
{
|
||||
GetDatas(&aStep);
|
||||
G4Step theStep;
|
||||
PrepareSecondary( trackData);
|
||||
|
||||
fParticleChange.AddSecondary(aSecondary);
|
||||
fParticleChange.ProposeTrackStatus(fStopAndKill) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
fParticleChange.ProposeTrackStatus(trackData.GetTrackStatus()) ;
|
||||
}
|
||||
return &fParticleChange;
|
||||
}
|
||||
|
||||
|
||||
G4bool lem4MuFormation::CheckCondition(const G4Step& aStep)
|
||||
{ // Decide when to call the MuFormation process - i.e. for muons going through the C foil.
|
||||
G4bool condition=false;
|
||||
p_name = aStep.GetTrack()->GetDefinition()->GetParticleName(); // particle name
|
||||
//if(p_name == "mu+"&&aStep.GetTrack()->GetVolume()->GetLogicalVolume()->GetName()=="log_CFoil")
|
||||
std::string logVolName = aStep.GetTrack()->GetVolume()->GetLogicalVolume()->GetName();
|
||||
if(p_name == "mu+" && ((logVolName=="log_coulombCFoil")||(logVolName=="log_CFoil")))
|
||||
{
|
||||
condition=true;
|
||||
}
|
||||
return condition;
|
||||
}
|
||||
|
||||
|
||||
G4double lem4MuFormation::GetMeanFreePath(const G4Track&,
|
||||
G4double,
|
||||
G4ForceCondition* condition)
|
||||
{
|
||||
*condition = Forced;
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
|
||||
void lem4MuFormation::GetDatas(const G4Step* aStep)
|
||||
{ // Particle generation according to yield table
|
||||
particleTable=G4ParticleTable::GetParticleTable();
|
||||
rnd=G4UniformRand();
|
||||
G4double E = aStep->GetTrack()->GetDynamicParticle()->GetKineticEnergy()/keV;
|
||||
Gonin.GetYields(E,105.658369*1000,yvector); // Energy [keV], muon mass [keV/c2], yield table
|
||||
G4String p_new = "Mu";
|
||||
|
||||
// Positive muon
|
||||
if(p_name=="mu+")
|
||||
{
|
||||
if(rnd<yvector[0])
|
||||
{
|
||||
particle = particleTable->FindParticle(p_name) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
particle = particleTable->FindParticle(p_new);
|
||||
}
|
||||
|
||||
// Set the new dynamic particle DP
|
||||
DP = new G4DynamicParticle(particle,
|
||||
aStep->GetTrack()->GetDynamicParticle()->GetMomentumDirection(),
|
||||
aStep->GetTrack()->GetDynamicParticle()->GetKineticEnergy());
|
||||
|
||||
// IMPORTANT : COPY THOSE DATA TO GET THE SAME PARTICLE PROPERTIES!!!
|
||||
// SHOULD BE KEPT WHEN BUILDING A PARTICLE CHANGE
|
||||
DP->SetProperTime( aStep->GetTrack()->GetDynamicParticle()->GetProperTime());
|
||||
DP->SetPolarization(aStep->GetTrack()->GetDynamicParticle()->GetPolarization().x(),
|
||||
aStep->GetTrack()->GetDynamicParticle()->GetPolarization().y(),
|
||||
aStep->GetTrack()->GetDynamicParticle()->GetPolarization().z());
|
||||
DP->SetPreAssignedDecayProperTime(aStep->GetTrack()->GetDynamicParticle()->GetPreAssignedDecayProperTime());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void lem4MuFormation::PrepareSecondary(const G4Track& track)
|
||||
{
|
||||
if(p_name=="mu+")
|
||||
{
|
||||
aSecondary = new G4Track(DP,track.GetGlobalTime(),track.GetPosition());
|
||||
}
|
||||
}
|
81
geant4/LEMuSR/src/lem4MuScatter.cc
Normal file
81
geant4/LEMuSR/src/lem4MuScatter.cc
Normal file
@ -0,0 +1,81 @@
|
||||
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||
// Muonium "Scattering"
|
||||
// Id : lem4MuScatter.cc, v 1.4
|
||||
// Author: Taofiq PARAISO, T. Shiroka
|
||||
// Date : 2007-12
|
||||
// Notes : Simplified model for Mu scattering. Spin effects have been excluded.
|
||||
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||
|
||||
#include "lem4MuScatter.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
lem4MuScatter::lem4MuScatter(const G4String& name,
|
||||
G4ProcessType aType)
|
||||
: G4VDiscreteProcess(name, aType){}
|
||||
|
||||
lem4MuScatter:: ~lem4MuScatter(){}
|
||||
|
||||
/*! - At the end of the step, the current volume is checked and if Muonium is in a solid
|
||||
material (except for the carbon foil where it is generated), it is stopped immediately. */
|
||||
G4VParticleChange* lem4MuScatter::PostStepDoIt(const G4Track& trackData,
|
||||
const G4Step& aStep)
|
||||
{
|
||||
fParticleChange.Initialize(trackData);
|
||||
|
||||
//! Tao - Get time information */
|
||||
itime = trackData.GetProperTime();
|
||||
gtime = trackData.GetGlobalTime();
|
||||
ftime = trackData.GetDynamicParticle()->GetPreAssignedDecayProperTime();
|
||||
|
||||
deltatime = ftime - itime;
|
||||
fParticleChange.ProposeGlobalTime(deltatime + itime -gtime);
|
||||
|
||||
/*! - Set position, momentum, energy and time of the particle change. */
|
||||
fParticleChange.ProposePosition(trackData.GetPosition());
|
||||
fParticleChange.ProposeMomentumDirection(trackData.GetMomentumDirection());
|
||||
fParticleChange.ProposeEnergy(trackData.GetKineticEnergy());
|
||||
fParticleChange.ProposeGlobalTime(gtime);
|
||||
fParticleChange.ProposeProperTime(itime);
|
||||
fParticleChange.ProposeTrackStatus(trackData.GetTrackStatus()) ;
|
||||
|
||||
/*! - Verify the condition of applying the process: if Mu is in a material
|
||||
different than vacuum and carbon foil, then stop it directly. */
|
||||
if( CheckCondition(aStep))
|
||||
{
|
||||
fParticleChange.ProposePosition(trackData.GetStep()->GetPreStepPoint()->GetPosition());
|
||||
fParticleChange.ProposeTrackStatus(fStopButAlive) ;
|
||||
}
|
||||
|
||||
/*! - Return the changed particle object. */
|
||||
return &fParticleChange;
|
||||
}
|
||||
|
||||
|
||||
/*! - Muonium will be stopped as soon as it enters a material different than vacuum or C foil. */
|
||||
G4bool lem4MuScatter::CheckCondition(const G4Step& aStep)
|
||||
{
|
||||
G4bool condition = false;
|
||||
p_name = aStep.GetTrack()->GetDefinition()->GetParticleName(); // particle name
|
||||
if(p_name == "Mu" && aStep.GetTrack()->GetVolume()->GetLogicalVolume()->GetName()!="log_CFoil" &&
|
||||
aStep.GetTrack()->GetVolume()->GetLogicalVolume()->GetMaterial()->GetName()!="G4_Galactic")
|
||||
{
|
||||
condition=true;
|
||||
}
|
||||
return condition;
|
||||
}
|
||||
|
||||
|
||||
G4double lem4MuScatter::GetMeanFreePath(const G4Track&,
|
||||
G4double,
|
||||
G4ForceCondition* condition)
|
||||
{
|
||||
*condition = Forced;
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
|
||||
void lem4MuScatter::PrepareSecondary(const G4Track& track)
|
||||
{
|
||||
aSecondary = new G4Track(DP,track.GetDynamicParticle()->GetPreAssignedDecayProperTime(),track.GetPosition());
|
||||
}
|
107
geant4/LEMuSR/src/lem4Muonium.cc
Normal file
107
geant4/LEMuSR/src/lem4Muonium.cc
Normal file
@ -0,0 +1,107 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// $Id: lem4Muonium.cc,v 1.13 2007/03/15 06:53:58 kurasige Exp $
|
||||
// GEANT4 tag $Name: geant4-09-00 $
|
||||
//
|
||||
//
|
||||
// ----------------------------------------------------------------------
|
||||
// GEANT 4 class implementation file
|
||||
//
|
||||
// History: first implementation, based on object model of
|
||||
// 4th April 1996, G. Cosmo
|
||||
// **********************************************************************
|
||||
// New implementation as an utility class M. Asai, 26 July 2004
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
#include "lem4Muonium.hh"
|
||||
#include "G4ParticleTable.hh"
|
||||
|
||||
#include "MuDecayChannel.hh"
|
||||
#include "G4DecayTable.hh"
|
||||
|
||||
// ######################################################################
|
||||
// ### MUONIUM ###
|
||||
// ######################################################################
|
||||
lem4Muonium* lem4Muonium::theInstance = 0;
|
||||
|
||||
lem4Muonium* lem4Muonium::Definition()
|
||||
{
|
||||
if (theInstance !=0) return theInstance;
|
||||
const G4String name = "Mu";
|
||||
// search in particle table]
|
||||
G4ParticleTable* pTable = G4ParticleTable::GetParticleTable();
|
||||
G4ParticleDefinition* anInstance = pTable->FindParticle(name);
|
||||
if (anInstance ==0)
|
||||
{
|
||||
// create particle
|
||||
//
|
||||
// Arguments for constructor are as follows
|
||||
// name mass width charge
|
||||
// 2*spin parity C-conjugation
|
||||
// 2*Isospin 2*Isospin3 G-parity
|
||||
// type lepton number baryon number PDG encoding
|
||||
// stable lifetime decay table
|
||||
// shortlived subType anti_encoding
|
||||
anInstance = new G4ParticleDefinition(
|
||||
name, 0.1056584*GeV, 2.99591e-16*MeV, 0.*eplus,
|
||||
1, 0, 0,
|
||||
0, 0, 0,
|
||||
"lepton", -1, 0, -1313,
|
||||
false, 2197.03*ns, NULL,
|
||||
false, "mu"
|
||||
);
|
||||
// Bohr magnetron of Muonium - T. Shiroka
|
||||
// The magnetic moment of Mu is the sum of those of mu+ and e- with
|
||||
// the respective gyromagnetic ratio anomalies as coefficients
|
||||
|
||||
G4double muBmu = 0.5*eplus*hbar_Planck/(0.10565840*GeV/c_squared);
|
||||
G4double muBel = -0.5*eplus*hbar_Planck/(0.51099906*MeV/c_squared);
|
||||
G4double muB = 1.0011659208*muBmu + 1.0011596521859*muBel;
|
||||
|
||||
anInstance->SetPDGMagneticMoment( muB );
|
||||
|
||||
//create Decay Table
|
||||
G4DecayTable* table = new G4DecayTable();
|
||||
// create a decay channel
|
||||
G4VDecayChannel* mode = new MuDecayChannel("Mu",1.00);
|
||||
table->Insert(mode);
|
||||
anInstance->SetDecayTable(table);
|
||||
}
|
||||
theInstance = reinterpret_cast<lem4Muonium*>(anInstance);
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
lem4Muonium* lem4Muonium::MuoniumDefinition()
|
||||
{
|
||||
return Definition();
|
||||
}
|
||||
|
||||
lem4Muonium* lem4Muonium::Muonium()
|
||||
{
|
||||
return Definition();
|
||||
}
|
||||
|
71
geant4/LEMuSR/src/lem4Parameters.cc
Normal file
71
geant4/LEMuSR/src/lem4Parameters.cc
Normal file
@ -0,0 +1,71 @@
|
||||
#include "lem4Parameters.hh"
|
||||
|
||||
///lem4Parameters::lem4Parameters()
|
||||
/// :typeOfProcesses("standard")
|
||||
///{
|
||||
/// pointerToParameters=this;
|
||||
///}
|
||||
|
||||
lem4Parameters::lem4Parameters(G4String steeringFileName)
|
||||
:typeOfProcesses("coulombAndMultiple") //lowenergy")
|
||||
{
|
||||
pointerToParameters=this;
|
||||
|
||||
// Read in the parameters, which have to be known before the detector construction is run
|
||||
// (and therefore the parameters can not be read in in the lem4DetectorConstruction.cc class).
|
||||
|
||||
FILE *fSteeringFile=fopen(steeringFileName.c_str(),"r");
|
||||
if (fSteeringFile==NULL) {
|
||||
G4cout<<"lem4Parameters::lem4Parameters: steeringFileName=\""<<steeringFileName
|
||||
<<"\" not opened for some reason."<<G4endl;
|
||||
}
|
||||
G4cout<<"lem4Parameters::lem4Parameters: steeringFileName=\""<<steeringFileName<<"\" opened."<<G4endl;
|
||||
char line[501];
|
||||
|
||||
while (!feof(fSteeringFile)) {
|
||||
fgets(line,500,fSteeringFile);
|
||||
if ((line[0]!='#')&&(line[0]!='\n')&&(line[0]!='\r')) {
|
||||
char tmpString0[100]="Unset";
|
||||
sscanf(&line[0],"%s",tmpString0);
|
||||
|
||||
// First find out how many events will be generated
|
||||
// (should be known at an early stage, if the field is to be set-up in steps):
|
||||
if (strcmp(tmpString0,"/run/beamOn")==0) {
|
||||
int nev;
|
||||
sscanf(&line[0],"%*s %d", &nev);
|
||||
lem4Parameters::nrOfEventsToBeGenerated = nev;
|
||||
}
|
||||
|
||||
// Now find out about some other private parameters that also need to be initialised at an early stage
|
||||
if (strcmp(tmpString0,"/lem4/command")!=0) {continue; }///{ break; }
|
||||
|
||||
char tmpString1[100]="Unset", tmpString2[100]="Unset";
|
||||
sscanf(&line[0],"%*s %s %s",tmpString1,tmpString2);
|
||||
|
||||
//! First commented by TS. Currently not in use! or not strictly necessary.
|
||||
if (strcmp(tmpString1,"G4GeneralParticleSource")==0){
|
||||
if (strcmp(tmpString2,"true")==0){ lem4Parameters::boolG4GeneralParticleSource = true; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
fclose(fSteeringFile);
|
||||
}
|
||||
|
||||
|
||||
lem4Parameters::~lem4Parameters() {}
|
||||
|
||||
lem4Parameters* lem4Parameters::pointerToParameters=NULL;
|
||||
lem4Parameters* lem4Parameters::GetInstance() {
|
||||
return pointerToParameters;
|
||||
}
|
||||
|
||||
G4bool lem4Parameters::storeOnlyEventsWithHits =true;
|
||||
G4double lem4Parameters::signalSeparationTime=100*nanosecond;
|
||||
G4bool lem4Parameters::storeOnlyTheFirstTimeHit=false;
|
||||
G4bool lem4Parameters::includeMuoniumProcesses =true;
|
||||
G4bool lem4Parameters::field_DecayWithSpin=false; //Added by TS to confrom with the new StepAction ...
|
||||
G4bool lem4Parameters::boolG4GeneralParticleSource=false; ///! This is not strictly necessary! TS
|
||||
G4int lem4Parameters::nrOfEventsToBeGenerated=0;
|
||||
|
416
geant4/LEMuSR/src/lem4PhysicsList.cc
Normal file
416
geant4/LEMuSR/src/lem4PhysicsList.cc
Normal file
@ -0,0 +1,416 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "globals.hh"
|
||||
#include "G4ios.hh"
|
||||
#include "lem4PhysicsList.hh"
|
||||
#include "G4VPhysicsConstructor.hh"
|
||||
#include "G4ProcessManager.hh"
|
||||
#include "G4ParticleTypes.hh"
|
||||
|
||||
#include "G4MuonDecayChannel.hh"
|
||||
#include "G4DecayTable.hh"
|
||||
//#include "lem4MuonDecayChannel.hh"
|
||||
//#include "lem4Decay.hh"
|
||||
//cks Added to have Geant default muon decay with spin
|
||||
#include "G4MuonDecayChannelWithSpin.hh"
|
||||
//#include "G4AtRestSpinPrecession.hh"
|
||||
|
||||
//TS Classes which account for Muonium as "particle" and its spin
|
||||
#include "lem4Muonium.hh"
|
||||
#include "MuDecayChannel.hh"
|
||||
#include "MuDecayChannelWithSpin.hh"
|
||||
|
||||
#include "lem4Parameters.hh"
|
||||
|
||||
// Constructor and Destructor
|
||||
lem4PhysicsList::lem4PhysicsList():G4VUserPhysicsList()
|
||||
{
|
||||
defaultCutValue = 0.1*mm; // 1.0*cm;
|
||||
SetVerboseLevel(0);
|
||||
}
|
||||
|
||||
lem4PhysicsList::~lem4PhysicsList()
|
||||
{}
|
||||
|
||||
|
||||
// Construction of the different particles (calls different construction methods)
|
||||
|
||||
void lem4PhysicsList::ConstructParticle()
|
||||
{
|
||||
ConstructBosons();
|
||||
ConstructLeptons();
|
||||
ConstructBaryons();
|
||||
}
|
||||
|
||||
// Bosons
|
||||
|
||||
void lem4PhysicsList::ConstructBosons()
|
||||
{
|
||||
// pseudo-particles
|
||||
G4Geantino::GeantinoDefinition();
|
||||
G4ChargedGeantino::ChargedGeantinoDefinition();
|
||||
|
||||
// gamma
|
||||
G4Gamma::GammaDefinition();
|
||||
}
|
||||
|
||||
// Leptons
|
||||
|
||||
void lem4PhysicsList::ConstructLeptons()
|
||||
{
|
||||
// e+/-
|
||||
G4Electron::ElectronDefinition();
|
||||
G4Positron::PositronDefinition();
|
||||
// mu+/-
|
||||
G4MuonPlus::MuonPlusDefinition();
|
||||
G4MuonMinus::MuonMinusDefinition();
|
||||
// Muonium - TS
|
||||
lem4Muonium::MuoniumDefinition();
|
||||
|
||||
G4NeutrinoE::NeutrinoEDefinition();
|
||||
G4AntiNeutrinoE::AntiNeutrinoEDefinition();
|
||||
// nu_mu
|
||||
G4NeutrinoMu::NeutrinoMuDefinition();
|
||||
G4AntiNeutrinoMu::AntiNeutrinoMuDefinition();
|
||||
|
||||
// Decays of muon and muonium
|
||||
//cks: Trial to use Geant4 muon decay with spin
|
||||
G4DecayTable* MuonPlusDecayTable = new G4DecayTable();
|
||||
MuonPlusDecayTable -> Insert(new G4MuonDecayChannelWithSpin("mu+",1.00));
|
||||
G4MuonPlus::MuonPlusDefinition() -> SetDecayTable(MuonPlusDecayTable);
|
||||
|
||||
//TS: Using the muonium decay with and without spin
|
||||
G4DecayTable* MuoniumDecayTable = new G4DecayTable();
|
||||
MuoniumDecayTable -> Insert(new MuDecayChannel("Mu",0.50));
|
||||
MuoniumDecayTable -> Insert(new MuDecayChannelWithSpin("Mu",0.5));
|
||||
lem4Muonium::MuoniumDefinition() -> SetDecayTable(MuoniumDecayTable);
|
||||
//MuoniumDecayTable ->DumpInfo(); // Info on muonium decay channels
|
||||
|
||||
}
|
||||
|
||||
// Mesons (only some light mesons)
|
||||
|
||||
void lem4PhysicsList::ConstructMesons()
|
||||
{
|
||||
G4PionPlus::PionPlusDefinition();
|
||||
G4PionMinus::PionMinusDefinition();
|
||||
G4PionZero::PionZeroDefinition();
|
||||
}
|
||||
|
||||
// Baryons
|
||||
|
||||
void lem4PhysicsList::ConstructBaryons()
|
||||
{
|
||||
G4Proton::ProtonDefinition();
|
||||
G4AntiProton::AntiProtonDefinition();
|
||||
G4Neutron::NeutronDefinition();
|
||||
G4AntiNeutron::AntiNeutronDefinition();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Physical processes - general
|
||||
|
||||
void lem4PhysicsList::ConstructProcess()
|
||||
{
|
||||
AddTransportation();
|
||||
ConstructEM();
|
||||
ConstructGeneral();
|
||||
}
|
||||
|
||||
// Declaration of the different processes
|
||||
#include "G4ComptonScattering.hh"
|
||||
#include "G4GammaConversion.hh"
|
||||
#include "G4PhotoElectricEffect.hh"
|
||||
|
||||
#include "G4MultipleScattering.hh"
|
||||
|
||||
#include "G4eIonisation.hh"
|
||||
#include "G4eBremsstrahlung.hh"
|
||||
#include "G4eplusAnnihilation.hh"
|
||||
|
||||
#include "G4MuIonisation.hh"
|
||||
#include "G4MuBremsstrahlung.hh"
|
||||
#include "G4MuPairProduction.hh"
|
||||
|
||||
#include "G4hIonisation.hh"
|
||||
|
||||
#include "G4UserSpecialCuts.hh"
|
||||
|
||||
//#include "lem4AtRestSpinRotation.hh"
|
||||
|
||||
// For low energy physics processes:
|
||||
#include "G4LowEnergyCompton.hh"
|
||||
//#include "G4LowEnergyPolarizedCompton.hh"
|
||||
#include "G4LowEnergyGammaConversion.hh"
|
||||
#include "G4LowEnergyPhotoElectric.hh"
|
||||
#include "G4LowEnergyRayleigh.hh"
|
||||
#include "G4LowEnergyBremsstrahlung.hh"
|
||||
#include "G4LowEnergyIonisation.hh"
|
||||
#include "G4hLowEnergyIonisation.hh"
|
||||
|
||||
|
||||
// For Penelope processes:
|
||||
#include "G4PenelopeCompton.hh"
|
||||
#include "G4PenelopeGammaConversion.hh"
|
||||
#include "G4PenelopePhotoElectric.hh"
|
||||
#include "G4PenelopeRayleigh.hh"
|
||||
#include "G4PenelopeIonisation.hh"
|
||||
#include "G4PenelopeBremsstrahlung.hh"
|
||||
#include "G4PenelopeAnnihilation.hh"
|
||||
|
||||
// For Coulomb scattering instead of multiple scattering
|
||||
#include "G4CoulombScattering.hh"
|
||||
|
||||
// For Muonium formation in the Carbon foil
|
||||
#include "lem4MuFormation.hh" // includes the yield function Y = Y(E).
|
||||
|
||||
// For a simple Muonium "scattering" when Mu hits solid materials
|
||||
#include "lem4MuScatter.hh"
|
||||
|
||||
|
||||
// Construction methods for the different processes
|
||||
|
||||
void lem4PhysicsList::ConstructEM()
|
||||
{
|
||||
G4String myTypeOfProcesses = lem4Parameters::GetInstance()->GetMyTypeOfProcesses();
|
||||
G4cout<<" uuuuuuuuu myTypeOfProcesses="<<myTypeOfProcesses<<G4endl;
|
||||
|
||||
G4bool inclMuProcesses = lem4Parameters::includeMuoniumProcesses;
|
||||
|
||||
theParticleIterator->reset();
|
||||
while( (*theParticleIterator)() ){
|
||||
G4ParticleDefinition* particle = theParticleIterator->value();
|
||||
G4ProcessManager* pmanager = particle->GetProcessManager();
|
||||
G4String particleName = particle->GetParticleName();
|
||||
|
||||
if (particleName == "gamma") { // gamma
|
||||
if (myTypeOfProcesses=="lowenergy") {
|
||||
pmanager->AddDiscreteProcess(new G4LowEnergyPhotoElectric);
|
||||
pmanager->AddDiscreteProcess(new G4LowEnergyCompton);
|
||||
pmanager->AddDiscreteProcess(new G4LowEnergyGammaConversion);
|
||||
pmanager->AddDiscreteProcess(new G4LowEnergyRayleigh);
|
||||
}
|
||||
else if (myTypeOfProcesses=="penelope") {
|
||||
pmanager->AddDiscreteProcess(new G4PenelopePhotoElectric);
|
||||
pmanager->AddDiscreteProcess(new G4PenelopeCompton);
|
||||
pmanager->AddDiscreteProcess(new G4PenelopeGammaConversion);
|
||||
pmanager->AddDiscreteProcess(new G4PenelopeRayleigh);
|
||||
}
|
||||
else { // Standard G4 (default)
|
||||
pmanager->AddDiscreteProcess(new G4PhotoElectricEffect);
|
||||
pmanager->AddDiscreteProcess(new G4ComptonScattering);
|
||||
pmanager->AddDiscreteProcess(new G4GammaConversion);
|
||||
}
|
||||
|
||||
}
|
||||
else if (particleName == "e-") { //electron
|
||||
if (myTypeOfProcesses=="lowenergy") {
|
||||
pmanager->AddProcess(new G4MultipleScattering, -1, 1,1);
|
||||
pmanager->AddProcess(new G4LowEnergyIonisation, -1, 2,2);
|
||||
pmanager->AddProcess(new G4LowEnergyBremsstrahlung,-1,-1,3);
|
||||
}
|
||||
else if (myTypeOfProcesses=="penelope") {
|
||||
pmanager->AddProcess(new G4MultipleScattering, -1, 1, 1);
|
||||
pmanager->AddProcess(new G4PenelopeIonisation, -1, 2, 2);
|
||||
pmanager->AddProcess(new G4PenelopeBremsstrahlung, -1,-1, 3);
|
||||
}
|
||||
else if (myTypeOfProcesses=="coulomb") {
|
||||
pmanager->AddDiscreteProcess(new G4CoulombScattering);
|
||||
pmanager->AddProcess(new G4eIonisation, -1, 2,2);
|
||||
pmanager->AddProcess(new G4eBremsstrahlung, -1, 3,3);
|
||||
}
|
||||
else { // Standard G4 (default)
|
||||
pmanager->AddProcess(new G4MultipleScattering,-1, 1,1);
|
||||
pmanager->AddProcess(new G4eIonisation, -1, 2,2);
|
||||
pmanager->AddProcess(new G4eBremsstrahlung, -1, 3,3);
|
||||
}
|
||||
}
|
||||
|
||||
else if (particleName == "e+") {
|
||||
|
||||
if (myTypeOfProcesses=="penelope") {
|
||||
pmanager->AddProcess(new G4MultipleScattering, -1, 1, 1);
|
||||
pmanager->AddProcess(new G4PenelopeIonisation, -1, 2, 2);
|
||||
pmanager->AddProcess(new G4PenelopeBremsstrahlung, -1,-1, 3);
|
||||
pmanager->AddProcess(new G4PenelopeAnnihilation, 0,-1, 4);
|
||||
}
|
||||
else if (myTypeOfProcesses=="coulomb") {
|
||||
pmanager->AddDiscreteProcess(new G4CoulombScattering);
|
||||
pmanager->AddProcess(new G4eIonisation, -1, 2,2);
|
||||
pmanager->AddProcess(new G4eBremsstrahlung, -1, 3,3);
|
||||
pmanager->AddProcess(new G4eplusAnnihilation, 0,-1,4);
|
||||
}
|
||||
else { // Standard G4 (default)
|
||||
pmanager->AddProcess(new G4MultipleScattering,-1, 1,1);
|
||||
pmanager->AddProcess(new G4eIonisation, -1, 2,2);
|
||||
pmanager->AddProcess(new G4eBremsstrahlung, -1, 3,3);
|
||||
pmanager->AddProcess(new G4eplusAnnihilation, 0,-1,4);
|
||||
}
|
||||
}
|
||||
|
||||
else if ((particleName=="mu+")||(particleName=="mu-")) { //muon
|
||||
|
||||
if (myTypeOfProcesses=="coulomb") {
|
||||
pmanager->AddDiscreteProcess(new G4CoulombScattering); // TS - Attention use Meyer!!
|
||||
}
|
||||
else if (myTypeOfProcesses=="coulombAndMultiple") {
|
||||
std::cout <<"musrPhysicsList: Switching between Coulomb and Multiple scattering for mu+"<<std::endl;
|
||||
pmanager->AddProcess(new G4MultipleScattering,-1, 1,1);
|
||||
pmanager->AddDiscreteProcess(new G4CoulombScattering);
|
||||
}
|
||||
else {
|
||||
pmanager->AddProcess(new G4MultipleScattering,-1, 1,1); // TS - Attention use Meyer!!
|
||||
}
|
||||
|
||||
if (inclMuProcesses){ // This accounts ONLY for Mu formation!
|
||||
G4VProcess* aMuoniumFormation = new lem4MuFormation();
|
||||
pmanager->AddProcess(aMuoniumFormation);
|
||||
pmanager->SetProcessOrdering(aMuoniumFormation,idxPostStep,2);
|
||||
//pmanager->AddProcess(new lem4MuFormation, -1,-1,2); // TS Muonium formation process - shorthand
|
||||
}
|
||||
|
||||
pmanager->AddProcess(new G4MuIonisation, -1, 2,2);
|
||||
pmanager->AddProcess(new G4MuBremsstrahlung, -1, 3,3);
|
||||
pmanager->AddProcess(new G4MuPairProduction, -1, 4,4);
|
||||
//cks Change to Geant 4 default muon decay with spin (instead of using the code of Taofiq).
|
||||
// pmanager->AddProcess(new lem4AtRestSpinRotation, 1, -1, -1);
|
||||
// lem4Decay* theDecayProcess = new lem4Decay();
|
||||
// pmanager->AddProcess(theDecayProcess);
|
||||
// pmanager ->SetProcessOrderingToLast(theDecayProcess, idxAtRest);
|
||||
// pmanager ->SetProcessOrdering(theDecayProcess, idxPostStep);
|
||||
//
|
||||
// // The spin precession (rotation) at rest is already included in
|
||||
// // the G4DecayWithSpin();
|
||||
// G4AtRestSpinPrecession* theSpinPrecession = new G4AtRestSpinPrecession();
|
||||
// pmanager->AddRestProcess(theSpinPrecession);
|
||||
|
||||
|
||||
|
||||
if (particle->GetParticleName()=="mu+"){
|
||||
G4DecayWithSpin* theDecayProcess = new G4DecayWithSpin();
|
||||
//lem4DecayWithSpin* theDecayProcess = new lem4DecayWithSpin();
|
||||
pmanager->AddProcess(theDecayProcess);
|
||||
pmanager->SetProcessOrderingToLast(theDecayProcess, idxAtRest);
|
||||
pmanager->SetProcessOrdering(theDecayProcess, idxPostStep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else if ((particle->GetParticleName()=="Mu")&&(inclMuProcesses)) { // other Mu processes
|
||||
G4cout<<"\nAccounting for Muonium formation and other Mu processes.\n"<<G4endl;
|
||||
//pmanager->AddProcess(new G4MultipleScattering, -1, 1, 1);
|
||||
//pmanager->AddProcess(new lem4MuScatter, -1, 1, 1); <--- ERROR ?!?
|
||||
//pmanager->AddProcess(new lem4MuScatter, -1, -1, 1); //<--- ERROR ?!?
|
||||
|
||||
// Muonium "scattering"
|
||||
G4VProcess* aMuScatt = new lem4MuScatter();
|
||||
pmanager->AddProcess(aMuScatt);
|
||||
pmanager->SetProcessOrdering(aMuScatt, idxPostStep, 1);
|
||||
|
||||
// Muonium decay process
|
||||
G4Decay* theDecayProcess = new G4Decay();
|
||||
//lem4DecayWithSpin* theDecayProcess = new lem4DecayWithSpin();
|
||||
pmanager->AddProcess(theDecayProcess);
|
||||
pmanager->SetProcessOrderingToLast(theDecayProcess, idxAtRest);
|
||||
pmanager->SetProcessOrdering(theDecayProcess, idxPostStep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
else if (particle->GetParticleName()=="Mu")
|
||||
{
|
||||
//!
|
||||
Half of the muonium has an isotropic decay.
|
||||
//
|
||||
G4DecayTable* MuoniumDecayTable = new G4DecayTable();
|
||||
MuoniumDecayTable -> Insert(new G4MuonDecayChannelWithSpin("Mu",0.5)); // ?? with spin? LEMuSRMuonDecayChannel("Mu",0.5));
|
||||
MuoniumDecayTable -> Insert(new G4MuonDecayChannel("Mu",0.5));
|
||||
MuoniumDecayTable ->DumpInfo();
|
||||
MuoniumParticle::MuoniumDefinition() -> SetDecayTable(MuoniumDecayTable);
|
||||
|
||||
G4ProcessManager* pmanager = particle->GetProcessManager();
|
||||
if (theLEMuSRDecayProcess->IsApplicable(*particle))
|
||||
{
|
||||
pmanager ->AddProcess(theLEMuSRDecayProcess);
|
||||
pmanager ->AddProcess(aStepLimiter);
|
||||
|
||||
// set ordering
|
||||
// pmanager ->SetProcessOrdering(aStepLimiter, idxPostStep, 1); // not needed for the muonium
|
||||
pmanager ->SetProcessOrderingToLast(theLEMuSRDecayProcess, idxPostStep);
|
||||
pmanager ->SetProcessOrderingToLast(theLEMuSRDecayProcess, idxAtRest);
|
||||
}
|
||||
|
||||
pmanager->DumpInfo();
|
||||
|
||||
|
||||
} */
|
||||
|
||||
//csk
|
||||
//}
|
||||
|
||||
else if ((!particle->IsShortLived()) &&
|
||||
(particle->GetPDGCharge() != 0.0) &&
|
||||
(particle->GetParticleName() != "chargedgeantino")) {
|
||||
// All stable, charged particles except geantino
|
||||
pmanager->AddProcess(new G4MultipleScattering, -1,1,1);
|
||||
if (myTypeOfProcesses=="lowenergy") {
|
||||
pmanager->AddProcess(new G4hLowEnergyIonisation, -1,2,2);
|
||||
}
|
||||
else {
|
||||
pmanager->AddProcess(new G4hIonisation, -1,2,2);
|
||||
}
|
||||
///pmanager->AddProcess(new G4UserSpecialCuts, -1,-1,3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
|
||||
#include "G4Decay.hh"
|
||||
void lem4PhysicsList::ConstructGeneral()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
#include "G4Region.hh"
|
||||
#include "G4RegionStore.hh"
|
||||
#include "G4ProductionCuts.hh"
|
||||
|
||||
void lem4PhysicsList::SetCuts()
|
||||
{
|
||||
//G4VUserPhysicsList::SetCutsWithDefault method sets
|
||||
//the default cut value for all particle types
|
||||
//
|
||||
SetCutsWithDefault();
|
||||
|
||||
//cks Set some cuts specific to a given region:
|
||||
// G4Region* region;
|
||||
// G4String regName;
|
||||
// G4ProductionCuts* cuts;
|
||||
//
|
||||
// regName="Target_region";
|
||||
// region = G4RegionStore::GetInstance()->GetRegion(regName);
|
||||
// if (region==NULL) {
|
||||
// G4cout << "lem4PhysicsList.cc: ERROR! Region "<<regName<<" not found."<<G4endl;
|
||||
// G4cout << " Program is forced to stop!"<<G4endl;
|
||||
// exit(EXIT_FAILURE);
|
||||
// }
|
||||
// cuts = new G4ProductionCuts;
|
||||
//
|
||||
// cuts->SetProductionCut(0.005*mm,G4ProductionCuts::GetIndex("mu+"));
|
||||
// cuts->SetProductionCut(0.005*mm,G4ProductionCuts::GetIndex("e-"));
|
||||
// region->SetProductionCuts(cuts);
|
||||
//csk
|
||||
|
||||
if (verboseLevel>0) DumpCutValuesTable();
|
||||
DumpCutValuesTable();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
318
geant4/LEMuSR/src/lem4PrimaryGeneratorAction.cc
Normal file
318
geant4/LEMuSR/src/lem4PrimaryGeneratorAction.cc
Normal file
@ -0,0 +1,318 @@
|
||||
#include "lem4PrimaryGeneratorAction.hh"
|
||||
#include "lem4DetectorConstruction.hh"
|
||||
#include "lem4PrimaryGeneratorMessenger.hh"
|
||||
#include "G4Event.hh"
|
||||
#include "G4ParticleGun.hh"
|
||||
#include "G4ParticleTable.hh"
|
||||
#include "G4ParticleDefinition.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4ios.hh"
|
||||
#include "G4ParticleGun.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "globals.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4RunManager.hh"
|
||||
#include "time.h"
|
||||
#include <iomanip>
|
||||
#include "lem4RootOutput.hh" //cks for storing some info in the Root output file
|
||||
#include "lem4ErrorMessage.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
lem4PrimaryGeneratorAction::lem4PrimaryGeneratorAction(
|
||||
lem4DetectorConstruction* lem4DC)
|
||||
:lem4Detector(lem4DC), x0(0), y0(0), z0(-124*cm), xSigma(0), ySigma(0), zSigma(0),
|
||||
rMaxAllowed(1e10*mm), zMinAllowed(-1e10*mm), zMaxAllowed(1e10*mm),
|
||||
p0(0), pSigma(0), pMinAllowed(0), pMaxAllowed(1e10*mm),
|
||||
xangle0(0), yangle0(0), xangleSigma(0), yangleSigma(0), pitch(0),
|
||||
UnpolarisedMuonBeam(false), xPolarisIni(1.), yPolarisIni(0.), zPolarisIni(0.),
|
||||
muonDecayTimeMin(-1), muonDecayTimeMax(-1), muonMeanLife(2197.03*ns),
|
||||
takeMuonsFromTurtleFile(false)
|
||||
//, firstCall(true)
|
||||
{
|
||||
G4int n_particle = 1;
|
||||
//cksdel particleGun = new lem4ParticleGun(n_particle);
|
||||
particleGun = new G4ParticleGun(n_particle);
|
||||
|
||||
//create a messenger for this class
|
||||
gunMessenger = new lem4PrimaryGeneratorMessenger(this);
|
||||
|
||||
// default particle kinematic
|
||||
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
|
||||
G4ParticleDefinition* particle= particleTable->FindParticle("mu+");
|
||||
particleGun->SetParticleDefinition(particle);
|
||||
mu_mass = particle->GetPDGMass();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
lem4PrimaryGeneratorAction::~lem4PrimaryGeneratorAction()
|
||||
{
|
||||
delete particleGun;
|
||||
delete gunMessenger;
|
||||
if (takeMuonsFromTurtleFile) {fclose(fTurtleFile);}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void lem4PrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent)
|
||||
{
|
||||
// This function is called at the begining of event.
|
||||
|
||||
// // First of all check the setting of some variables. Do it only once (for the first event).
|
||||
// if (firstCall) {
|
||||
// firstCall=false;
|
||||
// char message[200];
|
||||
// cout<<"******************** called just once **********************"<<G4endl;
|
||||
// // Check that the restriction of the generated position is reasonable:
|
||||
// if ( sqrt(rMaxAllowed-x0)*(rMaxAllowed-x0)+(rMaxAllowed-y0)*(rMaxAllowed-y0) >
|
||||
// 5*sqrt(xSigma*xSigma+ySigma*ySigma) ) {
|
||||
// sprintf(message,"lem4PrimaryGeneratorAction::GeneratePrimaries: Too strict restriction on the generated radius.");
|
||||
// lem4ErrorMessage::GetInstance()->lem4Error(FATAL,"message",true);
|
||||
// }
|
||||
// // Check that the restriction on the z-coordinate of the generated postion is reasonable:
|
||||
// if ( ((-zMaxAllowed+z0) > 5*fabs(zSigma)) || ((zMinAllowed-z0) > 5*fabs(zSigma)) ) {
|
||||
// sprintf(message,"lem4PrimaryGeneratorAction::GeneratePrimaries: Too strict restriction on the generated z-coordinate.");
|
||||
// lem4ErrorMessage::GetInstance()->lem4Error(FATAL,"message",true);
|
||||
// }
|
||||
// }
|
||||
|
||||
G4double x, y, z;
|
||||
G4double p, ke_offset;
|
||||
G4double xangle, yangle;
|
||||
|
||||
ke_offset = 3.73*keV; // Kin. energy offset due to a 3.73 kV acceleration at the Carbon foil
|
||||
|
||||
if (takeMuonsFromTurtleFile) {
|
||||
char line[501];
|
||||
G4int checkNrOfCounts=0;
|
||||
do {
|
||||
float xTmp, yTmp, xAngleTmp, yAngleTmp, pTmp;
|
||||
if (feof(fTurtleFile)) {rewind(fTurtleFile);G4cout<<"End of Turtle file."<<G4endl;}
|
||||
fgets(line,500,fTurtleFile);
|
||||
// sscanf(&line[0],"%g %g %g %g %g %g %g",&x,&xangle,&y,&yangle,&p,&w,&pol);
|
||||
sscanf(&line[0],"%g %g %g %g %g",&xTmp,&xAngleTmp,&yTmp,&yAngleTmp,&pTmp);
|
||||
xangle = xAngleTmp*mrad;
|
||||
yangle = yAngleTmp*mrad;
|
||||
x = xTmp*mm + z0*xangle ; // usually z0 is negative
|
||||
y = yTmp*mm + z0*yangle ;
|
||||
p = pTmp*GeV;
|
||||
// add some beam offset and beam tilt, if requested:
|
||||
xangle = xangle + xangle0;
|
||||
yangle = yangle + yangle0;
|
||||
x = x + x0;
|
||||
y = y + y0;
|
||||
// G4cout<<": ";
|
||||
checkNrOfCounts++;
|
||||
if (checkNrOfCounts>1000) {
|
||||
G4cout<<"lem4PrimaryGeneratorAction::GeneratePrimaries: Too strict requirements on the r position!"<<G4endl;
|
||||
}
|
||||
} while( (x*x+y*y)>(rMaxAllowed*rMaxAllowed) );
|
||||
z=z0;
|
||||
// G4cout<<"x,y,z=("<<x/mm<<","<<y/mm<<","<<z/mm<<"), angles="<<xangle/mrad<<","<<yangle/mrad<<" p="<<p/MeV<<G4endl;
|
||||
}
|
||||
|
||||
else { // Generate the starting position of the muon by random
|
||||
// rMaxAllowed ... maximal radius, within which the muon can be generated
|
||||
// x0, y0, z0 ... central point around which the muons are generated
|
||||
// xSigma, ySigma, zSigma ... sigma of the (gaussian) distributions of the beam
|
||||
// x, y, z ... actual initial position of the generated muon
|
||||
|
||||
G4int checkNrOfCounts=0;
|
||||
do {
|
||||
if (xSigma>0) {x = G4RandGauss::shoot(x0,xSigma);} // Gaussian distribution
|
||||
else if (xSigma<0) {x = x0 + xSigma*(G4UniformRand()*2.-1.);} // Uniform step distribution
|
||||
else { x = x0;} // Point-like
|
||||
|
||||
if (ySigma>0) {y = G4RandGauss::shoot(y0,ySigma);}
|
||||
else if (ySigma<0) {y = y0 + ySigma*(G4UniformRand()*2.-1.);}
|
||||
else {y = y0;}
|
||||
|
||||
if (zSigma>0) {z = G4RandGauss::shoot(z0,zSigma);}
|
||||
else if (zSigma<0) {z = z0 + zSigma*(G4UniformRand()*2.-1.);}
|
||||
else {z = z0;}
|
||||
|
||||
checkNrOfCounts++;
|
||||
if (checkNrOfCounts>1000) {
|
||||
G4cout<<"lem4PrimaryGeneratorAction::GeneratePrimaries: Too strict requirements on the r or z position!"<<G4endl;
|
||||
}
|
||||
} while( ((x*x+y*y)>(rMaxAllowed*rMaxAllowed))||(z>zMaxAllowed)||(z<zMinAllowed) );
|
||||
// The generated muon has to stay within some well defined region, e.g. within the beampipe.
|
||||
|
||||
|
||||
// If the user defines energy instead of momentum
|
||||
// if (E0==0 && p0>0) {p = p0;}
|
||||
// if (E0>0 && p0==0) {p0 = std::sqrt(E0*E0 + 2*mu_mass*E0);}
|
||||
// else if (E0>0 && p0>0) {
|
||||
// G4cout<<"Define either kinetic energy or momentum, but not both!"<<G4endl;
|
||||
// G4cout << "S T O P F O R C E D" << G4endl;
|
||||
// exit(1);
|
||||
// }
|
||||
|
||||
|
||||
// Now generate the momentum
|
||||
checkNrOfCounts=0;
|
||||
do {
|
||||
if (pSigma>0) {p = G4RandGauss::shoot(p0,pSigma);}
|
||||
else {p=p0;}
|
||||
checkNrOfCounts++;
|
||||
if (checkNrOfCounts>1000) {
|
||||
G4cout<<"lem4PrimaryGeneratorAction::GeneratePrimaries: Too strict requirements on the momentum!"<<G4endl;
|
||||
}
|
||||
} while ( (p>pMaxAllowed)||(p<pMinAllowed) );
|
||||
//G4cout<<"Kamil: momentum p="<<p/MeV<<" MeV"<<G4endl;
|
||||
|
||||
// Add some initial angle (px and py component of the momentum)
|
||||
if (xangleSigma>0) { xangle = G4RandGauss::shoot(xangle0,xangleSigma); }
|
||||
else { xangle = xangle0; }
|
||||
// Add the beam tilt, which depends on the distance from the beam centre.
|
||||
if (xSigma>0) {xangle += - pitch * (x-x0)/(1*mm);} //xSigma; } // Changed to absolute units of pitch
|
||||
|
||||
if (yangleSigma>0) { yangle = G4RandGauss::shoot(yangle0,yangleSigma); }
|
||||
else { yangle = yangle0; }
|
||||
// Add the beam tilt, which depends on the distance from the beam centre.
|
||||
if (ySigma>0) {yangle += - pitch * (y-y0)/(1*mm);} //ySigma; } // Changed to absolute units of pitch
|
||||
|
||||
} // end of the part specific for the muons generated by random rather then from TURTLE
|
||||
|
||||
|
||||
// Calculate the final momentum
|
||||
G4double px, py, pz;
|
||||
px = p*sin(xangle);
|
||||
py = p*sin(yangle);
|
||||
pz = std::sqrt(p*p - px*px - py*py);
|
||||
|
||||
// Assign spin
|
||||
G4double xpolaris=0, ypolaris=0, zpolaris=0;
|
||||
if (UnpolarisedMuonBeam) {
|
||||
G4cout<<"lem4PrimaryGeneratorAction.cc: Unpolarised muon beam not yet implemented!"<<G4endl;
|
||||
G4cout<<" =========> S T O P"<<G4endl;
|
||||
exit(0);
|
||||
// xpolaris = ;
|
||||
// ypolaris = ;
|
||||
// zpolaris = ;
|
||||
}
|
||||
else {
|
||||
xpolaris = xPolarisIni;
|
||||
ypolaris = yPolarisIni;
|
||||
zpolaris = zPolarisIni;
|
||||
}
|
||||
|
||||
// if (InitialMuonPolarization==3) { // longitudinal
|
||||
// zpolaris=-1;
|
||||
// }
|
||||
// else if (InitialMuonPolarization==2) { // transverse
|
||||
// xpolaris=1;
|
||||
// }
|
||||
// else if (InitialMuonPolarization==1) { // longitudinal
|
||||
// xpolaris = -px/p;
|
||||
// ypolaris = -py/p;
|
||||
// zpolaris = -pz/p;
|
||||
// }
|
||||
// else { // transverse
|
||||
// xpolaris = -pz/p;
|
||||
// ypolaris = -py/p;
|
||||
// zpolaris = -px/p;
|
||||
// }
|
||||
|
||||
particleGun->SetParticlePosition(G4ThreeVector(x,y,z));
|
||||
//particleGun->SetParticleMomentum(G4ThreeVector(px,py,pz));
|
||||
G4double particleEnergy = std::sqrt(p*p+mu_mass*mu_mass)-mu_mass;
|
||||
particleGun->SetParticleEnergy(particleEnergy + ke_offset);
|
||||
particleGun->SetParticleMomentumDirection(G4ThreeVector(px,py,pz));
|
||||
particleGun->SetParticlePolarization(G4ThreeVector(xpolaris,ypolaris,zpolaris));
|
||||
particleGun->GeneratePrimaryVertex(anEvent);
|
||||
|
||||
// G4cout<<"lem4PrimaryGeneratorAction: Parameters:"<<G4endl;
|
||||
// G4cout<<" x0,y0,z0="<<x0/mm<<","<<y0/mm<<","<<z0/mm<<" Sigma="<<xSigma/mm<<","<<ySigma/mm<<","<<zSigma/mm<<G4endl;
|
||||
// G4cout<<" rMaxAllowed="<<rMaxAllowed/mm<<" zMaxAllowed="<<zMaxAllowed/mm<<" zMinAllowed="<<zMinAllowed/mm<<G4endl;
|
||||
// G4cout<<" p0="<<p0/MeV<<" pSigma="<<pSigma/MeV
|
||||
// <<" pMinAllowed="<<pMinAllowed/MeV<<" pMaxAllowed=<<"<<pMaxAllowed/MeV<<G4endl;
|
||||
// G4cout<<" angle0="<<xangle0/deg<<","<<yangle0/deg<<",nic"
|
||||
// <<" Sigma="<<xangleSigma/deg<<","<<yangleSigma/deg<<",nic"<<G4endl;
|
||||
// G4cout<<" pitch="<<pitch/deg<<G4endl;
|
||||
//
|
||||
// G4cout<<"lem4PrimaryGeneratorAction: Generated muon:"<<G4endl;
|
||||
// G4cout<<" x,y,z="<<x/mm<<","<<y/mm<<","<<z/mm<<" angle="<<xangle/deg<<","<< yangle/deg<<",nic"<<G4endl;
|
||||
// G4cout<<" p="<<px/MeV<<","<<py/MeV<<","<<pz/MeV<<" E="<< (particleGun->GetParticleEnergy())/MeV<<G4endl;
|
||||
// G4cout<<" polarisation="<<xpolaris<<","<<ypolaris<<","<<zpolaris<<G4endl;
|
||||
|
||||
|
||||
|
||||
|
||||
// if requested by "/gun/decaytimelimits", set the decay time of the muon such that it is within
|
||||
// the required time window. Otherwise the decay time is set internally by Geant.
|
||||
if (muonDecayTimeMax>0.) {
|
||||
// G4cout<<"muonDecayTimeMin="<<muonDecayTimeMin/ns<<" ns , muonDecayTimeMax="<<muonDecayTimeMax/ns
|
||||
// <<" ns , muonMeanLife="<<muonMeanLife/ns<<" ns."<<G4endl;
|
||||
// find the primary muon
|
||||
// G4double decaytime;
|
||||
// do { // generate the decaytime within the specified time window
|
||||
// decaytime = -muonMeanLife*log(1-G4UniformRand());
|
||||
// } while ((decaytime<muonDecayTimeMin)||(decaytime>muonDecayTimeMax));
|
||||
//
|
||||
// This algorithm should be much faster then the previous one:
|
||||
G4PrimaryParticle* generatedMuon = anEvent->GetPrimaryVertex(0)->GetPrimary(0);
|
||||
// G4double decayLowerLimit = 1-exp(-muonDecayTimeMin/muonMeanLife);
|
||||
// G4double decayUpperLimit = 1-exp(-muonDecayTimeMax/muonMeanLife);
|
||||
// G4double randomVal = G4UniformRand()*(decayUpperLimit-decayLowerLimit) + decayLowerLimit;
|
||||
// G4double decaytime = -muonMeanLife*log(1-randomVal);
|
||||
//
|
||||
// The following code is numerically more stable compared to the commented lines above:
|
||||
G4double expMin = exp(-muonDecayTimeMin/muonMeanLife);
|
||||
G4double expMax = exp(-muonDecayTimeMax/muonMeanLife);
|
||||
G4double decaytime = -muonMeanLife * log(G4UniformRand()*(expMax-expMin)+expMin);
|
||||
//
|
||||
// G4cout<<"decaytime="<<decaytime/ns<<"ns."<< G4endl;
|
||||
generatedMuon->SetProperTime(decaytime);
|
||||
}
|
||||
|
||||
// Save variables into ROOT output file:
|
||||
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
myRootOutput->SetInitialMuonParameters(x,y,z,px,py,pz,xpolaris,ypolaris,zpolaris);
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
void lem4PrimaryGeneratorAction::SetInitialMuonPolariz(G4ThreeVector vIniPol)
|
||||
{
|
||||
G4double magnitude=vIniPol.mag();
|
||||
if(magnitude<0.00000001) {
|
||||
G4cout<< "Unpolarised initial muons"<<G4endl;
|
||||
UnpolarisedMuonBeam=true;
|
||||
}
|
||||
else {
|
||||
xPolarisIni=vIniPol(0)/magnitude;
|
||||
yPolarisIni=vIniPol(1)/magnitude;
|
||||
zPolarisIni=vIniPol(2)/magnitude;
|
||||
G4cout<< "Initial Muon Polarisation set to ("<<xPolarisIni<<","<<yPolarisIni<<","<<zPolarisIni<<")"<<G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
void lem4PrimaryGeneratorAction::SetMuonDecayTimeLimits(G4ThreeVector decayTimeLimits) {
|
||||
muonDecayTimeMin = decayTimeLimits[0];
|
||||
muonDecayTimeMax = decayTimeLimits[1];
|
||||
muonMeanLife = decayTimeLimits[2];
|
||||
// store the muon decay time parameters to the Root output
|
||||
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
myRootOutput->StoreGeantParameter(2,muonDecayTimeMin/microsecond);
|
||||
myRootOutput->StoreGeantParameter(3,muonDecayTimeMax/microsecond);
|
||||
myRootOutput->StoreGeantParameter(4,muonMeanLife/microsecond);
|
||||
}
|
||||
|
||||
void lem4PrimaryGeneratorAction::SetTurtleInput(G4String turtleFileName) {
|
||||
takeMuonsFromTurtleFile = true;
|
||||
fTurtleFile = fopen(turtleFileName.c_str(),"r");
|
||||
if (fTurtleFile==NULL) {
|
||||
G4cout << "E R R O R : Failed to open TURTLE input file \"" << turtleFileName
|
||||
<<"\"."<< G4endl;
|
||||
G4cout << "S T O P F O R C E D" << G4endl;
|
||||
exit(1);
|
||||
}
|
||||
else {G4cout << "Turtle input file \"" << turtleFileName <<"\" opened."<< G4endl;}
|
||||
}
|
136
geant4/LEMuSR/src/lem4PrimaryGeneratorMessenger.cc
Normal file
136
geant4/LEMuSR/src/lem4PrimaryGeneratorMessenger.cc
Normal file
@ -0,0 +1,136 @@
|
||||
#include "lem4PrimaryGeneratorMessenger.hh"
|
||||
#include "lem4PrimaryGeneratorAction.hh"
|
||||
#include "G4UIcmdWithAString.hh"
|
||||
#include "G4UIcmdWithADoubleAndUnit.hh"
|
||||
#include "G4UIcmdWithADouble.hh"
|
||||
#include "G4UIcmdWithAnInteger.hh"
|
||||
#include "G4UIcmdWith3Vector.hh"
|
||||
#include "G4UIcmdWith3VectorAndUnit.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
lem4PrimaryGeneratorMessenger::lem4PrimaryGeneratorMessenger(lem4PrimaryGeneratorAction* lem4Gun)
|
||||
:lem4Action(lem4Gun)
|
||||
{
|
||||
setvertexCmd = new G4UIcmdWith3VectorAndUnit("/gun/vertex",this);
|
||||
setvertexCmd->SetGuidance(" Set x0, y0, z0 of the generated muons (with unit)");
|
||||
setvertexCmd->SetParameterName("mes_x0","mes_y0","mes_z0",true,true);
|
||||
setvertexCmd->SetDefaultUnit("mm");
|
||||
|
||||
setvertexSigmaCmd = new G4UIcmdWith3VectorAndUnit("/gun/vertexsigma",this);
|
||||
setvertexSigmaCmd->SetGuidance(" Set xSigma, ySigma, ySigma of the generated muons (with unit)");
|
||||
setvertexSigmaCmd->SetParameterName("mes_xSigma","mes_ySigma","mes_zSigma",true,true);
|
||||
setvertexSigmaCmd->SetDefaultUnit("mm");
|
||||
|
||||
setvertexBoundaryCmd = new G4UIcmdWith3VectorAndUnit("/gun/vertexboundary",this);
|
||||
setvertexBoundaryCmd->SetGuidance(" Set maximum allowed radius, zmin, zmax of the generated vertex (with unit)");
|
||||
setvertexBoundaryCmd->SetParameterName("mes_rMaxAllowed","mes_zMinAllowed","mes_zMaxAllowed",true,true);
|
||||
setvertexBoundaryCmd->SetDefaultUnit("mm");
|
||||
|
||||
setEnergyCmd = new G4UIcmdWithADoubleAndUnit("/gun/kenergy",this);
|
||||
setEnergyCmd->SetGuidance(" Set kinetic energy of the generated muons (with unit)");
|
||||
setEnergyCmd->SetParameterName("mes_E0",true);
|
||||
setEnergyCmd->SetDefaultUnit("keV");
|
||||
//setEnergyCmd->SetUnitCandidates("eV keV MeV GeV");
|
||||
|
||||
setMomentumCmd = new G4UIcmdWithADoubleAndUnit("/gun/momentum",this);
|
||||
setMomentumCmd->SetGuidance(" Set mean momentum of the generated muons (with unit)");
|
||||
setMomentumCmd->SetParameterName("mes_p0",true);
|
||||
setMomentumCmd->SetDefaultUnit("MeV");
|
||||
|
||||
setMomentumSmearingCmd = new G4UIcmdWithADoubleAndUnit("/gun/momentumsmearing",this);
|
||||
setMomentumSmearingCmd->SetGuidance(" Set sigma of the momentum of the generated muons (with unit)");
|
||||
setMomentumSmearingCmd->SetParameterName("mes_pSigma",true);
|
||||
setMomentumSmearingCmd->SetDefaultUnit("MeV");
|
||||
|
||||
setMomentumBoundaryCmd = new G4UIcmdWith3VectorAndUnit("/gun/momentumboundary",this);
|
||||
setMomentumBoundaryCmd->SetGuidance(" Set minimum and maximum momentum allowed (with unit, z component ignored)");
|
||||
setMomentumBoundaryCmd->SetParameterName("mes_pMinAllowed","mes_pMaxAllowed","mes_dummy",true,true);
|
||||
setMomentumBoundaryCmd->SetDefaultUnit("MeV");
|
||||
|
||||
setTiltAngleCmd = new G4UIcmdWith3VectorAndUnit("/gun/tilt",this);
|
||||
setTiltAngleCmd->SetGuidance(" Set tilt angle of the generated muons (with unit, z component ignored)");
|
||||
setTiltAngleCmd->SetParameterName("mes_xangle","mes_yangle","dummy",true,true);
|
||||
setTiltAngleCmd->SetDefaultUnit("deg");
|
||||
|
||||
setSigmaTiltAngleCmd = new G4UIcmdWith3VectorAndUnit("/gun/tiltsigma",this);
|
||||
setSigmaTiltAngleCmd->SetGuidance(" Set sigma of the tilt angle (with unit, z component ignored)");
|
||||
setSigmaTiltAngleCmd->SetParameterName("mes_xangleSigma","mes_yangleSigma","mes_zangleSigma",true,true);
|
||||
setSigmaTiltAngleCmd->SetDefaultUnit("deg");
|
||||
|
||||
setPitchCmd = new G4UIcmdWithADoubleAndUnit("/gun/pitch",this);
|
||||
setPitchCmd->SetGuidance(" Set pitch angle of the generated muons (with unit)");
|
||||
setPitchCmd->SetParameterName("mes_pitch",true);
|
||||
setPitchCmd->SetDefaultUnit("deg");
|
||||
|
||||
// setMuonPolarizCmd = new G4UIcmdWithAnInteger("/gun/muonpolarization",this);
|
||||
// setMuonPolarizCmd->SetGuidance(" Set initial mu polariz: 0=transverse, 1=longitudinal ");
|
||||
// setMuonPolarizCmd->SetParameterName("IniPol",true);
|
||||
// setMuonPolarizCmd->SetDefaultValue(0) ;
|
||||
|
||||
setMuonPolarizCmd = new G4UIcmdWith3Vector("/gun/muonPolarizVector",this);
|
||||
setMuonPolarizCmd->SetGuidance("Set initial mu polarisation as a vector (without unit)");
|
||||
setMuonPolarizCmd->SetGuidance(" The vector does not have to be normalised to 1");
|
||||
setMuonPolarizCmd->SetParameterName("mes_polarisX","mes_polarisY","mes_polarisZ",true,true);
|
||||
|
||||
setMuonDecayTimeCmd = new G4UIcmdWith3VectorAndUnit("/gun/decaytimelimits",this);
|
||||
setMuonDecayTimeCmd->SetGuidance(" Set minimum and maximum decay time and the muon mean life ");
|
||||
setMuonDecayTimeCmd->SetParameterName("decayMin","decayMax","decayTime",true,true);
|
||||
setMuonDecayTimeCmd->SetDefaultUnit("ns");
|
||||
|
||||
setTurtleCmd = new G4UIcmdWithAString("/gun/turtlefilename",this);
|
||||
setTurtleCmd->SetGuidance("Set the filename of the TURTLE input file.");
|
||||
setTurtleCmd->SetGuidance("If this varialble is set, TURTLE input will be used. for initial muons");
|
||||
setTurtleCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
lem4PrimaryGeneratorMessenger::~lem4PrimaryGeneratorMessenger()
|
||||
{
|
||||
delete setvertexCmd;
|
||||
delete setvertexSigmaCmd;
|
||||
delete setvertexBoundaryCmd;
|
||||
delete setEnergyCmd;
|
||||
delete setMomentumCmd;
|
||||
delete setMomentumSmearingCmd;
|
||||
delete setMomentumBoundaryCmd;
|
||||
delete setTiltAngleCmd;
|
||||
delete setSigmaTiltAngleCmd;
|
||||
delete setPitchCmd;
|
||||
delete setMuonPolarizCmd;
|
||||
delete setMuonDecayTimeCmd;
|
||||
delete setTurtleCmd;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void lem4PrimaryGeneratorMessenger::SetNewValue(G4UIcommand *command, G4String newValue)
|
||||
{
|
||||
if( command == setvertexCmd)
|
||||
{ lem4Action->Setvertex(setvertexCmd->GetNew3VectorValue(newValue));}
|
||||
else if( command == setvertexSigmaCmd)
|
||||
{ lem4Action->SetvertexSigma(setvertexSigmaCmd->GetNew3VectorValue(newValue));}
|
||||
else if( command == setvertexBoundaryCmd)
|
||||
{ lem4Action->SetvertexBoundary(setvertexBoundaryCmd->GetNew3VectorValue(newValue));}
|
||||
else if( command == setEnergyCmd)
|
||||
{ lem4Action->SetEnergy(setEnergyCmd->GetNewDoubleValue(newValue));}
|
||||
else if( command == setMomentumCmd)
|
||||
{ lem4Action->SetMomentum(setMomentumCmd->GetNewDoubleValue(newValue));}
|
||||
else if( command == setMomentumSmearingCmd)
|
||||
{ lem4Action->SetMomentumSmearing(setMomentumSmearingCmd->GetNewDoubleValue(newValue));}
|
||||
else if( command == setMomentumBoundaryCmd)
|
||||
{ lem4Action->SetMomentumBoundary(setMomentumBoundaryCmd->GetNew3VectorValue(newValue));}
|
||||
else if( command == setTiltAngleCmd)
|
||||
{ lem4Action->SetTilt(setTiltAngleCmd->GetNew3VectorValue(newValue));}
|
||||
else if( command == setSigmaTiltAngleCmd)
|
||||
{ lem4Action->SetSigmaTilt(setSigmaTiltAngleCmd->GetNew3VectorValue(newValue));}
|
||||
else if( command == setPitchCmd)
|
||||
{ lem4Action->SetPitch(setPitchCmd->GetNewDoubleValue(newValue));}
|
||||
else if( command == setMuonPolarizCmd)
|
||||
{ lem4Action->SetInitialMuonPolariz(setMuonPolarizCmd->GetNew3VectorValue(newValue));}
|
||||
else if( command == setMuonDecayTimeCmd)
|
||||
{ lem4Action->SetMuonDecayTimeLimits(setMuonDecayTimeCmd->GetNew3VectorValue(newValue)); }
|
||||
else if ( command == setTurtleCmd)
|
||||
{ lem4Action->SetTurtleInput(newValue); }
|
||||
}
|
353
geant4/LEMuSR/src/lem4RootOutput.cc
Normal file
353
geant4/LEMuSR/src/lem4RootOutput.cc
Normal file
@ -0,0 +1,353 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "lem4RootOutput.hh"
|
||||
#include "G4RunManager.hh"
|
||||
#include "G4Run.hh"
|
||||
//#include "globals.hh"
|
||||
#include "lem4ErrorMessage.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4RootOutput::lem4RootOutput() {
|
||||
pointerToRoot=this;
|
||||
boolIsAnySpecialSaveVolumeDefined=false;
|
||||
nFieldNomVal=0;
|
||||
|
||||
// SensDetectorMapping["log_ScintBU"]=1;
|
||||
// SensDetectorMapping["log_ScintBD"]=2;
|
||||
// SensDetectorMapping["log_ScintBL"]=3;
|
||||
// SensDetectorMapping["log_ScintBR"]=4;
|
||||
// SensDetectorMapping["log_ScintFU"]=5;
|
||||
// SensDetectorMapping["log_ScintFD"]=6;
|
||||
// SensDetectorMapping["log_ScintFL"]=7;
|
||||
// SensDetectorMapping["log_ScintFR"]=8;
|
||||
|
||||
// SensDetectorMapping["logicScintBU"]=1;
|
||||
// SensDetectorMapping["logicScintBD"]=2;
|
||||
// SensDetectorMapping["logicScintBL"]=3;
|
||||
// SensDetectorMapping["logicScintBR"]=4;
|
||||
// SensDetectorMapping["logicScintFU"]=5;
|
||||
// SensDetectorMapping["logicScintFD"]=6;
|
||||
// SensDetectorMapping["logicScintFL"]=7;
|
||||
// SensDetectorMapping["logicScintFR"]=8;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4RootOutput::~lem4RootOutput() {}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4RootOutput* lem4RootOutput::pointerToRoot=0;
|
||||
lem4RootOutput* lem4RootOutput::GetRootInstance() {
|
||||
return pointerToRoot;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4bool lem4RootOutput::store_runID = true;
|
||||
G4bool lem4RootOutput::store_eventID = true;
|
||||
G4bool lem4RootOutput::store_BFieldAtDecay = true;
|
||||
G4bool lem4RootOutput::store_muIniPosX = true;
|
||||
G4bool lem4RootOutput::store_muIniPosY = true;
|
||||
G4bool lem4RootOutput::store_muIniPosZ = true;
|
||||
G4bool lem4RootOutput::store_muIniMomX = true;
|
||||
G4bool lem4RootOutput::store_muIniMomY = true;
|
||||
G4bool lem4RootOutput::store_muIniMomZ = true;
|
||||
G4bool lem4RootOutput::store_muIniPolX = true;
|
||||
G4bool lem4RootOutput::store_muIniPolY = true;
|
||||
G4bool lem4RootOutput::store_muIniPolZ = true;
|
||||
G4bool lem4RootOutput::store_muDecayDetID= true;
|
||||
G4bool lem4RootOutput::store_muDecayPosX = true;
|
||||
G4bool lem4RootOutput::store_muDecayPosY = true;
|
||||
G4bool lem4RootOutput::store_muDecayPosZ = true;
|
||||
G4bool lem4RootOutput::store_muDecayTime = true;
|
||||
G4bool lem4RootOutput::store_muDecayPolX = true;
|
||||
G4bool lem4RootOutput::store_muDecayPolY = true;
|
||||
G4bool lem4RootOutput::store_muDecayPolZ = true;
|
||||
G4bool lem4RootOutput::store_muTargetTime = true;
|
||||
G4bool lem4RootOutput::store_muTargetPolX = true;
|
||||
G4bool lem4RootOutput::store_muTargetPolY = true;
|
||||
G4bool lem4RootOutput::store_muTargetPolZ = true;
|
||||
G4bool lem4RootOutput::store_posIniMomX = true;
|
||||
G4bool lem4RootOutput::store_posIniMomY = true;
|
||||
G4bool lem4RootOutput::store_posIniMomZ = true;
|
||||
G4bool lem4RootOutput::store_globalTime = true;
|
||||
G4bool lem4RootOutput::store_fieldValue = true;
|
||||
G4bool lem4RootOutput::store_det_ID = true;
|
||||
G4bool lem4RootOutput::store_det_edep = true;
|
||||
G4bool lem4RootOutput::store_det_edep_el = true;
|
||||
G4bool lem4RootOutput::store_det_edep_pos = true;
|
||||
G4bool lem4RootOutput::store_det_edep_gam = true;
|
||||
G4bool lem4RootOutput::store_det_edep_mup = true;
|
||||
G4bool lem4RootOutput::store_det_nsteps = true;
|
||||
G4bool lem4RootOutput::store_det_length = true;
|
||||
G4bool lem4RootOutput::store_det_start = true;
|
||||
G4bool lem4RootOutput::store_det_end = true;
|
||||
G4bool lem4RootOutput::store_det_x = true;
|
||||
G4bool lem4RootOutput::store_det_y = true;
|
||||
G4bool lem4RootOutput::store_det_z = true;
|
||||
G4bool lem4RootOutput::store_fieldNomVal = true;
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4RootOutput::BeginOfRunAction() {
|
||||
G4cout << "lem4RootOutput::BeginOfRunAction() Defining Root tree and branches ..."<<G4endl;
|
||||
G4int tmpRunNr=(G4RunManager::GetRunManager())->GetCurrentRun()->GetRunID();
|
||||
char RootOutputFileName[200];
|
||||
sprintf(RootOutputFileName, "data/lem4_%i.root", tmpRunNr);
|
||||
// G4cout<<"RootOutputFileName="<<RootOutputFileName<<"----"<<G4endl;
|
||||
// rootFile=new TFile("lem4.root","update");
|
||||
rootFile=new TFile(RootOutputFileName,"recreate");
|
||||
rootTree=new TTree("t1","a simple Tree with simple variables");
|
||||
if (store_runID) {rootTree->Branch("runID",&runID_t,"runID/I");}
|
||||
if (store_eventID) {rootTree->Branch("eventID",&eventID_t,"eventID/I");}
|
||||
if (store_BFieldAtDecay){rootTree->Branch("BFieldAtDecay",&B_t,"Bx/D:By:Bz:B3:B4:B5");}
|
||||
if (store_muIniPosX) {rootTree->Branch("muIniPosX",&muIniPosX_t,"muIniPosX/D");}
|
||||
if (store_muIniPosY) {rootTree->Branch("muIniPosY",&muIniPosY_t,"muIniPosY/D");}
|
||||
if (store_muIniPosZ) {rootTree->Branch("muIniPosZ",&muIniPosZ_t,"muIniPosZ/D");}
|
||||
if (store_muIniMomX) {rootTree->Branch("muIniMomX",&muIniMomX_t,"muIniMomX/D");}
|
||||
if (store_muIniMomY) {rootTree->Branch("muIniMomY",&muIniMomY_t,"muIniMomY/D");}
|
||||
if (store_muIniMomZ) {rootTree->Branch("muIniMomZ",&muIniMomZ_t,"muIniMomZ/D");}
|
||||
if (store_muIniPolX) {rootTree->Branch("muIniPolX",&muIniPolX_t,"muIniPolX/D");}
|
||||
if (store_muIniPolY) {rootTree->Branch("muIniPolY",&muIniPolY_t,"muIniPolY/D");}
|
||||
if (store_muIniPolZ) {rootTree->Branch("muIniPolZ",&muIniPolZ_t,"muIniPolZ/D");}
|
||||
if (store_muDecayDetID) {rootTree->Branch("muDecayDetID",&muDecayDetID_t,"muDecayDetID/I");}
|
||||
if (store_muDecayPosX) {rootTree->Branch("muDecayPosX",&muDecayPosX_t,"muDecayPosX/D");}
|
||||
if (store_muDecayPosY) {rootTree->Branch("muDecayPosY",&muDecayPosY_t,"muDecayPosY/D");}
|
||||
if (store_muDecayPosZ) {rootTree->Branch("muDecayPosZ",&muDecayPosZ_t,"muDecayPosZ/D");}
|
||||
if (store_muDecayTime) {rootTree->Branch("muDecayTime",&muDecayTime_t,"muDecayTime/D");}
|
||||
if (store_muDecayPolX) {rootTree->Branch("muDecayPolX",&muDecayPolX_t,"muDecayPolX/D");}
|
||||
if (store_muDecayPolY) {rootTree->Branch("muDecayPolY",&muDecayPolY_t,"muDecayPolY/D");}
|
||||
if (store_muDecayPolZ) {rootTree->Branch("muDecayPolZ",&muDecayPolZ_t,"muDecayPolZ/D");}
|
||||
if (store_muTargetTime) {rootTree->Branch("muTargetTime",&muTargetTime_t,"muTargetTime/D");}
|
||||
if (store_muTargetPolX) {rootTree->Branch("muTargetPolX",&muTargetPolX_t,"muTargetPolX/D");}
|
||||
if (store_muTargetPolY) {rootTree->Branch("muTargetPolY",&muTargetPolY_t,"muTargetPolY/D");}
|
||||
if (store_muTargetPolZ) {rootTree->Branch("muTargetPolZ",&muTargetPolZ_t,"muTargetPolZ/D");}
|
||||
if (store_posIniMomX) {rootTree->Branch("posIniMomX",&posIniMomx_t,"posIniMomX/D");}
|
||||
if (store_posIniMomY) {rootTree->Branch("posIniMomY",&posIniMomy_t,"posIniMomY/D");}
|
||||
if (store_posIniMomZ) {rootTree->Branch("posIniMomZ",&posIniMomz_t,"posIniMomZ/D");}
|
||||
if (store_globalTime) {rootTree->Branch("globalTime",&globalTime_t,"globalTime/D");}
|
||||
if (store_fieldValue) {rootTree->Branch("fieldValue",&fieldValue_t,"fieldValue/D");}
|
||||
|
||||
// rootTree->Branch("nSubTracks",&nSubTracks,"nSubTracks/I");
|
||||
// rootTree->Branch("particleID",&particleID_t,"particleID[nSubTracks]/I");
|
||||
// rootTree->Branch("trackID",&trackID_t,"trackID[nSubTracks]/I");
|
||||
// rootTree->Branch("logicalVolumeID",&logicalVolumeID_t,"logicalVolumeID[nSubTracks]/I");
|
||||
// rootTree->Branch("edep",&edep_t,"edep[nSubTracks]/D");
|
||||
// rootTree->Branch("x",&x_t,"x[nSubTracks]/D");
|
||||
// rootTree->Branch("y",&y_t,"y[nSubTracks]/D");
|
||||
// rootTree->Branch("z",&z_t,"z[nSubTracks]/D");
|
||||
// rootTree->Branch("post_x",&post_x_t,"post_x[nSubTracks]/D");
|
||||
// rootTree->Branch("post_y",&post_y_t,"post_y[nSubTracks]/D");
|
||||
// rootTree->Branch("post_z",&post_z_t,"post_z[nSubTracks]/D");
|
||||
// rootTree->Branch("kineticEnergy",&kineticEnergy_t,"kineticEnergy[nSubTracks]/D");
|
||||
// rootTree->Branch("stepLength",&stepLength_t,"stepLength[nSubTracks]/D");
|
||||
// rootTree->Branch("nrOfSubsteps",&nrOfSubsteps_t,"nrOfSubsteps[nSubTracks]/I");
|
||||
|
||||
rootTree->Branch("det_n",&det_n,"det_n/I");
|
||||
if (store_det_ID) {rootTree->Branch("det_ID",&det_ID,"det_ID[det_n]/I");}
|
||||
if (store_det_edep) {rootTree->Branch("det_edep",&det_edep,"det_edep[det_n]/D");}
|
||||
if (store_det_edep_el) {rootTree->Branch("det_edep_el",&det_edep_el,"det_edep_el[det_n]/D");}
|
||||
if (store_det_edep_pos) {rootTree->Branch("det_edep_pos",&det_edep_pos,"det_edep_pos[det_n]/D");}
|
||||
if (store_det_edep_gam) {rootTree->Branch("det_edep_gam",&det_edep_gam,"det_edep_gam[det_n]/D");}
|
||||
if (store_det_edep_mup) {rootTree->Branch("det_edep_mup",&det_edep_mup,"det_edep_mup[det_n]/D");}
|
||||
if (store_det_nsteps) {rootTree->Branch("det_nsteps",&det_nsteps,"det_nsteps[det_n]/I");}
|
||||
if (store_det_length) {rootTree->Branch("det_length",&det_length,"det_length[det_n]/D");}
|
||||
if (store_det_start) {rootTree->Branch("det_time_start",&det_time_start,"det_time_start[det_n]/D");}
|
||||
if (store_det_end) {rootTree->Branch("det_time_end",&det_time_end,"det_time_end[det_n]/D");}
|
||||
if (store_det_x) {rootTree->Branch("det_x",&det_x,"det_x[det_n]/D");}
|
||||
if (store_det_y) {rootTree->Branch("det_y",&det_y,"det_y[det_n]/D");}
|
||||
if (store_det_z) {rootTree->Branch("det_z",&det_z,"det_z[det_n]/D");}
|
||||
|
||||
if (boolIsAnySpecialSaveVolumeDefined) {
|
||||
rootTree->Branch("save_n",&save_n,"save_n/I");
|
||||
rootTree->Branch("save_detID",&save_detID,"save_detID[save_n]/I");
|
||||
rootTree->Branch("save_particleID",&save_particleID,"save_particleID[save_n]/I");
|
||||
rootTree->Branch("save_ke",&save_ke,"save_ke[save_n]/D");
|
||||
rootTree->Branch("save_x", &save_x, "save_x[save_n]/D");
|
||||
rootTree->Branch("save_y", &save_y, "save_y[save_n]/D");
|
||||
rootTree->Branch("save_z", &save_z, "save_z[save_n]/D");
|
||||
rootTree->Branch("save_px",&save_px,"save_px[save_n]/D");
|
||||
rootTree->Branch("save_py",&save_py,"save_py[save_n]/D");
|
||||
rootTree->Branch("save_pz",&save_pz,"save_pz[save_n]/D");
|
||||
}
|
||||
|
||||
// htest1 = new TH1F("htest1","The debugging histogram 1",50,-4.,4.);
|
||||
// htest2 = new TH1F("htest2","The debugging histogram 2",50,0.,3.142);
|
||||
htest1 = new TH2F("htest1","x, y",50,-200.,200.,50,-200.,200.);
|
||||
htest2 = new TH2F("htest2","R, z",50,0.,250.,50,-150.,150.);
|
||||
htest3 = new TH1F("htest3","Energy in MeV",55,0.,55.);
|
||||
htest4 = new TH1F("htest4","Radioactive electron kinetic energy",250,0.,2.5);
|
||||
htest5 = new TH1F("htest5","The debugging histogram 5",50,-4.,4.);
|
||||
htest6 = new TH1F("htest6","The debugging histogram 6",50,0.,3.142);
|
||||
htest7 = new TH1F("htest7","The debugging histogram 7",50,-4.,4.);
|
||||
htest8 = new TH1F("htest8","The debugging histogram 8",50,0.,3.142);
|
||||
|
||||
G4cout << "lem4RootOutput::BeginOfRunAction() Root tree and branches were defined.\n"<<G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
void lem4RootOutput::EndOfRunAction() {
|
||||
G4cout << "\nlem4RootOutput::EndOfRunAction() - Writing out the Root tree ..."<<G4endl;
|
||||
rootTree->Write();
|
||||
htest1->Write();
|
||||
htest2->Write();
|
||||
htest3->Write();
|
||||
htest4->Write();
|
||||
htest5->Write();
|
||||
htest6->Write();
|
||||
htest7->Write();
|
||||
htest8->Write();
|
||||
// Variables exported from Geant simulation to the Root output
|
||||
// static const Int_t nGeantParamD=10;
|
||||
TVectorD TVector_GeantParametersD(maxNGeantParameters);
|
||||
for (Int_t i=0; i<maxNGeantParameters; i++) {
|
||||
TVector_GeantParametersD[i]=GeantParametersD[i];
|
||||
}
|
||||
TVector_GeantParametersD.Write("geantParametersD");
|
||||
rootFile->Close();
|
||||
G4cout<<"lem4RootOutput::EndOfRunAction() - Root tree written out.\n"<<G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4RootOutput::FillEvent() {
|
||||
// G4cout << "hhhhh: lem4RootOutput::FillEvent()"<<G4endl;
|
||||
// G4cout<<"Kamil: Fill the Root Tree:"<<G4endl;
|
||||
// G4ThreeVector ttt=(posIniMomx_t,posIniMomy_t,posIniMomz_t);
|
||||
// htest5->Fill(atan2(ttt.y(),ttt.x()));
|
||||
// htest6->Fill(atan2(sqrt(ttt.x()*ttt.x()+ttt.y()*ttt.y()),ttt.z()));
|
||||
htest5->Fill(atan2(posIniMomy_t,posIniMomx_t));
|
||||
htest6->Fill(atan2(sqrt(posIniMomx_t*posIniMomx_t+posIniMomy_t*posIniMomy_t),posIniMomz_t));
|
||||
// G4double PolModulus=sqrt(muDecayPolX_t*muDecayPolX_t+muDecayPolY_t*muDecayPolY_t+muDecayPolZ_t*muDecayPolZ_t);
|
||||
// G4double PolModulus0=sqrt(muTargetPolX_t*muTargetPolX_t+muTargetPolY_t*muTargetPolY_t+muTargetPolZ_t*muTargetPolZ_t);
|
||||
// if ((muPolx_t>1.0001)||((muPolx_t<-1.0001)&&(muPolx_t>-999.))||(muPolx0_t>1.0001)||((muPolx0_t<-1.0001)&&(muPolx0_t>-999.))) {
|
||||
// if ((PolModulus>1.001)||((PolModulus0>1.001)&&(muTargetTime_t>-999))) {
|
||||
// G4cout <<"lem4RootOutput.cc: Strange polarisation in run="<<runID_t<<" event="<<eventID_t
|
||||
// <<" PolModulus="<<PolModulus<<" PolModulus0="<<PolModulus0<<G4endl;
|
||||
// G4cout <<" muPol=("<<muDecayPolX_t<<","<<muDecayPolY_t<<","<<muDecayPolZ_t<<");"
|
||||
// <<" mupol0=("<<muPolx0_t<<","<<muPoly0_t<<","<<muPolz0_t<<");"<<G4endl;
|
||||
// }
|
||||
// G4cout << "eventID="<<eventID_t<<"; Deposited E (el, pos, gam, mu)="<<det_edep_el<<", "
|
||||
// << det_edep_pos<<", "<< det_edep_gam<<", "<< det_edep_mup<<G4endl;
|
||||
// G4cout<<"fieldValue="<<fieldValue_t<<G4endl;
|
||||
rootTree->Fill();
|
||||
// G4cout<<"Kamil: end of Filling the Root Tree:"<<G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4RootOutput::ClearAllRootVariables() {
|
||||
runID_t=-1000;
|
||||
eventID_t=-1000;
|
||||
B_t[0]=-1000.;B_t[1]=-1000.;B_t[2]=-1000.;B_t[3]=-1000.;B_t[4]=-1000.;B_t[5]=-1000.;
|
||||
muIniPosX_t=-1000; muIniPosY_t=-1000; muIniPosZ_t=-1000;
|
||||
muIniMomX_t=-1000; muIniMomY_t=-1000; muIniMomZ_t=-1000;
|
||||
muIniPolX_t=-1000; muIniPolY_t=-1000; muIniPolZ_t=-1000;
|
||||
muDecayDetID_t=-1000;
|
||||
muDecayPolX_t=-1000; muDecayPolY_t=-1000; muDecayPolZ_t=-1000;
|
||||
muTargetPolX_t=-1000; muTargetPolY_t=-1000; muTargetPolZ_t=-1000;
|
||||
muDecayPosX_t=-1000;muDecayPosY_t=-1000;muDecayPosZ_t=-1000;
|
||||
muDecayTime_t=-1000;
|
||||
posIniMomx_t=-1000;posIniMomy_t=-1000;posIniMomz_t=-1000;
|
||||
globalTime_t=-1000;
|
||||
fieldValue_t=-1000;
|
||||
muTargetTime_t=-1000;
|
||||
|
||||
// nSubTracks=0;
|
||||
// for (G4int i=0; i<maxNSubTracks; i++) {
|
||||
// particleID_t[i]=-1000;
|
||||
// trackID_t[i]=-1000;
|
||||
// logicalVolumeID_t[i]=-1000;
|
||||
// edep_t[i]=-1000;
|
||||
// x_t[i]=-1000;
|
||||
// y_t[i]=-1000;
|
||||
// z_t[i]=-1000;
|
||||
// post_x_t[i]=-1000;
|
||||
// post_y_t[i]=-1000;
|
||||
// post_z_t[i]=-1000;
|
||||
// kineticEnergy_t[i]=-1000;
|
||||
// stepLength_t[i]=-1000;
|
||||
// nrOfSubsteps_t[i]=-1000;
|
||||
// }
|
||||
|
||||
det_n=0;
|
||||
// for (G4int i=0; i<NrOfLogicalVolumes; i++) {
|
||||
// det_ID[i]=-1000;
|
||||
// det_edep[i]=-1000;
|
||||
// det_nsteps[i]=-1000;
|
||||
// det_length[i]=-1000;
|
||||
// }
|
||||
|
||||
save_n=0;
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
void lem4RootOutput::SetVolumeIDMapping(std::string logivol, int volumeID) {
|
||||
// This function assigns a unique number to each sensitive detector name.
|
||||
// The numbers are used in the root tree, as it is easier to work with numbers
|
||||
// rather than with strings.
|
||||
if (SensDetectorMapping[logivol]) {
|
||||
char message[100];
|
||||
sprintf(message,"lem4RootOutput::SetVolumeIDMapping: Sensitive volume %s already assigned.",logivol.c_str());
|
||||
lem4ErrorMessage::GetInstance()->lem4Error(FATAL,message,false);
|
||||
}
|
||||
else{
|
||||
SensDetectorMapping[logivol]=volumeID;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4int lem4RootOutput::ConvertVolumeToID(std::string logivol) {
|
||||
G4int volumeID = SensDetectorMapping[logivol];
|
||||
if (volumeID==0) {
|
||||
char message[100];
|
||||
sprintf(message,"lem4RootOutput::ConvertVolumeToID: No ID number assigned to sensitive volume %s .",logivol.c_str());
|
||||
lem4ErrorMessage::GetInstance()->lem4Error(SERIOUS,"message",true);
|
||||
}
|
||||
return volumeID;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4RootOutput::SetSaveDetectorInfo (G4int ID, G4int particleID, G4double ke,
|
||||
G4double x, G4double y, G4double z, G4double px, G4double py, G4double pz) {
|
||||
if (save_n>=save_nMax) {
|
||||
char message[200];
|
||||
sprintf(message,"lem4RootOutput.cc::SetSaveDetectorInfo(): more \"save\" hits then allowed: save_nMax=%i",save_nMax);
|
||||
lem4ErrorMessage::GetInstance()->lem4Error(SERIOUS,message,true);
|
||||
}
|
||||
else {
|
||||
save_detID[save_n]=ID;
|
||||
save_particleID[save_n]=particleID;
|
||||
save_ke[save_n]=ke/keV;
|
||||
save_x[save_n]=x/mm;
|
||||
save_y[save_n]=y/mm;
|
||||
save_z[save_n]=z/mm;
|
||||
save_px[save_n]=px/MeV;
|
||||
save_py[save_n]=py/MeV;
|
||||
save_pz[save_n]=pz/MeV;
|
||||
|
||||
save_n++;
|
||||
}
|
||||
}
|
||||
|
||||
void lem4RootOutput::SetFieldNomVal(G4int i, G4double value) {
|
||||
if (i<maxNFieldnNominalValues) {
|
||||
fieldNomVal[i]=value/tesla; /// ATTENTION CHANGE BEFORE, TO ACCOUNT FOR EM FIELDS !! TS
|
||||
}
|
||||
else {
|
||||
char message[200];
|
||||
sprintf(message,
|
||||
"lem4RootOutput.cc::SetFieldNomVal(): more electromagnetic fields then allowed: maxNFieldnNominalValues=%i",
|
||||
maxNFieldnNominalValues);
|
||||
lem4ErrorMessage::GetInstance()->lem4Error(SERIOUS,message,true);
|
||||
}
|
||||
}
|
||||
|
85
geant4/LEMuSR/src/lem4RunAction.cc
Normal file
85
geant4/LEMuSR/src/lem4RunAction.cc
Normal file
@ -0,0 +1,85 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
// Make G4Timer appear first!
|
||||
#include "G4Timer.hh"
|
||||
#include "lem4RunAction.hh"
|
||||
#include "lem4EventAction.hh"
|
||||
#include "G4Run.hh"
|
||||
#include "lem4ErrorMessage.hh"
|
||||
#include "F04GlobalField.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4RunAction::lem4RunAction() {
|
||||
timer = new G4Timer;
|
||||
}
|
||||
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4RunAction::~lem4RunAction() {
|
||||
delete timer;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4RunAction::BeginOfRunAction(const G4Run* aRun) {
|
||||
timer->Start();
|
||||
G4int run_id= aRun->GetRunID();
|
||||
// if (run_id%100 == 0) {
|
||||
G4cout << "### Run " << run_id << G4endl;
|
||||
// }
|
||||
// Set nr. of events that will be processed in this run to lem4EventAction class, as it will
|
||||
// be needed for the time dependent magnetic field;
|
||||
lem4EventAction* pointerToEventAction = lem4EventAction::GetInstance();
|
||||
pointerToEventAction->SetNumberOfEventsInThisRun(aRun->GetNumberOfEventToBeProcessed());
|
||||
//
|
||||
lem4RootOutput::GetRootInstance()->BeginOfRunAction();
|
||||
//
|
||||
// Initiate global electromagnetic field (if it exists):
|
||||
if (F04GlobalField::Exists()) {
|
||||
FieldList* fields = F04GlobalField::getObject()->getFields();
|
||||
|
||||
if (fields) {
|
||||
if (fields->size()>0) {
|
||||
G4int jjj=0;
|
||||
G4cout<<"\n------------ The following fields were defined: ----------------\n"<<G4endl;
|
||||
FieldList::iterator i;
|
||||
for (i=fields->begin(); i!=fields->end(); ++i) {
|
||||
(*i)->construct();
|
||||
// Get the nominal field value for the given field and store it in the Root output
|
||||
G4double nomFieldValue = (*i)->GetNominalFieldValue();
|
||||
lem4RootOutput::GetRootInstance()->SetFieldNomVal(jjj,nomFieldValue);
|
||||
jjj++;
|
||||
}
|
||||
G4cout<<"-----------------------------------------------------------------"<<G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Print out the field values at the points user requested to be printed out:
|
||||
F04GlobalField::getObject()->PrintFieldAtRequestedPoints();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4RunAction::EndOfRunAction(const G4Run* aRun) {
|
||||
lem4RootOutput::GetRootInstance()->EndOfRunAction();
|
||||
lem4ErrorMessage::GetInstance()->PrintErrorSummary();
|
||||
timer->Stop();
|
||||
G4cout << "lem4RunAction::EndOfRunAction:"<<G4endl;
|
||||
G4cout << " Number of events = " << aRun->GetNumberOfEvent()<<G4endl;
|
||||
// << " " << *timer << G4endl;
|
||||
G4cout << " User elapsed time = "<<timer->GetUserElapsed()/3600<<"h = "
|
||||
<<timer->GetUserElapsed()/60<<"min = "<<timer->GetUserElapsed()<<"s."<<G4endl;
|
||||
G4cout << " Real elapsed time = "<<timer->GetRealElapsed()/3600<<"h = "
|
||||
<<timer->GetRealElapsed()/60<<"min = "<<timer->GetRealElapsed()<<"s."<<G4endl;
|
||||
G4cout << " System elapsed time = "<<timer->GetSystemElapsed()/3600<<"h = "
|
||||
<<timer->GetSystemElapsed()/60<<"min = "<<timer->GetSystemElapsed()<<"s."<<G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
|
156
geant4/LEMuSR/src/lem4ScintHit.cc
Normal file
156
geant4/LEMuSR/src/lem4ScintHit.cc
Normal file
@ -0,0 +1,156 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "lem4ScintHit.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4VVisManager.hh"
|
||||
#include "G4Circle.hh"
|
||||
#include "G4Colour.hh"
|
||||
#include "G4VisAttributes.hh"
|
||||
#include "G4ios.hh"
|
||||
#include "G4MagneticField.hh"
|
||||
#include "G4FieldManager.hh"
|
||||
#include "G4TransportationManager.hh"
|
||||
#include "globals.hh"
|
||||
#include "G4Transform3D.hh"
|
||||
#include "G4ProcessManager.hh"
|
||||
#include "G4Track.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4RunManager.hh"
|
||||
#include "G4Run.hh"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
G4Allocator<lem4ScintHit> lem4ScintHitAllocator;
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4ScintHit::lem4ScintHit() {
|
||||
}
|
||||
|
||||
G4int lem4ScintHit::ScintMultihit=0;
|
||||
G4int lem4ScintHit::runIDoldScint=-1;
|
||||
G4int lem4ScintHit::eventIDoldScint=-1;
|
||||
G4int lem4ScintHit::NIS=0;
|
||||
G4int lem4ScintHit::ScintChamberNbold=-1;
|
||||
G4int lem4ScintHit::verboseLevel=0;
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4ScintHit::~lem4ScintHit() {
|
||||
//save the Tree header. The file will be automatically closed
|
||||
//when going out of the function scope
|
||||
// rootTree->Write();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4ScintHit::lem4ScintHit(const lem4ScintHit& right)
|
||||
: G4VHit()
|
||||
{
|
||||
particleName = right.particleName;
|
||||
trackID = right.trackID;
|
||||
edep = right.edep;
|
||||
pre_pos = right.pre_pos;
|
||||
pol = right.pol;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
const lem4ScintHit& lem4ScintHit::operator=(const lem4ScintHit& right)
|
||||
{
|
||||
particleName = right.particleName;
|
||||
trackID = right.trackID;
|
||||
edep = right.edep;
|
||||
pre_pos = right.pre_pos;
|
||||
pol = right.pol;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4int lem4ScintHit::operator==(const lem4ScintHit& right) const
|
||||
{
|
||||
return (this==&right) ? 1 : 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4ScintHit::Draw()
|
||||
{
|
||||
G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
|
||||
if(pVVisManager)
|
||||
{
|
||||
G4Circle circle(pre_pos);
|
||||
circle.SetScreenSize(0.04);
|
||||
circle.SetFillStyle(G4Circle::filled);
|
||||
G4Colour colour(1.,0.,0.);
|
||||
G4VisAttributes attribs(colour);
|
||||
circle.SetVisAttributes(attribs);
|
||||
pVVisManager->Draw(circle);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4ScintHit::Print()
|
||||
{
|
||||
if (verboseLevel>2) G4cout<<"VERBOSE 3: Kamil: lem4ScintHit::Print()"<<G4endl;
|
||||
|
||||
G4RunManager* fRunManager = G4RunManager::GetRunManager();
|
||||
eventID = fRunManager->GetCurrentEvent()->GetEventID();
|
||||
runID = fRunManager->GetCurrentRun()->GetRunID();
|
||||
G4int ScintMultihitSwitch=0;
|
||||
|
||||
if (runID != runIDoldScint) {
|
||||
NIS=0;
|
||||
ScintMultihit = 0;
|
||||
eventIDoldScint = -1;
|
||||
ScintChamberNbold = -1;
|
||||
}
|
||||
|
||||
//cks if (particleName== "e+" and (eventIDoldScint != eventID or ScintChamberNbold != IBchamberNb)) {
|
||||
if (particleName== "e+") {
|
||||
if (eventIDoldScint == eventID) {
|
||||
ScintMultihit++;
|
||||
ScintMultihitSwitch=1;
|
||||
}
|
||||
NIS++;
|
||||
|
||||
G4FieldManager *fMgr=G4TransportationManager::GetTransportationManager()->GetFieldManager();
|
||||
point[0]=0.;
|
||||
point[1]=0.;
|
||||
point[2]=0.;
|
||||
B[2]=0.0;
|
||||
if(!fMgr->DoesFieldChangeEnergy()) { //then we have a magnetic field
|
||||
mfield = fMgr->GetDetectorField();
|
||||
mfield->GetFieldValue(point,B);
|
||||
B[0]=B[0]/tesla;
|
||||
B[1]=B[1]/tesla;
|
||||
B[2]=B[2]/tesla;
|
||||
}
|
||||
// G4cout << " Segment: " << IBchamberNb << G4endl;
|
||||
// G4cout <<"Position " << pos.x()/cm<<" "<<pos.y()/cm <<" "<< pos.z()/cm <<G4endl;
|
||||
// G4cout << "Field is "<< B[2]<<G4endl;
|
||||
|
||||
std::ofstream posfile1;
|
||||
posfile1.open ("scint.dat", std::ios::out | std::ios::app);
|
||||
posfile1 << runID << " " << eventID
|
||||
<< " " << logicalVolume
|
||||
<< " " << ScintMultihitSwitch
|
||||
<<" " << edep
|
||||
<< " " << fabs(B[2])
|
||||
<<" "<< pre_pos.x()/cm<<" "<<pre_pos.y()/cm <<" "<< pre_pos.z()/cm
|
||||
<< " " << globalTime/s
|
||||
// << " " << IBchamberNb
|
||||
// << " first=" << firstStepInVolume << " last=" << lastStepInVolume
|
||||
<< G4endl;
|
||||
posfile1.close();
|
||||
}
|
||||
eventIDoldScint=eventID;
|
||||
runIDoldScint = runID;
|
||||
// ScintChamberNbold = IBchamberNb;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
382
geant4/LEMuSR/src/lem4ScintSD.cc
Normal file
382
geant4/LEMuSR/src/lem4ScintSD.cc
Normal file
@ -0,0 +1,382 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
//cksdel #include "lem4RunAction.hh"
|
||||
#include "lem4ScintSD.hh"
|
||||
#include "G4HCofThisEvent.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4SDManager.hh"
|
||||
#include "G4ios.hh"
|
||||
//#include "G4MagneticField.hh"
|
||||
//#include "G4FieldManager.hh"
|
||||
//#include "G4TransportationManager.hh"
|
||||
#include <algorithm> // needed for the sort() function
|
||||
#include "G4VProcess.hh" // needed for the degugging message of the process name
|
||||
#include "G4RunManager.hh"
|
||||
#include "G4Run.hh"
|
||||
#include "lem4Parameters.hh"
|
||||
#include "lem4ErrorMessage.hh"
|
||||
#include <vector>
|
||||
|
||||
//bool myREMOVEfunction (int i,int j) { return (i<j); }
|
||||
//bool timeOrdering (lem4ScintHit hit1, lem4ScintHit hit2) {
|
||||
// return (hit1.GetGlobalTime()<hit2.GetGlobalTime());
|
||||
//}
|
||||
//
|
||||
//bool timeOrdering2 (std::map<int,double>::iterator i1, std::map<int,double>::iterator m2) {
|
||||
// return ( (*i1).first()<(*i2).second() );
|
||||
//}
|
||||
//
|
||||
//bool timeOrdering2 (std::pair<int,double> p1, std::pair<int,double> p2) {
|
||||
// return ( p1.first()<p2.second() );
|
||||
//}
|
||||
//
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4ScintSD::lem4ScintSD(G4String name)
|
||||
:G4VSensitiveDetector(name)
|
||||
{
|
||||
G4String HCname;
|
||||
collectionName.insert(HCname="scintCollection");
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4ScintSD::~lem4ScintSD(){ }
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4ScintSD::Initialize(G4HCofThisEvent* HCE) {
|
||||
if (verboseLevel>1) G4cout<<"VERBOSE 2: lem4ScintSD::Initialize\n";
|
||||
// Positron_momentum_already_stored=0;
|
||||
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
myRootOutput->ClearAllRootVariables();
|
||||
|
||||
scintCollection = new lem4ScintHitsCollection
|
||||
(SensitiveDetectorName,collectionName[0]);
|
||||
static G4int HCID = -1;
|
||||
if(HCID<0) {
|
||||
HCID = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[0]);
|
||||
if (verboseLevel>1) G4cout<<"VERBOSE 2: lem4ScintSD::HCID was <0\n, now HCID="<<HCID<<"\n";
|
||||
}
|
||||
HCE->AddHitsCollection( HCID, scintCollection );
|
||||
myStoreOnlyEventsWithHits = lem4Parameters::storeOnlyEventsWithHits;
|
||||
mySignalSeparationTime = lem4Parameters::signalSeparationTime;
|
||||
myStoreOnlyTheFirstTimeHit= lem4Parameters::storeOnlyTheFirstTimeHit;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool lem4ScintSD::ProcessHits(G4Step* aStep,G4TouchableHistory*)
|
||||
{
|
||||
if (verboseLevel>1) G4cout<<"VERBOSE 2: lem4ScintSD::ProcessHits\n";
|
||||
G4double edep = aStep->GetTotalEnergyDeposit();
|
||||
if(edep==0.) {
|
||||
return false;
|
||||
}
|
||||
|
||||
G4Track* aTrack = aStep->GetTrack();
|
||||
G4String actualVolume=aTrack->GetVolume()->GetLogicalVolume()->GetName();
|
||||
// G4cout <<"actualVolume=="<<actualVolume<<G4endl;
|
||||
///if (actualVolume=="Target") { // Perhaps not necessary! TS.
|
||||
///return false;
|
||||
///}
|
||||
// else if ((strncmp(actualVolume.c_str(),"Shield",6)==0)||(strncmp(actualVolume.c_str(),"shield",6)==0)) {
|
||||
// delete track if the particle is far away from the detector (i.e. in the "shield" volume)
|
||||
// aTrack->SetTrackStatus(fSuspend);
|
||||
// }
|
||||
|
||||
// If requested, store only the hit that happened first (usefull for some special studies, not for a serious simulation)
|
||||
if (myStoreOnlyTheFirstTimeHit) {
|
||||
G4int NbHits = scintCollection->entries();
|
||||
if (NbHits>0) {
|
||||
aTrack->SetTrackStatus(fStopAndKill);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//cks Ignore hits from the particles that had been created at the time when the muon
|
||||
// was stopping in the target - not a correct thing to do, however no better way
|
||||
// to suppres wrong timing information of the hit found yet.
|
||||
// lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
// G4double muonArrivedInTarget = myRootOutput->GetTimeInTarget();
|
||||
// if (muonArrivedInTarget>0.) {
|
||||
// G4double timeOfThisTrack = aTrack->GetGlobalTime();
|
||||
// if (fabs(muonArrivedInTarget-timeOfThisTrack)<(2*ns)) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// // G4cout<<"Kamil: in the hit before muon has arrived into the target"<<G4endl;
|
||||
// }
|
||||
// if ( (aTrack->GetGlobalTime()) < (0.03*microsecond) ) return false;
|
||||
lem4ScintHit* newHit = new lem4ScintHit();
|
||||
// G4RunManager* fRunManager = G4RunManager::GetRunManager();
|
||||
// newHit->SetEventID(fRunManager->GetCurrentEvent()->GetEventID());
|
||||
// newHit->SetRunID(fRunManager->GetCurrentRun()->GetRunID());
|
||||
newHit->SetParticleName (aTrack->GetDefinition()->GetParticleName());
|
||||
newHit->SetParticleID (aTrack->GetDefinition()->GetPDGEncoding());
|
||||
// if (aTrack->GetDefinition()->GetPDGEncoding()==-13) {
|
||||
// if ((aTrack->GetGlobalTime())<(0.015*microsecond)) {
|
||||
// G4cout<<"PROCESS: detected particle="<<aTrack->GetDefinition()->GetParticleName()
|
||||
// <<" TIME="<<aTrack->GetGlobalTime()<<G4endl;
|
||||
// const G4VProcess* interestingProcess = aStep->GetPostStepPoint()->GetProcessDefinedStep();
|
||||
// // G4cout<<"GetProcessName()="<<interestingProcess->GetProcessName()<<G4endl;
|
||||
// const G4VProcess* creatorProcess =aTrack->GetCreatorProcess();
|
||||
// G4cout<<"Process that limitted this step: "; interestingProcess->DumpInfo();
|
||||
// if (creatorProcess!=NULL) {G4cout<<"Process that created this particle: "; creatorProcess->DumpInfo();}
|
||||
// }
|
||||
newHit->SetTrackID (aTrack->GetTrackID());
|
||||
newHit->SetEdep (edep);
|
||||
newHit->SetPrePos (aStep->GetPreStepPoint()->GetPosition());
|
||||
newHit->SetPostPos (aStep->GetPostStepPoint()->GetPosition());
|
||||
newHit->SetPol (aTrack->GetPolarization());
|
||||
newHit->SetLogVolName(aTrack->GetVolume()->GetLogicalVolume()->GetName());
|
||||
newHit->SetGlobTime (aTrack->GetGlobalTime());
|
||||
|
||||
/// Printout to check proper assignment of Global Time!
|
||||
//G4cout<<"StepTime="<<aStep->GetDeltaTime()<<"\t";
|
||||
//G4cout<<"GlobalTime="<<aTrack->GetGlobalTime()<<" LocalTime="<<aTrack->GetLocalTime()<<" ProperTime="<<aTrack->GetProperTime();
|
||||
//G4cout<<"\t trackID="<<aTrack->GetTrackID() <<"\t actualVolume="<<actualVolume<<G4endl;
|
||||
|
||||
// Warning - aStep->IsFirstStepInVolume() only available in Geant version >= 4.8.2 !
|
||||
// newHit->SetFirstStepInVolumeFlag(aStep->IsFirstStepInVolume());
|
||||
// newHit->SetLastStepInVolumeFlag(aStep->IsLastStepInVolume());
|
||||
newHit->SetKineticEnergy(aTrack->GetVertexKineticEnergy());
|
||||
// newHit->SetKineticEnergy(aTrack->GetKineticEnergy()+edep);
|
||||
newHit->SetStepLength (aStep->GetStepLength());
|
||||
// G4double BFieldAtOrigin[6] = {0.,0.,0.,0.,0.,0.};
|
||||
// G4double Origin[4] ={0.,0.,0.,0.};
|
||||
// G4FieldManager *fMgr=G4TransportationManager::GetTransportationManager()->GetFieldManager();
|
||||
// if (fMgr!=NULL) {
|
||||
// if(!fMgr->DoesFieldChangeEnergy()) { //then we have a magnetic field
|
||||
// fMgr->GetDetectorField()->GetFieldValue(Origin,BFieldAtOrigin);
|
||||
// }
|
||||
// else{
|
||||
// }
|
||||
// // G4cout<<"Kamil: pole="<<BFieldAtOrigin[0]/tesla<<" "<<BFieldAtOrigin[1]/tesla<<" "<<BFieldAtOrigin[2]/tesla
|
||||
// // <<" "<<BFieldAtOrigin[3]/tesla<<" "<<BFieldAtOrigin[4]/tesla<<" "<<BFieldAtOrigin[5]/tesla<<G4endl;
|
||||
// }
|
||||
// newHit->SetBField(BFieldAtOrigin);
|
||||
scintCollection->insert( newHit );
|
||||
// newHit->Print();
|
||||
newHit->Draw();
|
||||
return true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4ScintSD::EndOfEvent(G4HCofThisEvent*) {
|
||||
if (verboseLevel>1) {
|
||||
G4cout<<"VERBOSE 2: lem4ScintSD::EndOfEvent"<<G4endl;
|
||||
G4int NbHits = scintCollection->entries();
|
||||
G4cout << "\n-------->Hits Collection: in this event they are " << NbHits
|
||||
<< " hits in the scint chambers: " << G4endl;
|
||||
// for (G4int i=0;i<NbHits;i++) (*scintCollection)[i]->Print();
|
||||
}
|
||||
|
||||
// Positron_momentum_already_stored=0;
|
||||
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
|
||||
G4RunManager* fRunManager = G4RunManager::GetRunManager();
|
||||
myRootOutput->SetRunID(fRunManager->GetCurrentRun()->GetRunID());
|
||||
myRootOutput->SetEventID(fRunManager->GetCurrentEvent()->GetEventID());
|
||||
|
||||
G4int NbHits = scintCollection->entries();
|
||||
if ((NbHits<=0)&&(myStoreOnlyEventsWithHits)) {
|
||||
myRootOutput->ClearAllRootVariables();
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort out hits and fill them into root
|
||||
if (NbHits>0) {
|
||||
lem4ScintHit* firstHit = (*scintCollection)[0];
|
||||
myRootOutput->SetGlobTime(firstHit->GetGlobalTime());
|
||||
|
||||
const G4int det_IDmax = lem4RootOutput::det_nMax;
|
||||
G4double det_edep[det_IDmax];
|
||||
G4int det_nsteps[det_IDmax];
|
||||
G4double det_length[det_IDmax];
|
||||
G4int det_ID[det_IDmax];
|
||||
G4double det_edep_el[det_IDmax];
|
||||
G4double det_edep_pos[det_IDmax];
|
||||
G4double det_edep_gam[det_IDmax];
|
||||
G4double det_edep_mup[det_IDmax];
|
||||
G4double det_time_start[det_IDmax];
|
||||
G4double det_time_end[det_IDmax];
|
||||
G4double det_x[det_IDmax];
|
||||
G4double det_y[det_IDmax];
|
||||
G4double det_z[det_IDmax];
|
||||
// for (G4int ii=0; ii<det_IDmax; ii++) {
|
||||
// det_edep[ii]=0.;
|
||||
// det_nsteps[ii]=0;
|
||||
// det_length[ii]=0.;
|
||||
// det_ID[ii]=-1000;
|
||||
// det_edep_el[ii]=0.;
|
||||
// det_edep_pos[ii]=0.;
|
||||
// det_edep_gam[ii]=0.;
|
||||
// det_edep_mup[ii]=0.;
|
||||
// }
|
||||
|
||||
// const G4int subtrack_max=lem4RootOutput::maxNSubTracks;
|
||||
// G4int particleID[subtrack_max];
|
||||
// G4int trackID[subtrack_max];
|
||||
// G4int logicalVolumeID[subtrack_max];
|
||||
// G4double edep[subtrack_max];
|
||||
// G4double x[subtrack_max];
|
||||
// G4double y[subtrack_max];
|
||||
// G4double z[subtrack_max];
|
||||
// G4double post_x[subtrack_max];
|
||||
// G4double post_y[subtrack_max];
|
||||
// G4double post_z[subtrack_max];
|
||||
// G4double kineticEnergy[subtrack_max];
|
||||
// G4double stepLength[subtrack_max];
|
||||
// G4int nrOfSubsteps[subtrack_max];
|
||||
// for (G4int ii=0; ii<subtrack_max; ii++) {
|
||||
// particleID[ii]=-1000;
|
||||
// trackID[ii]=-1000;
|
||||
// logicalVolumeID[ii]=-1000;
|
||||
// edep[ii]=-1000;
|
||||
// x[ii]=-1000;
|
||||
// y[ii]=-1000;
|
||||
// z[ii]=-1000;
|
||||
// post_x[ii]=-1000;
|
||||
// post_y[ii]=-1000;
|
||||
// post_z[ii]=-1000;
|
||||
// kineticEnergy[ii]=-1000;
|
||||
// stepLength[ii]=-1000;
|
||||
// nrOfSubsteps[ii]=-1000;
|
||||
// }
|
||||
|
||||
// G4String aLogicalVolume_old="Unset";
|
||||
// G4String aParticleName_old="Unset";
|
||||
// G4int det_index=-1;
|
||||
// G4int subtrack_index=-1;
|
||||
// G4cout<<G4endl;
|
||||
|
||||
// int myints[] = {32,71,12,45,26,80,53,33};
|
||||
// std::vector<int> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33
|
||||
// std::vector<int>::iterator it;
|
||||
// sort (myvector.begin(), myvector.end(), myREMOVEfunction);
|
||||
// // print out content:
|
||||
// G4cout << "myvector contains:";
|
||||
// for (it=myvector.begin(); it!=myvector.end(); ++it)
|
||||
// G4cout << " " << *it;
|
||||
// G4cout << G4endl;
|
||||
|
||||
|
||||
// Sort hits according to the time. Using std::map is convenient, because it sorts
|
||||
// its entries according to the key (the first variable of the pair).
|
||||
std::map<G4double,G4int> myHitTimeMapping;
|
||||
std::map<G4double,G4int>::iterator it;
|
||||
for (G4int i=0; i<NbHits; i++) {
|
||||
lem4ScintHit* aHit = (*scintCollection)[i];
|
||||
G4double tmptime=aHit->GetGlobalTime();
|
||||
// G4cout<<"Hit nr "<<i<<" at time="<<tmptime<<" with edep="<<aHit->GetEdep()/MeV
|
||||
// <<" detID="<<myRootOutput->ConvertVolumeToID(aHit->GetLogVolName())<< G4endl;
|
||||
myHitTimeMapping.insert ( std::pair<G4double,G4int>(tmptime,i) );
|
||||
}
|
||||
|
||||
// Loop over all hits (which are sorted according to their time):
|
||||
G4int nSignals=0;
|
||||
for (it=myHitTimeMapping.begin(); it!=myHitTimeMapping.end(); it++) {
|
||||
// G4cout << "Key:" << it->first;
|
||||
// G4cout << " Value:" << it->second << "\n";
|
||||
G4int ii = it->second; // ii is the index of the hits, which is sorted according to time
|
||||
lem4ScintHit* aHit = (*scintCollection)[ii];
|
||||
G4String aHitVolumeName = aHit->GetLogVolName();
|
||||
G4int aHitVolumeID = myRootOutput->ConvertVolumeToID(aHitVolumeName);
|
||||
G4double aHitTime = aHit->GetGlobalTime();
|
||||
|
||||
// Loop over all already defined signals and check whether the hit falls into any of them
|
||||
G4bool signalAssigned=false;
|
||||
for (G4int j=0; j<nSignals; j++) {
|
||||
if ( (aHitVolumeID==det_ID[j]) && ((aHitTime-det_time_end[j])<mySignalSeparationTime) ) {
|
||||
signalAssigned=true;
|
||||
det_edep[j] += aHit->GetEdep();
|
||||
det_nsteps[j]++;
|
||||
det_length[j] += aHit->GetStepLength();
|
||||
det_time_end[j] = aHitTime;
|
||||
G4String aParticleName = aHit->GetParticleName();
|
||||
if (aParticleName=="e-") {
|
||||
det_edep_el[j] += aHit->GetEdep();
|
||||
} else if (aParticleName=="e+") {
|
||||
det_edep_pos[j] += aHit->GetEdep();
|
||||
} else if (aParticleName=="gamma") {
|
||||
det_edep_gam[j] += aHit->GetEdep();
|
||||
} else if (aParticleName=="mu+") {
|
||||
det_edep_mup[j] += aHit->GetEdep();
|
||||
} else {
|
||||
char message[200];
|
||||
sprintf(message,"lem4ScintSD.cc::EndOfEvent(): untreated particle \"%s\" deposited energy.",aParticleName.c_str());
|
||||
lem4ErrorMessage::GetInstance()->lem4Error(WARNING,message,true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!signalAssigned) { // The hit does not belong to any existing signal --> create a new signal.
|
||||
// Check, whether the maximum number of signals was not exceeded:
|
||||
if ( nSignals >= (det_IDmax-1) ) {
|
||||
char message[200];
|
||||
sprintf(message,"lem4ScintSD.cc::EndOfEvent(): number of signals exceeds maximal allowed value.");
|
||||
lem4ErrorMessage::GetInstance()->lem4Error(WARNING,message,true);
|
||||
}
|
||||
else {
|
||||
det_edep[nSignals] = aHit->GetEdep();
|
||||
det_nsteps[nSignals] = 1;
|
||||
det_length[nSignals] = aHit->GetStepLength();
|
||||
det_ID[nSignals] = aHitVolumeID;
|
||||
det_time_start[nSignals] = aHitTime;
|
||||
det_time_end[nSignals] = aHitTime;
|
||||
det_edep_el[nSignals] = 0;
|
||||
det_edep_pos[nSignals] = 0;
|
||||
det_edep_gam[nSignals] = 0;
|
||||
det_edep_mup[nSignals] = 0;
|
||||
G4String aParticleName = aHit->GetParticleName();
|
||||
if (aParticleName=="e-") {
|
||||
det_edep_el[nSignals] += aHit->GetEdep();
|
||||
} else if (aParticleName=="e+") {
|
||||
det_edep_pos[nSignals] += aHit->GetEdep();
|
||||
} else if (aParticleName=="gamma") {
|
||||
det_edep_gam[nSignals] += aHit->GetEdep();
|
||||
} else if (aParticleName=="mu+") {
|
||||
det_edep_mup[nSignals] += aHit->GetEdep();
|
||||
} else {
|
||||
char message[200];
|
||||
sprintf(message,"lem4ScintSD.cc::EndOfEvent(): UNTREATED PARTICLE \"%s\" deposited energy.",aParticleName.c_str());
|
||||
lem4ErrorMessage::GetInstance()->lem4Error(WARNING,message,true);
|
||||
}
|
||||
G4ThreeVector prePos = aHit->GetPrePos();
|
||||
det_x[nSignals]=prePos.x();
|
||||
det_y[nSignals]=prePos.y();
|
||||
det_z[nSignals]=prePos.z();
|
||||
nSignals++;
|
||||
}
|
||||
} // end of "if (!signalAssigned)"
|
||||
} // end of the for loop over the hits
|
||||
|
||||
// Sort the signals according to the energy (in decreasing order)
|
||||
std::map<G4double,G4int> mySignalMapping;
|
||||
std::map<G4double,G4int>::iterator itt;
|
||||
for (G4int i=0; i<nSignals; i++) {
|
||||
mySignalMapping.insert ( std::pair<G4double,G4int>(-det_edep[i],i) );
|
||||
}
|
||||
|
||||
// Write out the signals (sorted according to energy) to the lem4RootOutput class:
|
||||
G4int jj=-1;
|
||||
for (itt=mySignalMapping.begin(); itt!=mySignalMapping.end(); itt++) {
|
||||
jj++;
|
||||
G4int ii = itt->second;
|
||||
myRootOutput->SetDetectorInfo(jj,det_ID[ii],det_edep[ii],det_edep_el[ii],det_edep_pos[ii],
|
||||
det_edep_gam[ii],det_edep_mup[ii],det_nsteps[ii],det_length[ii],
|
||||
det_time_start[ii],det_time_end[ii],det_x[ii],det_y[ii],det_z[ii]);
|
||||
}
|
||||
|
||||
} //end "if (NbHits>0)"
|
||||
|
||||
myRootOutput->FillEvent();
|
||||
myRootOutput->ClearAllRootVariables();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
99
geant4/LEMuSR/src/lem4ShieldHit.cc
Normal file
99
geant4/LEMuSR/src/lem4ShieldHit.cc
Normal file
@ -0,0 +1,99 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "lem4ShieldHit.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4VVisManager.hh"
|
||||
#include "G4Circle.hh"
|
||||
#include "G4Colour.hh"
|
||||
#include "G4VisAttributes.hh"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include "G4ios.hh"
|
||||
#include "G4MagneticField.hh"
|
||||
#include "G4FieldManager.hh"
|
||||
#include "G4TransportationManager.hh"
|
||||
#include <iomanip>
|
||||
#include "globals.hh"
|
||||
#include "G4Transform3D.hh"
|
||||
#include "G4ProcessManager.hh"
|
||||
#include "G4Track.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4Event.hh"
|
||||
#include "G4EventManager.hh"
|
||||
#include "G4RunManager.hh"
|
||||
#include "G4Run.hh"
|
||||
|
||||
G4Allocator<lem4ShieldHit> lem4ShieldHitAllocator;
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4ShieldHit::lem4ShieldHit() {}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4ShieldHit::~lem4ShieldHit() {}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4ShieldHit::lem4ShieldHit(const lem4ShieldHit& right)
|
||||
: G4VHit()
|
||||
{
|
||||
|
||||
trackID = right.trackID;
|
||||
particle_name = right.particle_name;
|
||||
edep = right.edep;
|
||||
pos = right.pos;
|
||||
pol = right.pol;
|
||||
logicalvolume = right.logicalvolume;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
const lem4ShieldHit& lem4ShieldHit::operator=(const lem4ShieldHit& right)
|
||||
{
|
||||
|
||||
trackID = right.trackID;
|
||||
particle_name = right.particle_name;
|
||||
edep = right.edep;
|
||||
pos = right.pos;
|
||||
pol = right.pol;
|
||||
logicalvolume=right.logicalvolume;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4int lem4ShieldHit::operator==(const lem4ShieldHit& right) const
|
||||
{
|
||||
return (this==&right) ? 1 : 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4ShieldHit::Draw()
|
||||
{
|
||||
G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
|
||||
if(pVVisManager)
|
||||
{
|
||||
G4Circle circle(pos);
|
||||
circle.SetScreenSize(0.04);
|
||||
circle.SetFillStyle(G4Circle::filled);
|
||||
G4Colour colour(1.,0.,0.);
|
||||
G4VisAttributes attribs(colour);
|
||||
circle.SetVisAttributes(attribs);
|
||||
pVVisManager->Draw(circle);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4ShieldHit::Print()
|
||||
{
|
||||
|
||||
G4EventManager* fEventManager = G4EventManager::GetEventManager();
|
||||
fEventManager->AbortCurrentEvent();
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
82
geant4/LEMuSR/src/lem4ShieldSD.cc
Normal file
82
geant4/LEMuSR/src/lem4ShieldSD.cc
Normal file
@ -0,0 +1,82 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "lem4ShieldSD.hh"
|
||||
#include "G4HCofThisEvent.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4SDManager.hh"
|
||||
#include "G4ios.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
///
|
||||
/// The Shield sensitive detector. This object collects the
|
||||
/// information of a particle's interaction with this part
|
||||
/// of the geometry
|
||||
///
|
||||
|
||||
lem4ShieldSD::lem4ShieldSD(G4String name)
|
||||
:G4VSensitiveDetector(name)
|
||||
{
|
||||
G4String HCname;
|
||||
collectionName.insert(HCname="shieldCollection");
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4ShieldSD::~lem4ShieldSD(){ }
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4ShieldSD::Initialize(G4HCofThisEvent* HCE)
|
||||
{
|
||||
shieldCollection = new lem4ShieldHitsCollection
|
||||
(SensitiveDetectorName,collectionName[0]);
|
||||
static G4int HCID = -1;
|
||||
if(HCID<0)
|
||||
{ HCID = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[0]); }
|
||||
HCE->AddHitsCollection( HCID, shieldCollection );
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool lem4ShieldSD::ProcessHits(G4Step* aStep,G4TouchableHistory*)
|
||||
{
|
||||
///
|
||||
/// Collect the information regarding the interaction of a particle
|
||||
/// and the sensitive detector.
|
||||
///
|
||||
G4double edep = aStep->GetTotalEnergyDeposit();
|
||||
|
||||
if(edep==0.) return false;
|
||||
|
||||
lem4ShieldHit* newHit = new lem4ShieldHit();
|
||||
newHit->SetParticleName (aStep->GetTrack()->GetDefinition()->GetParticleName());
|
||||
newHit->SetTrackID (aStep->GetTrack()->GetTrackID());
|
||||
newHit->SetEdep (edep);
|
||||
newHit->SetPos (aStep->GetPostStepPoint()->GetPosition());
|
||||
newHit->SetPol (aStep->GetTrack()->GetPolarization());
|
||||
newHit->SetLogVolName (aStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetName());
|
||||
shieldCollection->insert( newHit );
|
||||
|
||||
newHit->Print();
|
||||
newHit->Draw();
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4ShieldSD::EndOfEvent(G4HCofThisEvent*)
|
||||
{
|
||||
if (verboseLevel>0) {
|
||||
G4int NbHits = shieldCollection->entries();
|
||||
G4cout << "\n-------->Hits Collection: in this event they are " << NbHits
|
||||
<< " hits: " << G4endl;
|
||||
for (G4int i=0;i<NbHits;i++) (*shieldCollection)[i]->Print();
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
337
geant4/LEMuSR/src/lem4SteppingAction.cc
Normal file
337
geant4/LEMuSR/src/lem4SteppingAction.cc
Normal file
@ -0,0 +1,337 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
#include "lem4SteppingAction.hh"
|
||||
//cksdel#include "lem4RunAction.hh"
|
||||
#include "G4SteppingManager.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "lem4RootOutput.hh"
|
||||
#include "G4RunManager.hh" // needed for the event nr. comparison
|
||||
#include "G4Run.hh" // ---------------||------------------
|
||||
#include "G4MagneticField.hh" // needed for storing the magnetic field to the Root class
|
||||
#include "G4FieldManager.hh" // ---------------||------------------
|
||||
#include "G4TransportationManager.hh" // ---------------||------------------
|
||||
#include "lem4ErrorMessage.hh"
|
||||
#include "lem4Parameters.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4SteppingAction::lem4SteppingAction() {
|
||||
pointer=this;
|
||||
// oldEventID=-1000;
|
||||
muPlusProcessManager=NULL;
|
||||
multipleToCoulombScatteringIsPossible=false;
|
||||
coulombScatteringIsActive=false;
|
||||
multipleScatteringIndex=1000;
|
||||
coulombScatteringIndex=1000;
|
||||
boolIsAnySpecialSaveVolumeDefined = false;
|
||||
lastActualVolume="Unset";
|
||||
}
|
||||
|
||||
lem4SteppingAction::~lem4SteppingAction() {
|
||||
}
|
||||
|
||||
|
||||
lem4SteppingAction* lem4SteppingAction::pointer=0;
|
||||
lem4SteppingAction* lem4SteppingAction::GetInstance()
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4SteppingAction::DoAtTheBeginningOfEvent() {
|
||||
// G4cout<<"lem4SteppingAction::DoAtTheBeginningOfEvent: KAMIL"<<G4endl;
|
||||
radioactiveElectronAlreadySavedInThisEvent=false;
|
||||
muAlreadyWasInTargetInThisEvent=false;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4SteppingAction::UserSteppingAction(const G4Step* aStep) {
|
||||
// sleep(1);
|
||||
// For debugging purposes: To find out the number of steps during one event:
|
||||
// G4RunManager* fRunManager = G4RunManager::GetRunManager();
|
||||
// G4int debugEventID = fRunManager->GetCurrentEvent()->GetEventID();
|
||||
// nrOfSteps++;
|
||||
// if (debugOldEventID != debugEventID) {
|
||||
// G4cout<<"lem4SteppingAction: Event nr. "<<debugOldEventID<<" has"<<nrOfSteps<<" steps."<<G4endl;
|
||||
// nrOfSteps=0;
|
||||
// debugOldEventID=debugEventID;
|
||||
// }
|
||||
|
||||
G4Track* aTrack = aStep->GetTrack();
|
||||
// if (nrOfSteps > 100000) {
|
||||
// G4cout<<"lem4SteppingAction.cc : event nr. "<<debugEventID
|
||||
// <<": nrOfSteps>100000 ==> KILL THE CURRENT TRACK with"
|
||||
// <<aTrack->GetDynamicParticle()->GetDefinition()->GetParticleName() <<" at"
|
||||
// <<aStep->GetPostStepPoint()->GetPosition() <<G4endl;
|
||||
// G4cout<<"GetCurrentStepNumber()="<<aTrack->GetCurrentStepNumber() <<G4endl;
|
||||
// aTrack->SetTrackStatus(fStopAndKill); // suspend the track if too many steps have already happened
|
||||
// // (should be done in a more clever way, but I do not know how yet).
|
||||
// nrOfSteps=0;
|
||||
// }
|
||||
|
||||
// suspend the track if too many steps have already happened (relevant at high fields)
|
||||
if (aTrack->GetCurrentStepNumber()>100000) {
|
||||
lem4ErrorMessage::GetInstance()->lem4Error(WARNING,
|
||||
"lem4SteppingAction: Current number of steps for the track > 100000 ==> TRACK KILLED",true);
|
||||
//
|
||||
// G4cout<<"lem4SteppingAction.cc : event nr. "<<oldEventID
|
||||
// <<" Current number of steps for the track > 100000 ==> KILL THIS TRACK: " <<G4endl;
|
||||
// <<aTrack->GetDynamicParticle()->GetDefinition()->GetParticleName() <<" at"
|
||||
// <<aStep->GetPostStepPoint()->GetPosition()
|
||||
// <<" E_kin_vertex="<<aTrack->GetVertexKineticEnergy()/MeV<<" MeV."<<G4endl;
|
||||
//
|
||||
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
G4double x=aStep->GetPostStepPoint()->GetPosition().x()/mm;
|
||||
G4double y=aStep->GetPostStepPoint()->GetPosition().y()/mm;
|
||||
G4double z=aStep->GetPostStepPoint()->GetPosition().z()/mm;
|
||||
G4double E=aTrack->GetVertexKineticEnergy()/MeV;
|
||||
myRootOutput->htest1->Fill(x,y);
|
||||
myRootOutput->htest2->Fill(sqrt(x*x+y*y),z);
|
||||
myRootOutput->htest3->Fill(E);
|
||||
|
||||
aTrack->SetTrackStatus(fStopAndKill);
|
||||
}
|
||||
|
||||
|
||||
if (aTrack->GetDefinition()) {
|
||||
G4ParticleDefinition* p_definition = aTrack->GetDynamicParticle()->GetDefinition();
|
||||
G4String p_name = p_definition->GetParticleName();
|
||||
// G4ProcessManager* p_manager = p_definition->GetProcessManager();
|
||||
// G4String p_name=aTrack->GetDynamicParticle()->GetDefinition()->GetParticleName();
|
||||
G4String actualVolume=aTrack->GetVolume()->GetLogicalVolume()->GetName();
|
||||
|
||||
|
||||
|
||||
//! First Commented by TS. Currently not in use! or not strictly necessary
|
||||
|
||||
|
||||
// This are the data just for the radioactive decay (when using the radioactive source):
|
||||
if ((lem4Parameters::boolG4GeneralParticleSource)) {
|
||||
// &&(!radioactiveElectronAlreadySavedInThisEvent)) {
|
||||
if (aTrack->GetTrackID() != 1 ){
|
||||
if (aTrack->GetCreatorProcess()->GetProcessName() == "RadioactiveDecay") {
|
||||
// if (aStep->GetPostStepPoint()->GetProcessDefinedStep()->GetProcessName() == "RadioactiveDecay") { did not work out
|
||||
// emitted particles
|
||||
// if (fTrack->GetDefinition()->GetParticleType() != "nucleus") {
|
||||
// G4String particleName = fTrack->GetDefinition()->GetParticleName();
|
||||
if (aTrack->GetDefinition()->GetParticleName()=="e-") {
|
||||
// G4double particleName = G4double (fTrack->GetDefinition()->GetPDGEncoding());
|
||||
// G4double time = fStep->GetPreStepPoint()->GetGlobalTime() ;
|
||||
// //- fStep->GetPreStepPoint()->GetLocalTime();
|
||||
// G4double weight = fStep->GetPreStepPoint()->GetWeight() ;
|
||||
// G4double energy = fStep->GetPreStepPoint()->GetKineticEnergy();
|
||||
//
|
||||
// exrdmAnalysisManager::getInstance()->AddParticle(particleName, energy, weight, time);
|
||||
//hovno
|
||||
// G4cout<<"aTrack->GetCurrentStepNumber()="<<aTrack->GetCurrentStepNumber()<<" ";
|
||||
if (aTrack->GetCurrentStepNumber()==1) {
|
||||
G4double electron_kinetic_energy=aStep->GetPreStepPoint()->GetKineticEnergy();
|
||||
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
myRootOutput->htest4->Fill(electron_kinetic_energy);
|
||||
// G4cout<<"First kinetic energy="<<aStep->GetPreStepPoint()->GetKineticEnergy()<<" ";
|
||||
// G4cout<<"GetKineticEnergy()="<<aTrack->GetKineticEnergy()<<G4endl;
|
||||
}
|
||||
// // G4ThreeVector radioactivePositronMomentum = aStep->GetPreStepPoint()->GetMomentum();
|
||||
// G4ThreeVector radioactivePositronMomentum = aTrack->GetMomentum();
|
||||
// G4double Apx=radioactivePositronMomentum.x();
|
||||
// G4double Apy=radioactivePositronMomentum.y();
|
||||
// G4double Apz=radioactivePositronMomentum.z();
|
||||
// lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
// myRootOutput->SetInitialMuonParameters(0,0,0,Apx,Apy,Apz,0,0,0);
|
||||
// radioactiveElectronAlreadySavedInThisEvent=true;
|
||||
// // G4cout<<"Apx,Apy,Apz="<<Apx<<" "<<Apy<<" "<<Apz<<G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//hovno
|
||||
// Check if in the special
|
||||
if (boolIsAnySpecialSaveVolumeDefined) {
|
||||
// G4bool isFirstStepInVolume=aStep->IsFirstStepInVolume();
|
||||
// This does not work!!! (aStep->IsFirstStepInVolume() is always zero.) I do not understand why!
|
||||
G4bool isFirstStepInVolume=false;
|
||||
if (actualVolume!=lastActualVolume) {
|
||||
lastActualVolume=actualVolume;
|
||||
isFirstStepInVolume=true;
|
||||
}
|
||||
|
||||
if (isFirstStepInVolume) {
|
||||
G4int tmpVolumeID=saveVolumeMapping[actualVolume];
|
||||
if (tmpVolumeID!=0) {
|
||||
G4int particle_id_save=p_definition->GetPDGEncoding();
|
||||
G4double ke_save=aStep->GetPreStepPoint()->GetKineticEnergy()/keV;
|
||||
G4double x_save=aStep->GetPreStepPoint()->GetPosition().x()/mm;
|
||||
G4double y_save=aStep->GetPreStepPoint()->GetPosition().y()/mm;
|
||||
G4double z_save=aStep->GetPreStepPoint()->GetPosition().z()/mm;
|
||||
G4double px_save=aStep->GetPreStepPoint()->GetMomentum().x()/MeV;
|
||||
G4double py_save=aStep->GetPreStepPoint()->GetMomentum().y()/MeV;
|
||||
G4double pz_save=aStep->GetPreStepPoint()->GetMomentum().z()/MeV;
|
||||
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
myRootOutput->SetSaveDetectorInfo(tmpVolumeID,particle_id_save,ke_save,x_save,y_save,z_save,px_save,py_save,pz_save);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Store information about when mu+ or Mu enter the target for the fist time
|
||||
// in a given event (i.e. the code has to be called just once during the event).
|
||||
if ((p_name == "mu+") || (p_name == "Mu")) {
|
||||
if (actualVolume=="log_target") {
|
||||
// G4RunManager* fRunManager = G4RunManager::GetRunManager();
|
||||
// G4int eventID = fRunManager->GetCurrentEvent()->GetEventID();
|
||||
// if (oldEventID != eventID) {
|
||||
// oldEventID=eventID;
|
||||
if (!muAlreadyWasInTargetInThisEvent) {
|
||||
muAlreadyWasInTargetInThisEvent=true;
|
||||
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
myRootOutput->SetPolInTarget(aTrack->GetPolarization());
|
||||
myRootOutput->SetTimeInTarget(aTrack->GetGlobalTime());
|
||||
//G4cout<<"particle = "<<p_name<<" TOF = "<<(aTrack->GetGlobalTime())/ns<<G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the pointer to the mu+ process manager, and the indexes of the "msc" and "eCoulombScat" processes.
|
||||
// This is needed for switching beween the multiple scattering and coulomb scattering in some volumes.
|
||||
if (p_name == "mu+") {
|
||||
if (muPlusProcessManager==NULL) { // The muPlusProcessManager should be NULL only once, at the beginning of the run.
|
||||
muPlusProcessManager = p_definition->GetProcessManager();
|
||||
G4ProcessVector* v = muPlusProcessManager->GetProcessList();
|
||||
size_t np = v->size();
|
||||
for(size_t i=0; i<np; i++) {
|
||||
// std::cout<<" "<<(*v)[i]->GetProcessName();
|
||||
if( (*v)[i]->GetProcessName() == "msc" ) {
|
||||
multipleScatteringIndex = i;
|
||||
}
|
||||
if( (*v)[i]->GetProcessName() == "eCoulombScat" ) {
|
||||
coulombScatteringIndex = i;
|
||||
}
|
||||
}
|
||||
// std::cout<<std::endl;
|
||||
// std::cout<<"multipleScatteringIndex,coulombScatteringIndex ="<<multipleScatteringIndex<<","<<coulombScatteringIndex<<std::endl;
|
||||
if ((multipleScatteringIndex<1000)&&(coulombScatteringIndex<1000)) { // Both multiple and Coulomb scattering processes for muon found
|
||||
multipleToCoulombScatteringIsPossible=true;
|
||||
std::cout<<"lem4SteppingAction: Switching between Coulomb and multiple scattering processes possible"<<std::endl;
|
||||
// Ensure that just one of them is active. Let the active one be the multiple scattering at the beginning.
|
||||
muPlusProcessManager->SetProcessActivation(multipleScatteringIndex, true);
|
||||
muPlusProcessManager->SetProcessActivation(coulombScatteringIndex, false);
|
||||
}
|
||||
else { // At least one of the "multiple scattering" and "coulomb scattering" was not found.
|
||||
// Perhaps they were not defined in the physics list ?
|
||||
if (lem4Parameters::GetInstance()->GetMyTypeOfProcesses()=="coulombAndMultiple") {
|
||||
if (coulombScatteringIndex==1000) {std::cout<<"lem4SteppingAction: Coulomb scattering process for mu+ not found!"<<std::endl;}
|
||||
if (multipleScatteringIndex==1000) {std::cout<<"lem4SteppingAction: Multiple scattering process for mu+ not found!"<<std::endl;}
|
||||
lem4ErrorMessage::GetInstance()->lem4Error(SERIOUS,
|
||||
"lem4SteppingAction: It is not possible to switch between Coulomb and multiple scattering.",true);
|
||||
|
||||
muPlusProcessManager->DumpInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// switch between G4MultipleScattering and G4CoulombScattering
|
||||
if (multipleToCoulombScatteringIsPossible) {
|
||||
if (strncmp(actualVolume.c_str(),"log_coulomb",11)==0) {
|
||||
if (!coulombScatteringIsActive) {
|
||||
// std::cout<<"Activating coulomb; volume= "<<actualVolume<<std::endl;
|
||||
muPlusProcessManager->SetProcessActivation(multipleScatteringIndex, false);
|
||||
muPlusProcessManager->SetProcessActivation(coulombScatteringIndex, true);
|
||||
coulombScatteringIsActive=true;
|
||||
}
|
||||
}
|
||||
else if (coulombScatteringIsActive) {
|
||||
// std::cout<<"Deactivating coulomb; volume= "<<actualVolume<<std::endl;
|
||||
muPlusProcessManager->SetProcessActivation(multipleScatteringIndex, true);
|
||||
muPlusProcessManager->SetProcessActivation(coulombScatteringIndex, false);
|
||||
coulombScatteringIsActive=false;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the information about the muon decay into the Root Class.
|
||||
// Pick up process "DecayWithSpin":
|
||||
const G4VProcess* process = aStep->GetPostStepPoint()->GetProcessDefinedStep();
|
||||
if (process!=NULL) {
|
||||
G4String processName = process->GetProcessName();
|
||||
if (processName=="DecayWithSpin") {
|
||||
lem4Parameters::field_DecayWithSpin=true;
|
||||
// std::cout<<"lem4SteppingAction: DecayWithSpin"<<std::endl;
|
||||
// store the information about the decaying muon
|
||||
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
G4double timeOfDecay_tmp=aTrack->GetGlobalTime();
|
||||
myRootOutput->SetDecayTime(timeOfDecay_tmp);
|
||||
myRootOutput->SetDecayPolarisation(aTrack->GetPolarization());
|
||||
G4ThreeVector positionOfDecay_tmp = aStep->GetPostStepPoint()->GetPosition();
|
||||
myRootOutput->SetDecayPosition(positionOfDecay_tmp);
|
||||
// store the detector ID in which the muon decayed
|
||||
myRootOutput->SetDecayDetectorID(actualVolume);
|
||||
// store the information about the magnetic field at the place where the muon decays
|
||||
G4double BFieldAtOrigin[6] = {0.,0.,0.,0.,0.,0.};
|
||||
G4double PointOfDecay[4] ={positionOfDecay_tmp.x(),positionOfDecay_tmp.y(),positionOfDecay_tmp.z(),timeOfDecay_tmp};
|
||||
G4FieldManager *fMgr=G4TransportationManager::GetTransportationManager()->GetFieldManager();
|
||||
if (fMgr!=NULL) {
|
||||
if(!fMgr->DoesFieldChangeEnergy()) { //then we have a magnetic field
|
||||
fMgr->GetDetectorField()->GetFieldValue(PointOfDecay,BFieldAtOrigin);
|
||||
myRootOutput->SetBField(BFieldAtOrigin);
|
||||
}
|
||||
else{
|
||||
}
|
||||
}
|
||||
|
||||
// store the information about the emerging positron
|
||||
G4TrackVector* secondary = fpSteppingManager->GetSecondary();
|
||||
G4int n_secondaries= (*secondary).size();
|
||||
for (G4int i=0; i<n_secondaries; i++) {
|
||||
// G4cout <<"Secondary ["<<i<<"]="<<(*secondary)[i]->GetDefinition()->GetParticleName()<<", ";
|
||||
if ( ((*secondary)[i]->GetDefinition()->GetParticleName()) == "e+" ) {
|
||||
myRootOutput->SetInitialPositronMomentum((*secondary)[i]->GetMomentum());
|
||||
|
||||
// These two times seem to be equivalent: (*secondary)[i]->GetGlobalTime()
|
||||
// aTrack->GetGlobalTime()
|
||||
// G4cout <<"Positron initial momentum="<<(*secondary)[i]->GetMomentum()<<G4endl;
|
||||
// G4cout <<"Positron time="<<(*secondary)[i]->GetGlobalTime()<<G4endl;
|
||||
// G4cout <<"astep time="<<aTrack->GetGlobalTime()<<G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//csk
|
||||
|
||||
G4ThreeVector position = aStep->GetPostStepPoint()->GetPosition();
|
||||
// G4double tof=aTrack->GetLocalTime();
|
||||
// G4double energy=aTrack->GetDynamicParticle()->GetKineticEnergy();
|
||||
G4ThreeVector polarization=aTrack->GetDynamicParticle()->GetPolarization();
|
||||
|
||||
// G4cout << "Stepping action: mu+ properties \n"
|
||||
// << "position " << G4BestUnit(position,"Length") <<"; \n"
|
||||
// << "time of flight " << G4BestUnit(tof,"Time") <<"; \n"
|
||||
// << "kinetic energy "<< G4BestUnit(energy,"Energy") <<"; \n"
|
||||
// << "polarization "<< polarization <<";\n"
|
||||
// <<G4endl;
|
||||
}
|
||||
|
||||
else { // particle is not muon
|
||||
// Delete track if the particle is far away from the detector (i.e. in the "shield" volume).
|
||||
// There is an example how to delete the track in example/novice/N04.
|
||||
// It is done in a different way here, because the example/novice/N04 was not doing
|
||||
// exactly what I wanted.
|
||||
/* if ((lem4Parameters::killAllPositrons)&&(p_name == "e+")){
|
||||
aTrack->SetTrackStatus(fStopAndKill); // suspend the track
|
||||
}
|
||||
*/
|
||||
if((actualVolume(0,10)=="log_shield")||(actualVolume(0,10)=="log_Shield")) {
|
||||
aTrack->SetTrackStatus(fStopAndKill); // suspend the track
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
|
||||
void lem4SteppingAction::SetLogicalVolumeAsSpecialSaveVolume(G4String logicName, G4int volumeID) {
|
||||
boolIsAnySpecialSaveVolumeDefined = true;
|
||||
saveVolumeMapping[logicName]=volumeID;
|
||||
}
|
151
geant4/LEMuSR/src/lem4SteppingVerbose.cc
Normal file
151
geant4/LEMuSR/src/lem4SteppingVerbose.cc
Normal file
@ -0,0 +1,151 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "lem4SteppingVerbose.hh"
|
||||
|
||||
#include "G4SteppingManager.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4SteppingVerbose::lem4SteppingVerbose()
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4SteppingVerbose::~lem4SteppingVerbose()
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4SteppingVerbose::StepInfo()
|
||||
{
|
||||
CopyState();
|
||||
|
||||
G4int prec = G4cout.precision(3);
|
||||
|
||||
if( verboseLevel >= 1 ){
|
||||
if( verboseLevel >= 4 ) VerboseTrack();
|
||||
if( verboseLevel >= 3 ){
|
||||
G4cout << G4endl;
|
||||
G4cout << std::setw( 5) << "#Step#" << " "
|
||||
<< std::setw( 6) << "X" << " "
|
||||
<< std::setw( 6) << "Y" << " "
|
||||
<< std::setw( 6) << "Z" << " "
|
||||
<< std::setw( 9) << "KineE" << " "
|
||||
<< std::setw( 9) << "dEStep" << " "
|
||||
<< std::setw(10) << "StepLeng"
|
||||
<< std::setw(10) << "TrakLeng"
|
||||
<< std::setw(10) << "Volume" << " "
|
||||
<< std::setw(10) << "Process" << G4endl;
|
||||
}
|
||||
|
||||
G4cout << std::setw(5) << fTrack->GetCurrentStepNumber() << " "
|
||||
<< std::setw(6) << G4BestUnit(fTrack->GetPosition().x(),"Length")
|
||||
<< std::setw(6) << G4BestUnit(fTrack->GetPosition().y(),"Length")
|
||||
<< std::setw(6) << G4BestUnit(fTrack->GetPosition().z(),"Length")
|
||||
<< std::setw(6) << G4BestUnit(fTrack->GetKineticEnergy(),"Energy")
|
||||
<< std::setw(6) << G4BestUnit(fStep->GetTotalEnergyDeposit(),"Energy")
|
||||
<< std::setw(6) << G4BestUnit(fStep->GetStepLength(),"Length")
|
||||
<< std::setw(6) << G4BestUnit(fTrack->GetTrackLength(),"Length")
|
||||
<< " ";
|
||||
|
||||
// if( fStepStatus != fWorldBoundary){
|
||||
if( fTrack->GetNextVolume() != 0 ) {
|
||||
G4cout << std::setw(10) << fTrack->GetVolume()->GetName();
|
||||
} else {
|
||||
G4cout << std::setw(10) << "OutOfWorld";
|
||||
}
|
||||
|
||||
if(fStep->GetPostStepPoint()->GetProcessDefinedStep() != NULL){
|
||||
G4cout << " "
|
||||
<< std::setw(10) << fStep->GetPostStepPoint()->GetProcessDefinedStep()
|
||||
->GetProcessName();
|
||||
} else {
|
||||
G4cout << " UserLimit";
|
||||
}
|
||||
|
||||
G4cout << G4endl;
|
||||
|
||||
if( verboseLevel == 2 ){
|
||||
G4int tN2ndariesTot = fN2ndariesAtRestDoIt +
|
||||
fN2ndariesAlongStepDoIt +
|
||||
fN2ndariesPostStepDoIt;
|
||||
if(tN2ndariesTot>0){
|
||||
G4cout << " :----- List of 2ndaries - "
|
||||
<< "#SpawnInStep=" << std::setw(3) << tN2ndariesTot
|
||||
<< "(Rest=" << std::setw(2) << fN2ndariesAtRestDoIt
|
||||
<< ",Along=" << std::setw(2) << fN2ndariesAlongStepDoIt
|
||||
<< ",Post=" << std::setw(2) << fN2ndariesPostStepDoIt
|
||||
<< "), "
|
||||
<< "#SpawnTotal=" << std::setw(3) << (*fSecondary).size()
|
||||
<< " ---------------"
|
||||
<< G4endl;
|
||||
|
||||
for(size_t lp1=(*fSecondary).size()-tN2ndariesTot;
|
||||
lp1<(*fSecondary).size(); lp1++){
|
||||
G4cout << " : "
|
||||
<< std::setw(6)
|
||||
<< G4BestUnit((*fSecondary)[lp1]->GetPosition().x(),"Length")
|
||||
<< std::setw(6)
|
||||
<< G4BestUnit((*fSecondary)[lp1]->GetPosition().y(),"Length")
|
||||
<< std::setw(6)
|
||||
<< G4BestUnit((*fSecondary)[lp1]->GetPosition().z(),"Length")
|
||||
<< std::setw(6)
|
||||
<< G4BestUnit((*fSecondary)[lp1]->GetKineticEnergy(),"Energy")
|
||||
<< std::setw(10)
|
||||
<< (*fSecondary)[lp1]->GetDefinition()->GetParticleName();
|
||||
G4cout << G4endl;
|
||||
}
|
||||
|
||||
G4cout << " :-----------------------------"
|
||||
<< "----------------------------------"
|
||||
<< "-- EndOf2ndaries Info ---------------"
|
||||
<< G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
G4cout.precision(prec);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4SteppingVerbose::TrackingStarted()
|
||||
{
|
||||
|
||||
CopyState();
|
||||
G4int prec = G4cout.precision(3);
|
||||
if( verboseLevel > 0 ){
|
||||
|
||||
G4cout << std::setw( 5) << "Step#" << " "
|
||||
<< std::setw( 6) << "X" << " "
|
||||
<< std::setw( 6) << "Y" << " "
|
||||
<< std::setw( 6) << "Z" << " "
|
||||
<< std::setw( 9) << "KineE" << " "
|
||||
<< std::setw( 9) << "dEStep" << " "
|
||||
<< std::setw(10) << "StepLeng"
|
||||
<< std::setw(10) << "TrakLeng"
|
||||
<< std::setw(10) << "Volume" << " "
|
||||
<< std::setw(10) << "Process" << G4endl;
|
||||
|
||||
G4cout << std::setw(5) << fTrack->GetCurrentStepNumber() << " "
|
||||
<< std::setw(6) << G4BestUnit(fTrack->GetPosition().x(),"Length")
|
||||
<< std::setw(6) << G4BestUnit(fTrack->GetPosition().y(),"Length")
|
||||
<< std::setw(6) << G4BestUnit(fTrack->GetPosition().z(),"Length")
|
||||
<< std::setw(6) << G4BestUnit(fTrack->GetKineticEnergy(),"Energy")
|
||||
<< std::setw(6) << G4BestUnit(fStep->GetTotalEnergyDeposit(),"Energy")
|
||||
<< std::setw(6) << G4BestUnit(fStep->GetStepLength(),"Length")
|
||||
<< std::setw(6) << G4BestUnit(fTrack->GetTrackLength(),"Length")
|
||||
<< " ";
|
||||
|
||||
if(fTrack->GetNextVolume()){
|
||||
G4cout << std::setw(10) << fTrack->GetVolume()->GetName();
|
||||
} else {
|
||||
G4cout << std::setw(10) << "OutOfWorld";
|
||||
}
|
||||
G4cout << " initStep" << G4endl;
|
||||
}
|
||||
G4cout.precision(prec);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
402
geant4/LEMuSR/src/lem4TabulatedElementField2D.cc
Normal file
402
geant4/LEMuSR/src/lem4TabulatedElementField2D.cc
Normal file
@ -0,0 +1,402 @@
|
||||
#include "lem4TabulatedElementField2D.hh"
|
||||
//#include "lem4EventAction.hh" // cks: just to get the event nr. if needed.
|
||||
#include "lem4Parameters.hh" /// Comment by TS - is this really needed?
|
||||
///#include "lem4ErrorMessage.hh" -> PUT SOME LIMIT DURING WRONG UNIT CONVERSIONS
|
||||
#include "G4UnitsTable.hh"
|
||||
#include <string>
|
||||
|
||||
//lem4TabulatedElementField2D::lem4TabulatedElementField2D(const char* filename, G4double fieldValue, G4double lenUnit, G4double fieldNormalisation, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter) : F04ElementField(positionOfTheCenter, logVolume),
|
||||
// ffieldValue(fieldValue)
|
||||
|
||||
|
||||
///G4double lenUnit, G4double fieldNormalisation,
|
||||
|
||||
lem4TabulatedElementField2D::lem4TabulatedElementField2D(const char* filename, const char fieldType, G4double fieldValue, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter) : F04ElementField(positionOfTheCenter, logVolume),
|
||||
fldType(fieldType), ffieldValue(fieldValue)
|
||||
{
|
||||
G4cout << "\n-----------------------------------------------------------";
|
||||
|
||||
// The DEFAULT user-defined field units for E and B (kilovolt/mm and tesla)
|
||||
// NOTE: Should be the same as EMfieldUnit defined in DetectorConstruction.cc!
|
||||
if (fldType == 'E') {G4cout << ("\n Electric field 2D"); fUnit = "kV/mm"; fieUnit= kilovolt/mm;}
|
||||
else if (fldType == 'B') {G4cout << ("\n Magnetic field 2D"); fUnit = "T"; fieUnit = tesla;}
|
||||
|
||||
G4cout << "\n-----------------------------------------------------------" << G4endl;
|
||||
G4cout << "\n ---> Reading the "<< fldType <<"-field map from " << filename << " ... " << G4endl;
|
||||
|
||||
// Open the file for reading
|
||||
std::ifstream file( filename );
|
||||
|
||||
///char buffer[256]; //not needed with file peek
|
||||
// Ignore first blank line
|
||||
// file.getline(buffer,256);
|
||||
|
||||
// Read table dimensions
|
||||
//G4String lUnit, fUnit;
|
||||
//G4double cFact;
|
||||
//fieldNormalisation = cFact;
|
||||
//lenUnit = 1*cm,
|
||||
//fieldNormalisation = 0.00001;
|
||||
// 101 1 1001 cm tesla 0.00001
|
||||
//G4double fieldNorm, lenNorm;
|
||||
//G4cout<< lUnit << " XXXX " << fUnit << G4endl;
|
||||
//G4cout<< "Tesla in G4 is "<< tesla << ", while kV/mm is " << kilovolt/mm << G4endl;
|
||||
|
||||
///file >> nr >> nDummy >> nz >> lUnit >> fUnit >> fieldNormalisation; // Note dodgy order
|
||||
// Read the file header
|
||||
file >> nr >> nz >> lUnit >> fieldNormalisation;
|
||||
// Add manually the length unit and norm. factor in the field-map file if missing!
|
||||
|
||||
G4cout << " The grid consists of [" << nr << " x " << nz << "] r and z values" << G4endl;
|
||||
|
||||
// Get the field map LENGTH unit and its value in G4 native units.
|
||||
lenUnit = G4UnitDefinition::GetValueOf(lUnit);
|
||||
G4cout << " Field length unit = " << lUnit << ", in G4 native units = " << lenUnit << G4endl;
|
||||
|
||||
/*
|
||||
// Get the EM field AMPLITUDE unit and its value in G4 native units.
|
||||
// Separate the E case from B, since E presents complex units (e.g. kV/mm)
|
||||
if (fldType == 'E') {
|
||||
G4double volNorm, lenNorm;
|
||||
std::string::size_type pos = fUnit.find("/");
|
||||
std::string v_unit = fUnit.substr(0, pos); // Voltage unit
|
||||
std::string l_unit = fUnit.substr(pos+1); // Length unit
|
||||
|
||||
volNorm = G4UnitDefinition::GetValueOf(v_unit);
|
||||
lenNorm = G4UnitDefinition::GetValueOf(l_unit);
|
||||
///G4cout<< v_unit << " " << l_unit << G4endl;
|
||||
///G4cout<< volNorm << " " << lenNorm << G4endl;
|
||||
|
||||
fNorm = volNorm/lenNorm; // Electric field unit = [Voltage]/[Length]
|
||||
G4cout << " Electric field unit = " << fUnit << ", in G4 native units = " << fNorm << G4endl;
|
||||
}
|
||||
|
||||
else if (fldType == 'B') {
|
||||
fNorm = G4UnitDefinition::GetValueOf(fUnit);
|
||||
G4cout << " Magnetic field unit = " << fUnit << ", in G4 native units = " << fNorm << G4endl;
|
||||
}
|
||||
*/
|
||||
G4cout << " Field map normalisation factor = " << fieldNormalisation << G4endl;
|
||||
|
||||
|
||||
///fieldValue = fieldValue*fNorm/tesla; // Convert
|
||||
|
||||
///fieldValue = fieldValue/fNorm; // Convert
|
||||
//double lenUnit = meter;
|
||||
//double fieldUnit= tesla;
|
||||
|
||||
//lenNorm = G4UnitDefinition::GetValueOf(leng_unit);
|
||||
//lenNorm = G4UnitDefinition::GetValueOf(lUnit);
|
||||
//fieldNorm = G4UnitDefinition::GetValueOf(fNorm);
|
||||
|
||||
|
||||
//G4double GetNewDoubleValue(const char*)
|
||||
//fieldNorm = G4UIcmdWithADouble::SetNewDoubleValue(fNorm);
|
||||
//fieldNorm = G4UIcmdWithADoubleAndUnit::GetNewUnitValue(fNorm); //GetNewDoubleRawValue(fNorm);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
G4cout << " Length Unit = " << leng_unit << G4endl; //lUnit
|
||||
G4cout << " Field Unit = " << leng_unit << G4endl; //lUnit
|
||||
|
||||
G4cout << " Length Unit = " << leng_unit << G4endl; //lUnit
|
||||
G4cout << " Conv. Unit = " << lenNorm << G4endl;
|
||||
G4cout << " Field Unit = " << fNorm << G4endl;
|
||||
G4cout << " Conv. Unit = " << fieldNorm << G4endl;
|
||||
G4cout << " Norm. Fact = " << cFact << G4endl;
|
||||
|
||||
*/
|
||||
/// FIELD NORMALISATION FACTOR INSIDE FIELD MAPS IS SUCH THAT (MAX. FIELD VALUE)*FNORMFACT = 1!
|
||||
/// CHANGE SIGN TO REVERT FIELD DIRECTION! THE FIELD MAP HAS NO UNITS.
|
||||
|
||||
///G4cout << " Field set to "<< fieldValue/fNorm << " " << fUnit << G4endl; ///????
|
||||
///G4cout << " Field set to "<< fieldValue*fNorm << " " << fUnit << G4endl;
|
||||
///G4cout << " Field set to "<< fieldValue << " " << fUnit << G4endl;
|
||||
|
||||
|
||||
// Set up storage space for the 2D table
|
||||
rField.resize(nr);
|
||||
zField.resize(nr);
|
||||
int ir, iz;
|
||||
for (ir=0; ir<nr; ir++) {
|
||||
rField[ir].resize(nz);
|
||||
zField[ir].resize(nz);
|
||||
}
|
||||
|
||||
// Ignore header information. All lines whose first character
|
||||
// is '%' are considered to be part of the header.
|
||||
do {
|
||||
file.ignore(256, '\n');
|
||||
} while (file.peek() == '%');
|
||||
|
||||
/// Attention: The old version works only ONCE, i.e. at a STOP signal, e.g. !
|
||||
//do {
|
||||
// file.getline(buffer, 256, '!');
|
||||
//} while (buffer[0] != '!');
|
||||
|
||||
|
||||
// Read in the data: [r, z, EMr, EMz]
|
||||
double rval, zval, fr, fz;
|
||||
for (ir=0; ir<nr; ir++) {
|
||||
for (iz=0; iz<nz; iz++) {
|
||||
file >> rval >> zval >> fr >> fz;
|
||||
//G4cout << rval << " v " << zval << " v " << fr << " v " << fz << G4endl;
|
||||
if ( ir==0 && iz==0 ) {
|
||||
minimumr = rval * lenUnit;
|
||||
minimumz = zval * lenUnit;
|
||||
}
|
||||
rField[ir][iz] = fr*fieldNormalisation;
|
||||
zField[ir][iz] = fz*fieldNormalisation;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
|
||||
maximumr = rval * lenUnit;
|
||||
maximumz = zval * lenUnit;
|
||||
|
||||
G4String volumeName = logVolume->GetName().substr(4);
|
||||
|
||||
G4cout << " ... done reading " << G4endl;
|
||||
G4cout << "\n ---> " << fldType << "-field in volume "<< volumeName
|
||||
<< " set to: " << fieldValue/fieUnit << " " << fUnit << G4endl;
|
||||
G4cout << "\n ---> Assumed order: r, z, "<< fldType <<"r, "<< fldType <<"z "
|
||||
<< "\n Min values r, z: "
|
||||
<< minimumr/cm << " " << minimumz/cm << " cm "
|
||||
<< "\n Max values r, z: "
|
||||
<< maximumr/cm << " " << maximumz/cm << " cm" << G4endl;
|
||||
|
||||
|
||||
// Should really check that the limits are not the wrong way around.
|
||||
if (maximumr < minimumr) {Invert("r");}
|
||||
if (maximumz < minimumz) {Invert("z");}
|
||||
|
||||
if ((maximumr < minimumr) || (maximumz < minimumz)) {
|
||||
G4cout << "\n ---> After reordering:"
|
||||
<< "\n Min values r, z: "
|
||||
<< minimumr/cm << " " << minimumz/cm << " cm "
|
||||
<< "\n Max values r, z: "
|
||||
<< maximumr/cm << " " << maximumz/cm << " cm " << G4endl;
|
||||
}
|
||||
|
||||
dr = maximumr - minimumr;
|
||||
dz = maximumz - minimumz;
|
||||
|
||||
G4cout << " Range of values: "
|
||||
<< dr/cm << " cm (in r) and " << dz/cm << " cm (in z)"
|
||||
<< "\n-----------------------------------------------------------\n" << G4endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void lem4TabulatedElementField2D::addFieldValue(const G4double point[4],
|
||||
G4double *field ) const
|
||||
{
|
||||
|
||||
///G4cout << "addFieldValue is being called" << G4endl;
|
||||
G4double EMf[3]; // EM field value obtained from the field map
|
||||
///TS
|
||||
///G4cout<<"TTfileTT Global coord. ("<<point[0]/mm<<", "<<point[1]/mm<<", "<<point[2]/mm<<")."<<G4endl;
|
||||
G4ThreeVector global(point[0],point[1],point[2]);
|
||||
G4ThreeVector local;
|
||||
|
||||
local = global2local.TransformPoint(global);
|
||||
///TS
|
||||
///G4cout<<"TTfileTT Local coord. ("<<local[0]/mm<<", "<<local[1]/mm<<", "<<local[2]/mm<<")."<<G4endl;
|
||||
///G4cout<<"The LOGICAL volume is named "<<lvolume->GetName()<<G4endl;
|
||||
|
||||
double r = sqrt(local.x()*local.x()+local.y()*local.y());
|
||||
double z = local.z(); //Modified by TS
|
||||
/// double z = fabs(local.z());
|
||||
/// double z_sign =(local.z()>0) ? 1.:-1.;
|
||||
|
||||
// G4cout<<"Global points= "<<point[0]<<", "<<point[1]<<", "<<point[2]<<", Local point= "<<x<<", "<<y<<", "<<z<<G4endl;
|
||||
|
||||
// Check that the point is within the defined region
|
||||
if ( r<maximumr && z<maximumz ) {
|
||||
// if (evNr>evNrKriz) std::cout<<"bol som tu"<<std::endl;
|
||||
|
||||
// Position of given point within region, normalized to the range
|
||||
// [0,1]
|
||||
double rfraction = (r - minimumr) / dr;
|
||||
double zfraction = (z - minimumz) / dz;
|
||||
|
||||
// Need addresses of these to pass to modf below.
|
||||
// modf uses its second argument as an OUTPUT argument.
|
||||
double rdindex, zdindex;
|
||||
|
||||
// Position of the point within the cuboid defined by the
|
||||
// nearest surrounding tabulated points
|
||||
double rlocal = ( modf(rfraction*(nr-1), &rdindex));
|
||||
double zlocal = ( modf(zfraction*(nz-1), &zdindex));
|
||||
|
||||
// The indices of the nearest tabulated point whose coordinates
|
||||
// are all less than those of the given point
|
||||
int rindex = static_cast<int>(rdindex);
|
||||
int zindex = static_cast<int>(zdindex);
|
||||
|
||||
//cks The following check is necessary - even though rindex and zindex should never be out of range,
|
||||
// it may happen (due to some rounding error ?). It is better to leave the check here.
|
||||
if ((rindex<0)||(rindex>(nr-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: rindex out of range! rindex="<<rindex<<" r="<<r<<" rfraction="<<rfraction<<std::endl;
|
||||
if (rindex<0) rindex=0;
|
||||
else rindex=nr-2;
|
||||
}
|
||||
if ((zindex<0)||(zindex>(nz-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: zindex out of range! zindex="<<zindex<<" z="<<z<<" zfraction="<<zfraction<<std::endl;
|
||||
if (zindex<0) zindex=0;
|
||||
else zindex=nz-2;
|
||||
}
|
||||
|
||||
// G4cout<<"xField["<<xindex<<"]["<<zindex<<"]="<<xField[xindex ][zindex ]<<G4endl;
|
||||
// G4cout<<"zField["<<xindex<<"]["<<zindex<<"]="<<zField[xindex ][zindex ]<<G4endl;
|
||||
|
||||
// Interpolate between the neighbouring points
|
||||
double EMfield_R =
|
||||
rField[rindex ][zindex ] * (1-rlocal) * (1-zlocal) +
|
||||
rField[rindex ][zindex+1] * (1-rlocal) * zlocal +
|
||||
rField[rindex+1][zindex ] * rlocal * (1-zlocal) +
|
||||
rField[rindex+1][zindex+1] * rlocal * zlocal ;
|
||||
EMf[0] = (r>0) ? EMfield_R * (local.x() /r) : 0.;
|
||||
EMf[1] = (r>0) ? EMfield_R * (local.y() /r) : 0.;
|
||||
EMf[2] =
|
||||
zField[rindex ][zindex ] * (1-rlocal) * (1-zlocal) +
|
||||
zField[rindex ][zindex+1] * (1-rlocal) * zlocal +
|
||||
zField[rindex+1][zindex ] * rlocal * (1-zlocal) +
|
||||
zField[rindex+1][zindex+1] * rlocal * zlocal ;
|
||||
|
||||
EMf[0] *= ffieldValue; /// * z_sign; ///Modified by TS: Not need for FULL field map
|
||||
EMf[1] *= ffieldValue; /// * z_sign; ///Modified by TS: Not need for FULL field map
|
||||
EMf[2] *= ffieldValue;
|
||||
|
||||
///G4cout << "The local coord. is: x_l=" << rlocal << ", z_l=" << zlocal << G4endl;
|
||||
///G4cout << "The coord. is: x_loc=" << local.x() << ", y_loc=" << local.y() << ", z_loc=" << local.z() << G4endl;
|
||||
|
||||
G4ThreeVector finalField(EMf[0],EMf[1],EMf[2]);
|
||||
finalField = global2local.Inverse().TransformAxis(finalField);
|
||||
|
||||
if (fldType == 'B') {
|
||||
field[0] += finalField.x();
|
||||
field[1] += finalField.y();
|
||||
field[2] += finalField.z();
|
||||
}
|
||||
else if (fldType == 'E') {
|
||||
field[3] += finalField.x();
|
||||
field[4] += finalField.y();
|
||||
field[5] += finalField.z();
|
||||
}
|
||||
|
||||
}
|
||||
// G4cout<<"Kamil: Field: ("<<field[0]/tesla<<","<<field[1]/tesla<<","<<field[2]/tesla<<")"<<G4endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
G4double lem4TabulatedElementField2D::GetNominalFieldValue() {
|
||||
return ffieldValue;
|
||||
}
|
||||
|
||||
void lem4TabulatedElementField2D::SetNominalFieldValue(G4double newFieldValue) {
|
||||
// Rescale the magnetic field for a new value of the magnetic field
|
||||
ffieldValue=newFieldValue;
|
||||
|
||||
///G4cout<<"lem4TabulatedElementField2D.cc: ffieldValue changed to "<< ffieldValue << fUnit << G4endl;
|
||||
G4cout<<"lem4TabulatedElementField2D.cc: ffieldValue changed to "<< ffieldValue/fieUnit << fUnit << G4endl;
|
||||
///G4cout<<"lem4TabulatedElementField2D.cc: ffieldValue changed to "<< ffieldValue/tesla << " T"<< G4endl;
|
||||
}
|
||||
|
||||
void lem4TabulatedElementField2D::Invert(const char* indexToInvert) {
|
||||
// This function inverts the indices of the field table for a given axis (r or z).
|
||||
// It should be called in the case when the r or z coordinate in the initial
|
||||
// field table is ordered in the decreasing order.
|
||||
std::vector< std::vector< double > > rFieldTemp(rField);
|
||||
std::vector< std::vector< double > > zFieldTemp(zField);
|
||||
G4bool invertR=false;
|
||||
G4bool invertZ=false;
|
||||
|
||||
G4cout<<"Check that the lem4TabulatedElementField2D::Invert() function works properly!"<<G4endl;
|
||||
G4cout<<"It has not been tested yet!"<<G4endl;
|
||||
|
||||
if (strcmp(indexToInvert,"r")==0) {invertR=true; std::swap(maximumr,minimumr);}
|
||||
if (strcmp(indexToInvert,"z")==0) {invertZ=true; std::swap(maximumz,minimumz);}
|
||||
|
||||
for (int ir=0; ir<nr; ir++) {
|
||||
for (int iz=0; iz<nz; iz++) {
|
||||
if (invertR) {
|
||||
rField[ir][iz] = rFieldTemp[nr-1-ir][iz];
|
||||
zField[ir][iz] = zFieldTemp[nr-1-ir][iz];
|
||||
}
|
||||
else if(invertZ) {
|
||||
rField[ir][iz] = rFieldTemp[ir][nz-1-iz];
|
||||
zField[ir][iz] = zFieldTemp[ir][nz-1-iz];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//#include "G4UIcmdWithADouble.hh"
|
||||
//#include "G4UIcmdWithADoubleAndUnit.hh"
|
||||
|
||||
//#include <iostream>
|
||||
//using namespace std;
|
||||
|
||||
///G4double G4UIcmdWithADouble::GetNewDoubleValue(const char* paramString)
|
||||
|
||||
|
||||
///**********************///
|
||||
//char str[] ="- This, a sample string.";
|
||||
///char str[] ="kilovolt/mm";
|
||||
///char * pch;
|
||||
///printf ("Splitting string \"%s\" into tokens:\n",str);
|
||||
//pch = strtok (str," ,.-");
|
||||
///pch = strtok (str,"*/");
|
||||
///while (pch != NULL)
|
||||
///{
|
||||
///printf ("%s\n",pch);
|
||||
//pch = strtok (NULL, " ,.-");
|
||||
///pch = strtok (NULL,"*/");
|
||||
///}
|
||||
|
||||
///**********************///
|
||||
|
||||
//char str[] ="kilovolt/mm";
|
||||
//char * pch;
|
||||
//printf ("Splitting string \"%s\" into tokens:\n",str);
|
||||
//pch = strtok (str," ,.-");
|
||||
//pch = strtok (str,"/");
|
||||
//for (int i=0; i<2; x++) {
|
||||
//while (pch != NULL)
|
||||
//{
|
||||
// printf ("%s\n",pch);
|
||||
// pch[]
|
||||
//}
|
||||
//pch = strtok (NULL,"*/");
|
||||
//}
|
||||
|
||||
//int x;
|
||||
//for(x=1; x <= 100; x++) {
|
||||
//printf("%d ", x);
|
||||
//}
|
||||
|
||||
///**********************///
|
||||
// Only if field is E!
|
||||
///char str[] = "This is a sample string kilovolt/mm";
|
||||
///char * pch;
|
||||
///printf ("Looking for the '/' character in \"%s\"...\n",str);
|
||||
///pch = strchr(str,'/');
|
||||
///while (pch!=NULL)
|
||||
///{
|
||||
///printf ("found at %d\n",pch-str+1);
|
||||
///pch=strchr(pch+1,'s');
|
||||
///}
|
||||
|
||||
///**********************///
|
||||
|
420
geant4/LEMuSR/src/lem4TabulatedElementField2Df.cc
Normal file
420
geant4/LEMuSR/src/lem4TabulatedElementField2Df.cc
Normal file
@ -0,0 +1,420 @@
|
||||
#include "lem4TabulatedElementField2Df.hh"
|
||||
//#include "lem4EventAction.hh" // cks: just to get the event nr. if needed.
|
||||
#include "lem4Parameters.hh" /// Comment by TS - is this really needed?
|
||||
///#include "lem4ErrorMessage.hh" -> PUT SOME LIMIT DURING WRONG UNIT CONVERSIONS
|
||||
#include "G4UnitsTable.hh"
|
||||
#include <string>
|
||||
|
||||
/// TS ATTENTION: Since B and E are respectively Axial and Polar vectors, their
|
||||
/// transformation upon inversion of coordinates are DIFFERENT!!
|
||||
/// A Polar vector reverses sign when the coordinate axes are reversed.
|
||||
/// An Axial vector does not reverse sign when the coordinate axes are reversed.
|
||||
|
||||
|
||||
/// This version of the 2d axial field map contains an additional two-fold symmetry at z=0.
|
||||
/// Therefore the maps read by this file (ending in 1Dq) are 1/4 of the whole plane map.
|
||||
|
||||
//lem4TabulatedElementField2D::lem4TabulatedElementField2D(const char* filename, G4double fieldValue, G4double lenUnit, G4double fieldNormalisation, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter) : F04ElementField(positionOfTheCenter, logVolume),
|
||||
// ffieldValue(fieldValue)
|
||||
|
||||
|
||||
///G4double lenUnit, G4double fieldNormalisation,
|
||||
|
||||
lem4TabulatedElementField2Df::lem4TabulatedElementField2Df(const char* filename, const char fieldType, G4double fieldValue, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter) : F04ElementField(positionOfTheCenter, logVolume),
|
||||
fldType(fieldType), ffieldValue(fieldValue)
|
||||
{
|
||||
G4cout << "\n-----------------------------------------------------------";
|
||||
|
||||
// The DEFAULT user-defined field units for E and B (kilovolt/mm and tesla)
|
||||
// NOTE: Should be the same as EMfieldUnit defined in DetectorConstruction.cc!
|
||||
if (fldType == 'E') {G4cout << ("\n Electric field 2D - Folded (r, z > 0)"); fUnit = "kV/mm"; fieUnit= kilovolt/mm;}
|
||||
else if (fldType == 'B') {G4cout << ("\n Magnetic field 2D - Folded (r, z > 0)"); fUnit = "T"; fieUnit = tesla;}
|
||||
|
||||
G4cout << "\n-----------------------------------------------------------" << G4endl;
|
||||
G4cout << "\n ---> Reading the "<< fldType <<"-field map from " << filename << " ... " << G4endl;
|
||||
|
||||
// Open the file for reading
|
||||
std::ifstream file( filename );
|
||||
|
||||
///char buffer[256]; //not needed with file peek
|
||||
// Ignore first blank line
|
||||
// file.getline(buffer,256);
|
||||
|
||||
// Read table dimensions
|
||||
//G4String lUnit, fUnit;
|
||||
//G4double cFact;
|
||||
//fieldNormalisation = cFact;
|
||||
//lenUnit = 1*cm,
|
||||
//fieldNormalisation = 0.00001;
|
||||
// 101 1 1001 cm tesla 0.00001
|
||||
//G4double fieldNorm, lenNorm;
|
||||
//G4cout<< lUnit << " XXXX " << fUnit << G4endl;
|
||||
//G4cout<< "Tesla in G4 is "<< tesla << ", while kV/mm is " << kilovolt/mm << G4endl;
|
||||
|
||||
///file >> nr >> nDummy >> nz >> lUnit >> fUnit >> fieldNormalisation; // Note dodgy order
|
||||
// Read the file header
|
||||
file >> nr >> nz >> lUnit >> fieldNormalisation;
|
||||
// Add manually the length unit and norm. factor in the field-map file if missing!
|
||||
|
||||
G4cout << " The grid consists of [" << nr << " x " << nz << "] r and z values" << G4endl;
|
||||
|
||||
// Get the field map LENGTH unit and its value in G4 native units.
|
||||
lenUnit = G4UnitDefinition::GetValueOf(lUnit);
|
||||
G4cout << " Field length unit = " << lUnit << ", in G4 native units = " << lenUnit << G4endl;
|
||||
|
||||
/*
|
||||
// Get the EM field AMPLITUDE unit and its value in G4 native units.
|
||||
// Separate the E case from B, since E presents complex units (e.g. kV/mm)
|
||||
if (fldType == 'E') {
|
||||
G4double volNorm, lenNorm;
|
||||
std::string::size_type pos = fUnit.find("/");
|
||||
std::string v_unit = fUnit.substr(0, pos); // Voltage unit
|
||||
std::string l_unit = fUnit.substr(pos+1); // Length unit
|
||||
|
||||
volNorm = G4UnitDefinition::GetValueOf(v_unit);
|
||||
lenNorm = G4UnitDefinition::GetValueOf(l_unit);
|
||||
///G4cout<< v_unit << " " << l_unit << G4endl;
|
||||
///G4cout<< volNorm << " " << lenNorm << G4endl;
|
||||
|
||||
fNorm = volNorm/lenNorm; // Electric field unit = [Voltage]/[Length]
|
||||
G4cout << " Electric field unit = " << fUnit << ", in G4 native units = " << fNorm << G4endl;
|
||||
}
|
||||
|
||||
else if (fldType == 'B') {
|
||||
fNorm = G4UnitDefinition::GetValueOf(fUnit);
|
||||
G4cout << " Magnetic field unit = " << fUnit << ", in G4 native units = " << fNorm << G4endl;
|
||||
}
|
||||
*/
|
||||
G4cout << " Field map normalisation factor = " << fieldNormalisation << G4endl;
|
||||
|
||||
|
||||
///fieldValue = fieldValue*fNorm/tesla; // Convert
|
||||
|
||||
///fieldValue = fieldValue/fNorm; // Convert
|
||||
//double lenUnit = meter;
|
||||
//double fieldUnit= tesla;
|
||||
|
||||
//lenNorm = G4UnitDefinition::GetValueOf(leng_unit);
|
||||
//lenNorm = G4UnitDefinition::GetValueOf(lUnit);
|
||||
//fieldNorm = G4UnitDefinition::GetValueOf(fNorm);
|
||||
|
||||
|
||||
//G4double GetNewDoubleValue(const char*)
|
||||
//fieldNorm = G4UIcmdWithADouble::SetNewDoubleValue(fNorm);
|
||||
//fieldNorm = G4UIcmdWithADoubleAndUnit::GetNewUnitValue(fNorm); //GetNewDoubleRawValue(fNorm);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
G4cout << " Length Unit = " << leng_unit << G4endl; //lUnit
|
||||
G4cout << " Field Unit = " << leng_unit << G4endl; //lUnit
|
||||
|
||||
G4cout << " Length Unit = " << leng_unit << G4endl; //lUnit
|
||||
G4cout << " Conv. Unit = " << lenNorm << G4endl;
|
||||
G4cout << " Field Unit = " << fNorm << G4endl;
|
||||
G4cout << " Conv. Unit = " << fieldNorm << G4endl;
|
||||
G4cout << " Norm. Fact = " << cFact << G4endl;
|
||||
|
||||
*/
|
||||
/// FIELD NORMALISATION FACTOR INSIDE FIELD MAPS IS SUCH THAT (MAX. FIELD VALUE)*FNORMFACT = 1!
|
||||
/// CHANGE SIGN TO REVERT FIELD DIRECTION! THE FIELD MAP HAS NO UNITS.
|
||||
|
||||
///G4cout << " Field set to "<< fieldValue/fNorm << " " << fUnit << G4endl; ///????
|
||||
///G4cout << " Field set to "<< fieldValue*fNorm << " " << fUnit << G4endl;
|
||||
///G4cout << " Field set to "<< fieldValue << " " << fUnit << G4endl;
|
||||
|
||||
// Set up storage space for the 2D table
|
||||
rField.resize(nr);
|
||||
zField.resize(nr);
|
||||
int ir, iz;
|
||||
for (ir=0; ir<nr; ir++) {
|
||||
rField[ir].resize(nz);
|
||||
zField[ir].resize(nz);
|
||||
}
|
||||
|
||||
|
||||
// Ignore header information. All lines whose first character
|
||||
// is '%' are considered to be part of the header.
|
||||
do {
|
||||
file.ignore(256, '\n');
|
||||
} while (file.peek() == '%');
|
||||
|
||||
/// ATTENTION: OLD VERSION WORKS ONLY ONCE, AT A STOP SIGNAL, E.G. !
|
||||
//do {
|
||||
// file.getline(buffer, 256, '!');
|
||||
//} while (buffer[0] != '!');
|
||||
|
||||
// Read in the data: [r, z, EMr, EMz]
|
||||
double rval,zval,fr,fz;
|
||||
for (ir=0; ir<nr; ir++) {
|
||||
for (iz=0; iz<nz; iz++) {
|
||||
file >> rval >> zval >> fr >> fz;
|
||||
if ( ir==0 && iz==0 ) {
|
||||
minimumr = rval * lenUnit;
|
||||
minimumz = zval * lenUnit;
|
||||
}
|
||||
rField[ir][iz] = fr*fieldNormalisation;
|
||||
zField[ir][iz] = fz*fieldNormalisation;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
|
||||
maximumr = rval * lenUnit;
|
||||
maximumz = zval * lenUnit;
|
||||
|
||||
G4String volumeName = logVolume->GetName().substr(4);
|
||||
|
||||
G4cout << " ... done reading " << G4endl;
|
||||
G4cout << "\n ---> " << fldType << "-field in volume "<< volumeName
|
||||
<< " set to: " << fieldValue/fieUnit << " " << fUnit << G4endl;
|
||||
G4cout << "\n ---> Assumed order: r, z, "<< fldType <<"r, "<< fldType <<"z "
|
||||
<< "\n Min values r, z: "
|
||||
<< minimumr/cm << " " << minimumz/cm << " cm "
|
||||
<< "\n Max values r, z: "
|
||||
<< maximumr/cm << " " << maximumz/cm << " cm" << G4endl;
|
||||
|
||||
|
||||
// Should really check that the limits are not the wrong way around.
|
||||
if (maximumr < minimumr) {Invert("r");}
|
||||
if (maximumz < minimumz) {Invert("z");}
|
||||
|
||||
if ((maximumr < minimumr) || (maximumz < minimumz)) {
|
||||
G4cout << "\n ---> After reordering:"
|
||||
<< "\n Min values r, z: "
|
||||
<< minimumr/cm << " " << minimumz/cm << " cm "
|
||||
<< "\n Max values r, z: "
|
||||
<< maximumr/cm << " " << maximumz/cm << " cm " << G4endl;
|
||||
}
|
||||
|
||||
dr = maximumr - minimumr;
|
||||
dz = maximumz - minimumz;
|
||||
|
||||
G4cout << " Range of values: "
|
||||
<< dr/cm << " cm (in r) and " << dz/cm << " cm (in z)"
|
||||
<< "\n-----------------------------------------------------------\n" << G4endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void lem4TabulatedElementField2Df::addFieldValue(const G4double point[4],
|
||||
G4double *field ) const
|
||||
{
|
||||
G4double EMf[3]; // EM field value obtained from the field map
|
||||
G4ThreeVector global(point[0],point[1],point[2]);
|
||||
G4ThreeVector local;
|
||||
|
||||
local = global2local.TransformPoint(global);
|
||||
|
||||
/// The folded 2D field map contains only positive r and z!
|
||||
double r = sqrt(local.x()*local.x()+local.y()*local.y());
|
||||
double z = fabs(local.z());
|
||||
/// Store the z_sign and use it when extending map to negative z-values
|
||||
double z_sign =(local.z()>0) ? 1.:-1.;
|
||||
|
||||
///double z = 0; /// An alternative approach
|
||||
/// E is a Polar vectorn, while B is an axial one (pseudovector)! TS
|
||||
///if (fldType == 'E') {z = local.z();}
|
||||
///else if (fldType == 'B') {z = fabs(local.z());}
|
||||
///G4cout<<"Global points= "<< z << G4endl;
|
||||
|
||||
// G4cout<<"Global points= "<<point[0]<<", "<<point[1]<<", "<<point[2]<<", Local point= "<<x<<", "<<y<<", "<<z<<G4endl;
|
||||
|
||||
// Check that the point is within the defined region
|
||||
if ( r<maximumr && z<maximumz ) {
|
||||
// if (evNr>evNrKriz) std::cout<<"bol som tu"<<std::endl;
|
||||
|
||||
// Position of given point within region, normalized to the range
|
||||
// [0,1]
|
||||
double rfraction = (r - minimumr) / dr;
|
||||
double zfraction = (z - minimumz) / dz;
|
||||
|
||||
// Need addresses of these to pass to modf below.
|
||||
// modf uses its second argument as an OUTPUT argument.
|
||||
double rdindex, zdindex;
|
||||
|
||||
// Position of the point within the cuboid defined by the
|
||||
// nearest surrounding tabulated points
|
||||
double rlocal = ( modf(rfraction*(nr-1), &rdindex));
|
||||
double zlocal = ( modf(zfraction*(nz-1), &zdindex));
|
||||
|
||||
// The indices of the nearest tabulated point whose coordinates
|
||||
// are all less than those of the given point
|
||||
int rindex = static_cast<int>(rdindex);
|
||||
int zindex = static_cast<int>(zdindex);
|
||||
|
||||
//cks The following check is necessary - even though rindex and zindex should never be out of range,
|
||||
// it may happen (due to some rounding error ?). It is better to leave the check here.
|
||||
if ((rindex<0)||(rindex>(nr-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: rindex out of range! rindex="<<rindex<<" r="<<r<<" rfraction="<<rfraction<<std::endl;
|
||||
if (rindex<0) rindex=0;
|
||||
else rindex=nr-2;
|
||||
}
|
||||
if ((zindex<0)||(zindex>(nz-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: zindex out of range! zindex="<<zindex<<" z="<<z<<" zfraction="<<zfraction<<std::endl;
|
||||
if (zindex<0) zindex=0;
|
||||
else zindex=nz-2;
|
||||
}
|
||||
|
||||
// G4cout<<"xField["<<xindex<<"]["<<zindex<<"]="<<xField[xindex ][zindex ]<<G4endl;
|
||||
// G4cout<<"zField["<<xindex<<"]["<<zindex<<"]="<<zField[xindex ][zindex ]<<G4endl;
|
||||
|
||||
// Interpolate between the neighbouring points
|
||||
double EMfield_R =
|
||||
rField[rindex ][zindex ] * (1-rlocal) * (1-zlocal) +
|
||||
rField[rindex ][zindex+1] * (1-rlocal) * zlocal +
|
||||
rField[rindex+1][zindex ] * rlocal * (1-zlocal) +
|
||||
rField[rindex+1][zindex+1] * rlocal * zlocal ;
|
||||
EMf[0] = (r>0) ? EMfield_R * (local.x() /r) : 0.;
|
||||
EMf[1] = (r>0) ? EMfield_R * (local.y() /r) : 0.;
|
||||
EMf[2] =
|
||||
zField[rindex ][zindex ] * (1-rlocal) * (1-zlocal) +
|
||||
zField[rindex ][zindex+1] * (1-rlocal) * zlocal +
|
||||
zField[rindex+1][zindex ] * rlocal * (1-zlocal) +
|
||||
zField[rindex+1][zindex+1] * rlocal * zlocal ;
|
||||
|
||||
/// E is a Polar vector, while B is an axial one (pseudovector)! TS
|
||||
/// Hence, during an r-axis folding they transform as follows:
|
||||
|
||||
if (fldType == 'B') { // Axial vector
|
||||
EMf[0] *= ffieldValue * z_sign;
|
||||
EMf[1] *= ffieldValue * z_sign;
|
||||
EMf[2] *= ffieldValue;
|
||||
}
|
||||
else if (fldType == 'E') { // Polar vector
|
||||
EMf[0] *= ffieldValue;
|
||||
EMf[1] *= ffieldValue;
|
||||
EMf[2] *= ffieldValue * z_sign;
|
||||
}
|
||||
|
||||
///G4cout << "The local coord. is: x_l=" << rlocal << ", z_l=" << zlocal << G4endl;
|
||||
///G4cout << "The coord. is: x_loc=" << local.x() << ", y_loc=" << local.y() << ", z_loc=" << local.z() << G4endl;
|
||||
|
||||
|
||||
G4ThreeVector finalField(EMf[0],EMf[1],EMf[2]);
|
||||
finalField = global2local.Inverse().TransformAxis(finalField);
|
||||
|
||||
if (fldType == 'B') {
|
||||
field[0] += finalField.x();
|
||||
field[1] += finalField.y();
|
||||
field[2] += finalField.z();
|
||||
}
|
||||
else if (fldType == 'E') {
|
||||
field[3] += finalField.x();
|
||||
field[4] += finalField.y();
|
||||
field[5] += finalField.z();
|
||||
}
|
||||
|
||||
}
|
||||
// G4cout<<"Kamil: Field: ("<<field[0]/tesla<<","<<field[1]/tesla<<","<<field[2]/tesla<<")"<<G4endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
G4double lem4TabulatedElementField2Df::GetNominalFieldValue() {
|
||||
return ffieldValue;
|
||||
}
|
||||
|
||||
void lem4TabulatedElementField2Df::SetNominalFieldValue(G4double newFieldValue) {
|
||||
// Rescale the magnetic field for a new value of the magnetic field
|
||||
ffieldValue=newFieldValue;
|
||||
|
||||
///G4cout<<"lem4TabulatedElementField2Df.cc: ffieldValue changed to "<< ffieldValue << fUnit << G4endl;
|
||||
G4cout<<"lem4TabulatedElementField2Df.cc: ffieldValue changed to "<< ffieldValue/fieUnit << fUnit << G4endl;
|
||||
///G4cout<<"lem4TabulatedElementField2Df.cc: ffieldValue changed to "<< ffieldValue/tesla << " T"<< G4endl;
|
||||
}
|
||||
|
||||
void lem4TabulatedElementField2Df::Invert(const char* indexToInvert) {
|
||||
// This function inverts the indices of the field table for a given axis (r or z).
|
||||
// It should be called in the case when the r or z coordinate in the initial
|
||||
// field table is ordered in the decreasing order.
|
||||
std::vector< std::vector< double > > rFieldTemp(rField);
|
||||
std::vector< std::vector< double > > zFieldTemp(zField);
|
||||
G4bool invertR=false;
|
||||
G4bool invertZ=false;
|
||||
|
||||
G4cout<<"Check that the lem4TabulatedElementField2Df::Invert() function works properly!"<<G4endl;
|
||||
G4cout<<"It has not been tested yet!"<<G4endl;
|
||||
|
||||
if (strcmp(indexToInvert,"r")==0) {invertR=true; std::swap(maximumr,minimumr);}
|
||||
if (strcmp(indexToInvert,"z")==0) {invertZ=true; std::swap(maximumz,minimumz);}
|
||||
|
||||
for (int ir=0; ir<nr; ir++) {
|
||||
for (int iz=0; iz<nz; iz++) {
|
||||
if (invertR) {
|
||||
rField[ir][iz] = rFieldTemp[nr-1-ir][iz];
|
||||
zField[ir][iz] = zFieldTemp[nr-1-ir][iz];
|
||||
}
|
||||
else if(invertZ) {
|
||||
rField[ir][iz] = rFieldTemp[ir][nz-1-iz];
|
||||
zField[ir][iz] = zFieldTemp[ir][nz-1-iz];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//#include "G4UIcmdWithADouble.hh"
|
||||
//#include "G4UIcmdWithADoubleAndUnit.hh"
|
||||
|
||||
//#include <iostream>
|
||||
//using namespace std;
|
||||
|
||||
///G4double G4UIcmdWithADouble::GetNewDoubleValue(const char* paramString)
|
||||
|
||||
|
||||
///**********************///
|
||||
//char str[] ="- This, a sample string.";
|
||||
///char str[] ="kilovolt/mm";
|
||||
///char * pch;
|
||||
///printf ("Splitting string \"%s\" into tokens:\n",str);
|
||||
//pch = strtok (str," ,.-");
|
||||
///pch = strtok (str,"*/");
|
||||
///while (pch != NULL)
|
||||
///{
|
||||
///printf ("%s\n",pch);
|
||||
//pch = strtok (NULL, " ,.-");
|
||||
///pch = strtok (NULL,"*/");
|
||||
///}
|
||||
|
||||
///**********************///
|
||||
|
||||
//char str[] ="kilovolt/mm";
|
||||
//char * pch;
|
||||
//printf ("Splitting string \"%s\" into tokens:\n",str);
|
||||
//pch = strtok (str," ,.-");
|
||||
//pch = strtok (str,"/");
|
||||
//for (int i=0; i<2; x++) {
|
||||
//while (pch != NULL)
|
||||
//{
|
||||
// printf ("%s\n",pch);
|
||||
// pch[]
|
||||
//}
|
||||
//pch = strtok (NULL,"*/");
|
||||
//}
|
||||
|
||||
//int x;
|
||||
//for(x=1; x <= 100; x++) {
|
||||
//printf("%d ", x);
|
||||
//}
|
||||
|
||||
///**********************///
|
||||
// Only if field is E!
|
||||
///char str[] = "This is a sample string kilovolt/mm";
|
||||
///char * pch;
|
||||
///printf ("Looking for the '/' character in \"%s\"...\n",str);
|
||||
///pch = strchr(str,'/');
|
||||
///while (pch!=NULL)
|
||||
///{
|
||||
///printf ("found at %d\n",pch-str+1);
|
||||
///pch=strchr(pch+1,'s');
|
||||
///}
|
||||
|
||||
///**********************///
|
||||
|
327
geant4/LEMuSR/src/lem4TabulatedElementField3D.cc
Normal file
327
geant4/LEMuSR/src/lem4TabulatedElementField3D.cc
Normal file
@ -0,0 +1,327 @@
|
||||
#include "lem4TabulatedElementField3D.hh"
|
||||
#include "lem4Parameters.hh"
|
||||
|
||||
#include "G4UnitsTable.hh"
|
||||
#include <string>
|
||||
|
||||
lem4TabulatedElementField3D::lem4TabulatedElementField3D(const char* filename, const char fieldType, G4double fieldValue, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter) : F04ElementField(positionOfTheCenter, logVolume),
|
||||
fldType(fieldType), ffieldValue(fieldValue)
|
||||
{
|
||||
G4cout << "\n-----------------------------------------------------------";
|
||||
|
||||
// The DEFAULT user-defined field units for E and B (kilovolt/mm and tesla)
|
||||
// NOTE: Should be the same as EMfieldUnit defined in DetectorConstruction.cc!
|
||||
if (fldType == 'E') {G4cout << ("\n Electric field 3D"); fUnit = "kV/mm"; fieUnit= kilovolt/mm;}
|
||||
else if (fldType == 'B') {G4cout << ("\n Magnetic field 3D"); fUnit = "T"; fieUnit = tesla;}
|
||||
|
||||
G4cout << "\n-----------------------------------------------------------" << G4endl;
|
||||
G4cout << "\n ---> Reading the "<< fldType <<"-field map from " << filename << " ... " << G4endl;
|
||||
|
||||
// Open the file for reading
|
||||
std::ifstream file( filename );
|
||||
|
||||
// Read the first line of the file header (contains the metadata)
|
||||
char buffer[256];
|
||||
file.getline(buffer,256);
|
||||
|
||||
//G4cout << "The first line of file "<< filename << " is:\n"<< buffer << G4endl;
|
||||
// Read the file header
|
||||
///file >> nx >> ny >> nz >> lUnit >> fieldNormalisation; // OLD VERSION
|
||||
|
||||
// Read the number of arguments and decide filetype - 3 or 6 columns
|
||||
int n_arg = sscanf (buffer,"%d %d %d %s %lf %lf %lf %lf %lf %lf %lf",
|
||||
&nx, &ny, &nz, lUnit, &fieldNormalisation,
|
||||
&minimumx, &maximumx, &minimumy, &maximumy, &minimumz, &maximumz);
|
||||
// Add manually the length unit and norm. factor in the field-map file if missing!
|
||||
|
||||
//printf ("The following data were read in: \n");
|
||||
//printf ("nx = %d, ny = %d, nz = %d, Unit = %s, Norm = %f,\n minx = %f, maxx = %f, miny = %f, maxy = %f, minz = %f, maxz = %f\n",nx,ny,nz,lUnit,fieldNormalisation,minimumx, maximumx, minimumy, maximumy, minimumz, maximumz);
|
||||
///printf ("nx = %d, ny = %d, nz = %d, Unit = %s, Norm = %f,\n minx = %f\n",nx,ny,nz,lUnit,fieldNormalisation,minimumx);
|
||||
//printf ("Number of args read: %d\n", n_arg);
|
||||
|
||||
G4cout << " The grid consists of [" << nx << " x " << ny << " x " << nz << "] x, y, z values" << G4endl;
|
||||
|
||||
// Get the field map LENGTH unit and its value in G4 native units.
|
||||
lenUnit = G4UnitDefinition::GetValueOf(lUnit);
|
||||
G4cout << " Field length unit = " << lUnit << ", in G4 native units = " << lenUnit << G4endl;
|
||||
G4cout << " Field map normalisation factor = " << fieldNormalisation << G4endl;
|
||||
|
||||
// Set up storage space for the 3D table: notice the order!
|
||||
xField.resize(nx);
|
||||
yField.resize(nx);
|
||||
zField.resize(nx);
|
||||
int ix, iy, iz;
|
||||
for (ix=0; ix<nx; ix++) {
|
||||
xField[ix].resize(ny);
|
||||
yField[ix].resize(ny);
|
||||
zField[ix].resize(ny);
|
||||
for (iy=0; iy<ny; iy++) {
|
||||
xField[ix][iy].resize(nz);
|
||||
yField[ix][iy].resize(nz);
|
||||
zField[ix][iy].resize(nz);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Ignore header information. All lines whose first character
|
||||
// is '%' are considered to be part of the header.
|
||||
do {
|
||||
file.ignore(256, '\n');
|
||||
} while (file.peek() == '%');
|
||||
|
||||
/// NOTE: The old version works only ONCE, i.e. at a STOP signal, e.g. !
|
||||
//do {
|
||||
// file.getline(buffer, 256, '!');
|
||||
//} while (buffer[0] != '!');
|
||||
|
||||
|
||||
// Read in the data: [x, y, z, EMx, EMy, EMz] or [EMx, EMy, EMz]
|
||||
double xval, yval, zval; // Coordinates
|
||||
double fx, fy, fz; // Field values
|
||||
//std::ofstream fileout("three_columns.txt"); // Useful for rewriting files
|
||||
|
||||
for (ix=0; ix<nx; ix++) { // notice the order!
|
||||
for (iy=0; iy<ny; iy++) {
|
||||
for (iz=0; iz<nz; iz++) {
|
||||
|
||||
if (n_arg == 5) { // Read BOTH coordinates and field values
|
||||
file >> xval >> yval >> zval >> fx >> fy >> fz;
|
||||
//fileout << fx <<" \t"<< fy << " \t"<< fz << std::endl; // for rewriting files
|
||||
if ( ix==0 && iy==0 && iz==0 ) {
|
||||
minimumx = xval * lenUnit;
|
||||
minimumy = yval * lenUnit;
|
||||
minimumz = zval * lenUnit;
|
||||
}
|
||||
}
|
||||
else if (n_arg == 11) {
|
||||
file >> fx >> fy >> fz; // Read ONLY field values
|
||||
}
|
||||
|
||||
xField[ix][iy][iz] = fx*fieldNormalisation;
|
||||
yField[ix][iy][iz] = fy*fieldNormalisation;
|
||||
zField[ix][iy][iz] = fz*fieldNormalisation;
|
||||
}
|
||||
}
|
||||
}
|
||||
//fileout.close(); // for rewriting files
|
||||
file.close();
|
||||
|
||||
if (n_arg == 5) {
|
||||
maximumx = xval * lenUnit;
|
||||
maximumy = yval * lenUnit;
|
||||
maximumz = zval * lenUnit;
|
||||
}
|
||||
else if (n_arg == 11) {
|
||||
minimumx = minimumx * lenUnit;
|
||||
minimumy = minimumy * lenUnit;
|
||||
minimumz = minimumz * lenUnit;
|
||||
maximumx = maximumx * lenUnit;
|
||||
maximumy = maximumy * lenUnit;
|
||||
maximumz = maximumz * lenUnit;
|
||||
}
|
||||
|
||||
|
||||
G4String volumeName = logVolume->GetName().substr(4);
|
||||
|
||||
G4cout << " ... done reading " << G4endl;
|
||||
G4cout << "\n ---> " << fldType << "-field in volume "<< volumeName
|
||||
<< " set to: " << fieldValue/fieUnit << " " << fUnit << G4endl;
|
||||
if (n_arg == 5) { G4cout << "\n ---> Assumed order (6 col.): x, y, z, ";}
|
||||
else if (n_arg == 11) { G4cout << "\n ---> Assumed order (3 col.): ";}
|
||||
G4cout << fldType <<"x, "<< fldType <<"y, "<< fldType <<"z "
|
||||
<< "\n Min values x, y, z: "
|
||||
<< minimumx/cm << " " << minimumy/cm << " " << minimumz/cm << " cm "
|
||||
<< "\n Max values x, y, z: "
|
||||
<< maximumx/cm << " " << maximumy/cm << " " << maximumz/cm << " cm" << G4endl;
|
||||
|
||||
// Should really check that the limits are not the wrong way around.
|
||||
if (maximumx < minimumx) {Invert("x");}
|
||||
if (maximumy < minimumy) {Invert("y");}
|
||||
if (maximumz < minimumz) {Invert("z");}
|
||||
|
||||
if ((maximumx < minimumx) || (maximumy < minimumy)|| (maximumz < minimumz)) {
|
||||
G4cout << "\n ---> After reordering:"
|
||||
<< "\n Min values x, y, z: "
|
||||
<< minimumx/cm << " " << minimumy/cm << " " << minimumz/cm << " cm "
|
||||
<< "\n Max values x, y, z: "
|
||||
<< maximumx/cm << " " << maximumy/cm << " " << maximumz/cm << " cm " << G4endl;
|
||||
}
|
||||
|
||||
dx = maximumx - minimumx;
|
||||
dy = maximumy - minimumy;
|
||||
dz = maximumz - minimumz;
|
||||
|
||||
G4cout << " Range of values: "
|
||||
<< dx/cm << " cm (in x), " << dy/cm << " cm (in y) and " << dz/cm << " cm (in z)."
|
||||
<< "\n-----------------------------------------------------------\n" << G4endl;
|
||||
|
||||
}
|
||||
|
||||
void lem4TabulatedElementField3D::addFieldValue(const G4double point[4],
|
||||
G4double *field ) const
|
||||
{
|
||||
G4double EMf[3]; // EM field value obtained from the field map
|
||||
|
||||
G4ThreeVector global(point[0],point[1],point[2]);
|
||||
G4ThreeVector local;
|
||||
|
||||
local = global2local.TransformPoint(global);
|
||||
|
||||
double x = local.x();
|
||||
double y = local.y();
|
||||
double z = local.z();
|
||||
|
||||
// G4cout<<"Global points= "<<point[0]<<", "<<point[1]<<", "<<point[2]<<", Local point= "<<x<<", "<<y<<", "<<z<<G4endl;
|
||||
|
||||
|
||||
// Check that the point is within the defined region
|
||||
if ( x>minimumx && x<maximumx &&
|
||||
y>minimumy && y<maximumy &&
|
||||
z>minimumz && z<maximumz ) {
|
||||
|
||||
// Position of given point within region, normalized to the range
|
||||
// [0,1]
|
||||
double xfraction = (x - minimumx) / dx;
|
||||
double yfraction = (y - minimumy) / dy;
|
||||
double zfraction = (z - minimumz) / dz;
|
||||
|
||||
// Need addresses of these to pass to modf below.
|
||||
// modf uses its second argument as an OUTPUT argument.
|
||||
double xdindex, ydindex, zdindex;
|
||||
|
||||
// Position of the point within the cuboid defined by the
|
||||
// nearest surrounding tabulated points
|
||||
double xlocal = ( modf(xfraction*(nx-1), &xdindex));
|
||||
double ylocal = ( modf(yfraction*(ny-1), &ydindex));
|
||||
double zlocal = ( modf(zfraction*(nz-1), &zdindex));
|
||||
|
||||
// The indices of the nearest tabulated point whose coordinates
|
||||
// are all less than those of the given point
|
||||
int xindex = static_cast<int>(xdindex);
|
||||
int yindex = static_cast<int>(ydindex);
|
||||
int zindex = static_cast<int>(zdindex);
|
||||
|
||||
//cks The following check is necessary - even though xindex and zindex should never be out of range,
|
||||
// it may happen (due to some rounding error ?). It is better to leave the check here.
|
||||
if ((xindex<0)||(xindex>(nx-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: xindex out of range! xindex="<<xindex<<" x="<<x<<" xfraction="<<xfraction<<std::endl;
|
||||
if (xindex<0) xindex=0;
|
||||
else xindex=nx-2;
|
||||
}
|
||||
if ((yindex<0)||(yindex>(ny-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: yindex out of range! yindex="<<yindex<<" y="<<y<<" yfraction="<<yfraction<<std::endl;
|
||||
if (yindex<0) yindex=0;
|
||||
else yindex=ny-2;
|
||||
}
|
||||
if ((zindex<0)||(zindex>(nz-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: zindex out of range! zindex="<<zindex<<" z="<<z<<" zfraction="<<zfraction<<std::endl;
|
||||
if (zindex<0) zindex=0;
|
||||
else zindex=nz-2;
|
||||
}
|
||||
|
||||
// Full 3-dimensional version
|
||||
EMf[0] =
|
||||
xField[xindex ][yindex ][zindex ] * (1-xlocal) * (1-ylocal) * (1-zlocal) +
|
||||
xField[xindex ][yindex ][zindex+1] * (1-xlocal) * (1-ylocal) * zlocal +
|
||||
xField[xindex ][yindex+1][zindex ] * (1-xlocal) * ylocal * (1-zlocal) +
|
||||
xField[xindex ][yindex+1][zindex+1] * (1-xlocal) * ylocal * zlocal +
|
||||
xField[xindex+1][yindex ][zindex ] * xlocal * (1-ylocal) * (1-zlocal) +
|
||||
xField[xindex+1][yindex ][zindex+1] * xlocal * (1-ylocal) * zlocal +
|
||||
xField[xindex+1][yindex+1][zindex ] * xlocal * ylocal * (1-zlocal) +
|
||||
xField[xindex+1][yindex+1][zindex+1] * xlocal * ylocal * zlocal ;
|
||||
EMf[1] =
|
||||
yField[xindex ][yindex ][zindex ] * (1-xlocal) * (1-ylocal) * (1-zlocal) +
|
||||
yField[xindex ][yindex ][zindex+1] * (1-xlocal) * (1-ylocal) * zlocal +
|
||||
yField[xindex ][yindex+1][zindex ] * (1-xlocal) * ylocal * (1-zlocal) +
|
||||
yField[xindex ][yindex+1][zindex+1] * (1-xlocal) * ylocal * zlocal +
|
||||
yField[xindex+1][yindex ][zindex ] * xlocal * (1-ylocal) * (1-zlocal) +
|
||||
yField[xindex+1][yindex ][zindex+1] * xlocal * (1-ylocal) * zlocal +
|
||||
yField[xindex+1][yindex+1][zindex ] * xlocal * ylocal * (1-zlocal) +
|
||||
yField[xindex+1][yindex+1][zindex+1] * xlocal * ylocal * zlocal ;
|
||||
EMf[2] =
|
||||
zField[xindex ][yindex ][zindex ] * (1-xlocal) * (1-ylocal) * (1-zlocal) +
|
||||
zField[xindex ][yindex ][zindex+1] * (1-xlocal) * (1-ylocal) * zlocal +
|
||||
zField[xindex ][yindex+1][zindex ] * (1-xlocal) * ylocal * (1-zlocal) +
|
||||
zField[xindex ][yindex+1][zindex+1] * (1-xlocal) * ylocal * zlocal +
|
||||
zField[xindex+1][yindex ][zindex ] * xlocal * (1-ylocal) * (1-zlocal) +
|
||||
zField[xindex+1][yindex ][zindex+1] * xlocal * (1-ylocal) * zlocal +
|
||||
zField[xindex+1][yindex+1][zindex ] * xlocal * ylocal * (1-zlocal) +
|
||||
zField[xindex+1][yindex+1][zindex+1] * xlocal * ylocal * zlocal ;
|
||||
|
||||
EMf[0] *= ffieldValue;
|
||||
EMf[1] *= ffieldValue;
|
||||
EMf[2] *= ffieldValue;
|
||||
|
||||
G4ThreeVector finalField(EMf[0],EMf[1],EMf[2]);
|
||||
finalField = global2local.Inverse().TransformAxis(finalField);
|
||||
|
||||
if (fldType == 'B') {
|
||||
field[0] += finalField.x();
|
||||
field[1] += finalField.y();
|
||||
field[2] += finalField.z();
|
||||
}
|
||||
else if (fldType == 'E') {
|
||||
field[3] += finalField.x();
|
||||
field[4] += finalField.y();
|
||||
field[5] += finalField.z();
|
||||
}
|
||||
|
||||
}
|
||||
// G4cout<<"Kamil: Field: ("<<field[0]/tesla<<","<<field[1]/tesla<<","<<field[2]/tesla<<")"<<G4endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
G4double lem4TabulatedElementField3D::GetNominalFieldValue() {
|
||||
return ffieldValue;
|
||||
}
|
||||
|
||||
void lem4TabulatedElementField3D::SetNominalFieldValue(G4double newFieldValue) {
|
||||
// // Rescale the magnetic field for a new value of the magnetic field
|
||||
ffieldValue=newFieldValue;
|
||||
G4cout<<"lem4TabulatedElementField3D.cc: ffieldValue changed to="<< ffieldValue/fieUnit << fUnit << G4endl;
|
||||
}
|
||||
|
||||
void lem4TabulatedElementField3D::Invert(const char* indexToInvert) {
|
||||
// This function inverts the indices of the field table for a given axis (x or z).
|
||||
// It should be called in the case when the x or z coordinate in the initial
|
||||
// field table is ordered in the decreasing order.
|
||||
std::vector< std::vector< std::vector< double > > > xFieldTemp(xField);
|
||||
std::vector< std::vector< std::vector< double > > > yFieldTemp(yField);
|
||||
std::vector< std::vector< std::vector< double > > > zFieldTemp(zField);
|
||||
G4bool invertX=false;
|
||||
G4bool invertY=false;
|
||||
G4bool invertZ=false;
|
||||
|
||||
G4cout<<"Check that the lem4TabulatedElementField3D::Invert() function works properly!"<<G4endl;
|
||||
G4cout<<"It has not been tested yet!"<<G4endl;
|
||||
|
||||
if (strcmp(indexToInvert,"x")==0) {invertX=true; std::swap(maximumx,minimumx);}
|
||||
if (strcmp(indexToInvert,"y")==0) {invertY=true; std::swap(maximumx,minimumx);}
|
||||
if (strcmp(indexToInvert,"z")==0) {invertZ=true; std::swap(maximumz,minimumz);}
|
||||
|
||||
for (int ix=0; ix<nx; ix++) {
|
||||
for (int iy=0; iy<ny; iy++) {
|
||||
for (int iz=0; iz<nz; iz++) {
|
||||
if (invertX) {
|
||||
xField[ix][iy][iz] = xFieldTemp[nx-1-ix][iy][iz];
|
||||
yField[ix][iy][iz] = yFieldTemp[nx-1-ix][iy][iz];
|
||||
zField[ix][iy][iz] = zFieldTemp[nx-1-ix][iy][iz];
|
||||
}
|
||||
else if(invertY) {
|
||||
xField[ix][iy][iz] = xFieldTemp[ix][ny-1-iy][iz];
|
||||
yField[ix][iy][iz] = yFieldTemp[ix][ny-1-iy][iz];
|
||||
zField[ix][iy][iz] = zFieldTemp[ix][ny-1-iy][iz];
|
||||
}
|
||||
else if(invertZ) {
|
||||
xField[ix][iy][iz] = xFieldTemp[ix][iy][nz-1-iz];
|
||||
yField[ix][iy][iz] = yFieldTemp[ix][iy][nz-1-iz];
|
||||
zField[ix][iy][iz] = zFieldTemp[ix][iy][nz-1-iz];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
229
geant4/LEMuSR/src/lem4TabulatedField2D.cc
Normal file
229
geant4/LEMuSR/src/lem4TabulatedField2D.cc
Normal file
@ -0,0 +1,229 @@
|
||||
#include "lem4TabulatedField2D.hh"
|
||||
//#include "lem4EventAction.hh" // cks: just to get the event nr. if needed.
|
||||
#include "lem4Parameters.hh"
|
||||
|
||||
|
||||
lem4TabulatedField2D* lem4TabulatedField2D::pointerToTabulatedField2D=NULL;
|
||||
lem4TabulatedField2D* lem4TabulatedField2D::GetInstance() {
|
||||
return pointerToTabulatedField2D;
|
||||
}
|
||||
|
||||
lem4TabulatedField2D::lem4TabulatedField2D( const char* filename, double fieldValue, double lenUnit, double fieldNormalisation )
|
||||
:ffieldValue(fieldValue),invertX(false),invertZ(false)
|
||||
{
|
||||
pointerToTabulatedField2D=this;
|
||||
G4cout << "pointerToTabulatedField2D="<<pointerToTabulatedField2D<<G4endl;
|
||||
// double lenUnit= meter;
|
||||
// double fieldUnit= tesla;
|
||||
G4cout << "\n-----------------------------------------------------------"
|
||||
<< "\n Magnetic field"
|
||||
<< "\n-----------------------------------------------------------"
|
||||
<< G4endl;
|
||||
G4cout << " tesla="<<tesla<<G4endl;
|
||||
G4cout << " Field set to "<< fieldValue/tesla << " T"<< G4endl;
|
||||
G4cout << "\n ---> " "Reading the field grid from " << filename << " ... " << G4endl;
|
||||
positionOffset[0]=0;
|
||||
positionOffset[1]=0;
|
||||
positionOffset[2]=0;
|
||||
positionOffset[3]=0;
|
||||
std::ifstream file( filename ); // Open the file for reading.
|
||||
|
||||
// Ignore first blank line
|
||||
char buffer[256];
|
||||
// file.getline(buffer,256);
|
||||
|
||||
// Read table dimensions
|
||||
int nDummy;
|
||||
file >> nx >> nDummy >> nz; // Note dodgy order
|
||||
|
||||
G4cout << " [ Number of values x,z: "
|
||||
<< nx << " " << nz << " ] "
|
||||
<< G4endl;
|
||||
|
||||
// Set up storage space for table
|
||||
xField.resize( nx );
|
||||
zField.resize( nx );
|
||||
int ix, iz;
|
||||
for (ix=0; ix<nx; ix++) {
|
||||
xField[ix].resize(nz);
|
||||
zField[ix].resize(nz);
|
||||
}
|
||||
|
||||
// Ignore other header information
|
||||
// The first line whose second character is '0' is considered to
|
||||
// be the last line of the header.
|
||||
do {
|
||||
file.getline(buffer,256);
|
||||
} while ( buffer[1]!='0');
|
||||
|
||||
// Read in the data
|
||||
double xval,yval,zval,bx,bz;
|
||||
double permeability; // Not used in this example.
|
||||
for (ix=0; ix<nx; ix++) {
|
||||
for (iz=0; iz<nz; iz++) {
|
||||
file >> xval >> yval >> zval >> bx >> bz >> permeability;
|
||||
if ( ix==0 && iz==0 ) {
|
||||
minx = xval * lenUnit;
|
||||
minz = zval * lenUnit;
|
||||
}
|
||||
//xField[ix][iy][iz] = bx * fieldUnit * fieldValue;
|
||||
//zField[ix][iy][iz] = bz * fieldUnit * fieldValue;
|
||||
// xField[ix][iy][iz] = bx * fieldValue;
|
||||
// zField[ix][iy][iz] = bz * fieldValue;
|
||||
xField[ix][iz] = bx*fieldNormalisation;
|
||||
zField[ix][iz] = bz*fieldNormalisation;
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
|
||||
maxx = xval * lenUnit;
|
||||
maxz = zval * lenUnit;
|
||||
|
||||
G4cout << "\n ---> ... done reading " << G4endl;
|
||||
|
||||
// G4cout << " Read values of field from file " << filename << G4endl;
|
||||
G4cout << " ---> assumed the order: x, y, z, Bx, Bz "
|
||||
<< "\n ---> Min values x,y,z: "
|
||||
<< minx/cm << " " << minz/cm << " cm "
|
||||
<< "\n ---> Max values x,y,z: "
|
||||
<< maxx/cm << " " << maxz/cm << " cm " << G4endl;
|
||||
|
||||
|
||||
// Should really check that the limits are not the wrong way around.
|
||||
if (maxx < minx) {std::swap(maxx,minx); invertX = true;}
|
||||
if (maxz < minz) {std::swap(maxz,minz); invertZ = true;}
|
||||
G4cout << "\nAfter reordering if neccesary"
|
||||
<< "\n ---> Min values x,y,z: "
|
||||
<< minx/cm << " " << minz/cm << " cm "
|
||||
<< " \n ---> Max values x,y,z: "
|
||||
<< maxx/cm << " " << maxz/cm << " cm ";
|
||||
|
||||
dx = maxx - minx;
|
||||
dz = maxz - minz;
|
||||
G4cout << "\n ---> Dif values x,z (range): "
|
||||
<< dx/cm << " " << dz/cm << " cm in z "
|
||||
<< "\n-----------------------------------------------------------" << G4endl;
|
||||
}
|
||||
|
||||
void lem4TabulatedField2D::GetFieldValue(const double point[4],
|
||||
double *Bfield ) const
|
||||
{
|
||||
// G4cout<<"Tabulated: Field requested at point ("<<point[0]<<","<<point[1]<<","<<point[2]<<")"<<G4endl;
|
||||
// lem4EventAction* myEventAction= lem4EventAction::GetInstance();
|
||||
// G4int evNr=myEventAction->GetLatestEventNr();
|
||||
// G4int evNrKriz=6795; //457; //14250
|
||||
// if (evNr==evNrKriz) {
|
||||
// std::cout<<"evNr="<<evNr<<std::endl;
|
||||
// printf ("for point= %f %f %f B= %10.10f %10.10f %10.10f \n",
|
||||
// point[0],point[1],point[2],Bfield[0]/tesla,Bfield[1]/tesla,Bfield[2]/tesla);
|
||||
// }
|
||||
Bfield[0]=0.; Bfield[1]=0.; Bfield[2]=0.;
|
||||
|
||||
double pppoint[4];
|
||||
pppoint[0]=point[0]+positionOffset[0];
|
||||
pppoint[1]=point[1]+positionOffset[1];
|
||||
pppoint[2]=point[2]+positionOffset[2];
|
||||
pppoint[3]=point[3]+positionOffset[3];
|
||||
double x = sqrt(pppoint[0]*pppoint[0]+pppoint[1]*pppoint[1]);
|
||||
double z = fabs(pppoint[2]);
|
||||
double z_sign = (pppoint[2]>0) ? 1.:-1.;
|
||||
//if (evNr==evNrKriz) std::cout<<"x ="<<x<<" maxx="<<maxx<<std::endl;
|
||||
|
||||
// Check that the point is within the defined region
|
||||
if ( x<maxx && z<maxz ) {
|
||||
// if (evNr>evNrKriz) std::cout<<"bol som tu"<<std::endl;
|
||||
|
||||
// Position of given point within region, normalized to the range
|
||||
// [0,1]
|
||||
double xfraction = (x - minx) / dx;
|
||||
double zfraction = (z - minz) / dz;
|
||||
|
||||
if (invertX) { xfraction = 1 - xfraction;}
|
||||
if (invertZ) { zfraction = 1 - zfraction;}
|
||||
// Need addresses of these to pass to modf below.
|
||||
// modf uses its second argument as an OUTPUT argument.
|
||||
double xdindex, zdindex;
|
||||
|
||||
// Position of the point within the cuboid defined by the
|
||||
// nearest surrounding tabulated points
|
||||
double xlocal = ( modf(xfraction*(nx-1), &xdindex));
|
||||
double zlocal = ( modf(zfraction*(nz-1), &zdindex));
|
||||
|
||||
// The indices of the nearest tabulated point whose coordinates
|
||||
// are all less than those of the given point
|
||||
int xindex = static_cast<int>(xdindex);
|
||||
int zindex = static_cast<int>(zdindex);
|
||||
|
||||
//cks The following check is necessary - even though xindex and zindex should never be out of range,
|
||||
// it may happen (due to some rounding error ?). It is better to leave the check here.
|
||||
if ((xindex<0)||(xindex>(nx-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: xindex out of range! xindex="<<xindex<<" x="<<x<<" xfraction="<<xfraction<<std::endl;
|
||||
if (xindex<0) xindex=0;
|
||||
else xindex=nx-2;
|
||||
}
|
||||
if ((zindex<0)||(zindex>(nz-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: zindex out of range! zindex="<<zindex<<" z="<<z<<" zfraction="<<zfraction<<std::endl;
|
||||
if (zindex<0) zindex=0;
|
||||
else zindex=nz-2;
|
||||
}
|
||||
|
||||
// Find out whether the muon is decaying. If yes, calculate the field in
|
||||
// more detail (more precisely).
|
||||
// The following commented piece of code was not reliable (was indicating the
|
||||
// proccess "DecayWithSpin" even if there was none).
|
||||
// G4String processName = G4RunManagerKernel::GetRunManagerKernel()->
|
||||
// // G4String processName = G4EventManager::GetEventManager()->
|
||||
// GetTrackingManager()->GetTrack()->GetStep()->
|
||||
// GetPostStepPoint()->GetProcessDefinedStep()->
|
||||
// GetProcessName();
|
||||
// The following seems to be OK:
|
||||
// if (lem4Parameters::field_DecayWithSpin) {
|
||||
// lem4Parameters::field_DecayWithSpin=false;
|
||||
//
|
||||
// }
|
||||
// else { // Muon is not decaying, use a fast method of interpolation.
|
||||
// Interpolate between the neighbouring points
|
||||
double Bfield_R =
|
||||
xField[xindex ][zindex ] * (1-xlocal) * (1-zlocal) +
|
||||
xField[xindex ][zindex+1] * (1-xlocal) * zlocal +
|
||||
xField[xindex+1][zindex ] * xlocal * (1-zlocal) +
|
||||
xField[xindex+1][zindex+1] * xlocal * zlocal ;
|
||||
Bfield[0] = (x>0) ? Bfield_R * (pppoint[0]/x) : 0.;
|
||||
Bfield[1] = (x>0) ? Bfield_R * (pppoint[1]/x) : 0.;
|
||||
Bfield[2] =
|
||||
zField[xindex ][zindex ] * (1-xlocal) * (1-zlocal) +
|
||||
zField[xindex ][zindex+1] * (1-xlocal) * zlocal +
|
||||
zField[xindex+1][zindex ] * xlocal * (1-zlocal) +
|
||||
zField[xindex+1][zindex+1] * xlocal * zlocal ;
|
||||
|
||||
Bfield[0] = Bfield[0] * ffieldValue * z_sign;
|
||||
Bfield[1] = Bfield[1] * ffieldValue * z_sign;
|
||||
Bfield[2] = Bfield[2] * ffieldValue;
|
||||
// }
|
||||
}
|
||||
|
||||
// Set some small field if field is almost zero (to avoid internal problems of Geant).
|
||||
if (sqrt(Bfield[0]*Bfield[0]+Bfield[1]*Bfield[1]+Bfield[2]*Bfield[2])<0.00001*tesla) {
|
||||
// if (evNr>evNrKriz) std::cout<<"bol som tuna"<<std::endl;
|
||||
// Bfield[0] = 0.0;
|
||||
// Bfield[1] = 0.0;
|
||||
// Bfield[2] = Bfield[2] + 0.00001*tesla;
|
||||
Bfield[2] = 0.00001*tesla;
|
||||
}
|
||||
// Print the field (for debugging)
|
||||
// if ((point[2]>-0.1*mm)&&(point[2]<0.1*mm)) {
|
||||
// printf ("for point= %f %f %f B= %10.10f %10.10f %10.10f \n",
|
||||
// point[0],point[1],point[2],Bfield[0]/tesla,Bfield[1]/tesla,Bfield[2]/tesla);
|
||||
// }
|
||||
// if (evNr>evNrKriz) std::cout<<"this is the end"<<std::endl;
|
||||
}
|
||||
|
||||
G4double lem4TabulatedField2D::GetFieldSetValue() {
|
||||
return ffieldValue;
|
||||
}
|
||||
|
||||
void lem4TabulatedField2D::SetFieldValue(double newFieldValue) {
|
||||
// // Rescale the magnetic field for a new value of the magnetic field
|
||||
ffieldValue=newFieldValue;
|
||||
G4cout<<"lem4TabulatedField2D.cc: ffieldValue changed to="<< ffieldValue/tesla<<"T "<<G4endl;
|
||||
}
|
251
geant4/LEMuSR/src/lem4TabulatedField3D.cc
Normal file
251
geant4/LEMuSR/src/lem4TabulatedField3D.cc
Normal file
@ -0,0 +1,251 @@
|
||||
#include "lem4TabulatedField3D.hh"
|
||||
|
||||
|
||||
lem4TabulatedField3D* lem4TabulatedField3D::pointerToTabulatedField3D=NULL;
|
||||
lem4TabulatedField3D* lem4TabulatedField3D::GetInstance() {
|
||||
return pointerToTabulatedField3D;
|
||||
}
|
||||
|
||||
|
||||
lem4TabulatedField3D::lem4TabulatedField3D( const char* filename, double fieldValue )
|
||||
:ffieldValue(fieldValue),invertX(false),invertY(false),invertZ(false)
|
||||
{
|
||||
pointerToTabulatedField3D=this;
|
||||
double lenUnit= meter;
|
||||
// double fieldUnit= tesla;
|
||||
G4cout << "\n-----------------------------------------------------------"
|
||||
<< "\n Magnetic field"
|
||||
<< "\n-----------------------------------------------------------"
|
||||
<< endl;
|
||||
G4cout << " tesla="<<tesla<<G4endl;
|
||||
G4cout << " Field set to "<< fieldValue/tesla << " T"<< G4endl;
|
||||
G4cout << "\n ---> " "Reading the field grid from " << filename << " ... " << G4endl;
|
||||
ifstream file( filename ); // Open the file for reading.
|
||||
|
||||
// Ignore first blank line
|
||||
char buffer[256];
|
||||
file.getline(buffer,256);
|
||||
|
||||
// Read table dimensions
|
||||
file >> nx >> ny >> nz; // Note dodgy order
|
||||
|
||||
G4cout << " [ Number of values x,y,z: "
|
||||
<< nx << " " << ny << " " << nz << " ] "
|
||||
<< endl;
|
||||
|
||||
// Set up storage space for table
|
||||
xField.resize( nx );
|
||||
yField.resize( nx );
|
||||
zField.resize( nx );
|
||||
int ix, iy, iz;
|
||||
for (ix=0; ix<nx; ix++) {
|
||||
xField[ix].resize(ny);
|
||||
yField[ix].resize(ny);
|
||||
zField[ix].resize(ny);
|
||||
for (iy=0; iy<ny; iy++) {
|
||||
xField[ix][iy].resize(nz);
|
||||
yField[ix][iy].resize(nz);
|
||||
zField[ix][iy].resize(nz);
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore other header information
|
||||
// The first line whose second character is '0' is considered to
|
||||
// be the last line of the header.
|
||||
do {
|
||||
file.getline(buffer,256);
|
||||
} while ( buffer[1]!='0');
|
||||
|
||||
// Read in the data
|
||||
double xval,yval,zval,bx,by,bz;
|
||||
double permeability; // Not used in this example.
|
||||
for (ix=0; ix<nx; ix++) {
|
||||
for (iy=0; iy<ny; iy++) {
|
||||
for (iz=0; iz<nz; iz++) {
|
||||
file >> xval >> yval >> zval >> bx >> by >> bz >> permeability;
|
||||
if ( ix==0 && iy==0 && iz==0 ) {
|
||||
minx = xval * lenUnit;
|
||||
miny = yval * lenUnit;
|
||||
minz = zval * lenUnit;
|
||||
}
|
||||
//xField[ix][iy][iz] = bx * fieldUnit * fieldValue;
|
||||
//yField[ix][iy][iz] = by * fieldUnit * fieldValue;
|
||||
//zField[ix][iy][iz] = bz * fieldUnit * fieldValue;
|
||||
// xField[ix][iy][iz] = bx * fieldValue;
|
||||
// yField[ix][iy][iz] = by * fieldValue;
|
||||
// zField[ix][iy][iz] = bz * fieldValue;
|
||||
xField[ix][iy][iz] = bx;
|
||||
yField[ix][iy][iz] = by;
|
||||
zField[ix][iy][iz] = bz;
|
||||
}
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
|
||||
maxx = xval * lenUnit;
|
||||
maxy = yval * lenUnit;
|
||||
maxz = zval * lenUnit;
|
||||
|
||||
G4cout << "\n ---> ... done reading " << endl;
|
||||
|
||||
// G4cout << " Read values of field from file " << filename << endl;
|
||||
G4cout << " ---> assumed the order: x, y, z, Bx, By, Bz "
|
||||
<< "\n ---> Min values x,y,z: "
|
||||
<< minx/cm << " " << miny/cm << " " << minz/cm << " cm "
|
||||
<< "\n ---> Max values x,y,z: "
|
||||
<< maxx/cm << " " << maxy/cm << " " << maxz/cm << " cm " << endl;
|
||||
|
||||
|
||||
// Should really check that the limits are not the wrong way around.
|
||||
if (maxx < minx) {swap(maxx,minx); invertX = true;}
|
||||
if (maxy < miny) {swap(maxy,miny); invertY = true;}
|
||||
if (maxz < minz) {swap(maxz,minz); invertZ = true;}
|
||||
G4cout << "\nAfter reordering if neccesary"
|
||||
<< "\n ---> Min values x,y,z: "
|
||||
<< minx/cm << " " << miny/cm << " " << minz/cm << " cm "
|
||||
<< " \n ---> Max values x,y,z: "
|
||||
<< maxx/cm << " " << maxy/cm << " " << maxz/cm << " cm ";
|
||||
|
||||
dx = maxx - minx;
|
||||
dy = maxy - miny;
|
||||
dz = maxz - minz;
|
||||
G4cout << "\n ---> Dif values x,y,z (range): "
|
||||
<< dx/cm << " " << dy/cm << " " << dz/cm << " cm in z "
|
||||
<< "\n-----------------------------------------------------------" << endl;
|
||||
}
|
||||
|
||||
void lem4TabulatedField3D::GetFieldValue(const double point[4],
|
||||
double *Bfield ) const
|
||||
{
|
||||
Bfield[0]=0.; Bfield[1]=0.; Bfield[2]=0.;
|
||||
|
||||
double x = point[0]+positionOffset[0];
|
||||
double y = point[1]+positionOffset[1];
|
||||
double z = point[2]+positionOffset[2];
|
||||
|
||||
|
||||
// Check that the point is within the defined region
|
||||
if ( x>minx && x<maxx &&
|
||||
y>miny && y<maxy &&
|
||||
z>minz && z<maxz ) {
|
||||
|
||||
// Position of given point within region, normalized to the range
|
||||
// [0,1]
|
||||
double xfraction = (x - minx) / dx;
|
||||
double yfraction = (y - miny) / dy;
|
||||
double zfraction = (z - minz) / dz;
|
||||
|
||||
if (invertX) { xfraction = 1 - xfraction;}
|
||||
if (invertY) { yfraction = 1 - yfraction;}
|
||||
if (invertZ) { zfraction = 1 - zfraction;}
|
||||
|
||||
// Need addresses of these to pass to modf below.
|
||||
// modf uses its second argument as an OUTPUT argument.
|
||||
double xdindex, ydindex, zdindex;
|
||||
|
||||
// Position of the point within the cuboid defined by the
|
||||
// nearest surrounding tabulated points
|
||||
double xlocal = ( modf(xfraction*(nx-1), &xdindex));
|
||||
double ylocal = ( modf(yfraction*(ny-1), &ydindex));
|
||||
double zlocal = ( modf(zfraction*(nz-1), &zdindex));
|
||||
|
||||
// The indices of the nearest tabulated point whose coordinates
|
||||
// are all less than those of the given point
|
||||
int xindex = static_cast<int>(xdindex);
|
||||
int yindex = static_cast<int>(ydindex);
|
||||
int zindex = static_cast<int>(zdindex);
|
||||
|
||||
//cks The following check is necessary - even though xindex and zindex should never be out of range,
|
||||
// it may happen (due to some rounding error ?). It is better to leave the check here.
|
||||
if ((xindex<0)||(xindex>(nx-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: xindex out of range! xindex="<<xindex<<" x="<<x<<" xfraction="<<xfraction<<std::endl;
|
||||
if (xindex<0) xindex=0;
|
||||
else xindex=nx-2;
|
||||
}
|
||||
if ((yindex<0)||(yindex>(ny-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: yindex out of range! yindex="<<yindex<<" y="<<y<<" yfraction="<<yfraction<<std::endl;
|
||||
if (yindex<0) yindex=0;
|
||||
else yindex=ny-2;
|
||||
}
|
||||
if ((zindex<0)||(zindex>(nz-2))) {
|
||||
std::cout<<"SERIOUS PROBLEM: zindex out of range! zindex="<<zindex<<" z="<<z<<" zfraction="<<zfraction<<std::endl;
|
||||
if (zindex<0) zindex=0;
|
||||
else zindex=nz-2;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_INTERPOLATING_FIELD
|
||||
G4cout << "Local x,y,z: " << xlocal << " " << ylocal << " " << zlocal << endl;
|
||||
G4cout << "Index x,y,z: " << xindex << " " << yindex << " " << zindex << endl;
|
||||
double valx0z0, mulx0z0, valx1z0, mulx1z0;
|
||||
double valx0z1, mulx0z1, valx1z1, mulx1z1;
|
||||
valx0z0= table[xindex ][0][zindex]; mulx0z0= (1-xlocal) * (1-zlocal);
|
||||
valx1z0= table[xindex+1][0][zindex]; mulx1z0= xlocal * (1-zlocal);
|
||||
valx0z1= table[xindex ][0][zindex+1]; mulx0z1= (1-xlocal) * zlocal;
|
||||
valx1z1= table[xindex+1][0][zindex+1]; mulx1z1= xlocal * zlocal;
|
||||
#endif
|
||||
|
||||
// Full 3-dimensional version
|
||||
Bfield[0] =
|
||||
xField[xindex ][yindex ][zindex ] * (1-xlocal) * (1-ylocal) * (1-zlocal) +
|
||||
xField[xindex ][yindex ][zindex+1] * (1-xlocal) * (1-ylocal) * zlocal +
|
||||
xField[xindex ][yindex+1][zindex ] * (1-xlocal) * ylocal * (1-zlocal) +
|
||||
xField[xindex ][yindex+1][zindex+1] * (1-xlocal) * ylocal * zlocal +
|
||||
xField[xindex+1][yindex ][zindex ] * xlocal * (1-ylocal) * (1-zlocal) +
|
||||
xField[xindex+1][yindex ][zindex+1] * xlocal * (1-ylocal) * zlocal +
|
||||
xField[xindex+1][yindex+1][zindex ] * xlocal * ylocal * (1-zlocal) +
|
||||
xField[xindex+1][yindex+1][zindex+1] * xlocal * ylocal * zlocal ;
|
||||
Bfield[1] =
|
||||
yField[xindex ][yindex ][zindex ] * (1-xlocal) * (1-ylocal) * (1-zlocal) +
|
||||
yField[xindex ][yindex ][zindex+1] * (1-xlocal) * (1-ylocal) * zlocal +
|
||||
yField[xindex ][yindex+1][zindex ] * (1-xlocal) * ylocal * (1-zlocal) +
|
||||
yField[xindex ][yindex+1][zindex+1] * (1-xlocal) * ylocal * zlocal +
|
||||
yField[xindex+1][yindex ][zindex ] * xlocal * (1-ylocal) * (1-zlocal) +
|
||||
yField[xindex+1][yindex ][zindex+1] * xlocal * (1-ylocal) * zlocal +
|
||||
yField[xindex+1][yindex+1][zindex ] * xlocal * ylocal * (1-zlocal) +
|
||||
yField[xindex+1][yindex+1][zindex+1] * xlocal * ylocal * zlocal ;
|
||||
Bfield[2] =
|
||||
zField[xindex ][yindex ][zindex ] * (1-xlocal) * (1-ylocal) * (1-zlocal) +
|
||||
zField[xindex ][yindex ][zindex+1] * (1-xlocal) * (1-ylocal) * zlocal +
|
||||
zField[xindex ][yindex+1][zindex ] * (1-xlocal) * ylocal * (1-zlocal) +
|
||||
zField[xindex ][yindex+1][zindex+1] * (1-xlocal) * ylocal * zlocal +
|
||||
zField[xindex+1][yindex ][zindex ] * xlocal * (1-ylocal) * (1-zlocal) +
|
||||
zField[xindex+1][yindex ][zindex+1] * xlocal * (1-ylocal) * zlocal +
|
||||
zField[xindex+1][yindex+1][zindex ] * xlocal * ylocal * (1-zlocal) +
|
||||
zField[xindex+1][yindex+1][zindex+1] * xlocal * ylocal * zlocal ;
|
||||
|
||||
Bfield[0] = Bfield[0] * ffieldValue;
|
||||
Bfield[1] = Bfield[1] * ffieldValue;
|
||||
Bfield[2] = Bfield[2] * ffieldValue;
|
||||
|
||||
}
|
||||
|
||||
if (sqrt(Bfield[0]*Bfield[0]+Bfield[1]*Bfield[1]+Bfield[2]*Bfield[2])<0.00001*tesla) {
|
||||
// Bfield[0] = 0.0;
|
||||
// Bfield[1] = 0.0;
|
||||
Bfield[2] = 0.00001*tesla;
|
||||
}
|
||||
// if ((point[2]>-1*cm)&&(point[2]<1*cm)) {
|
||||
// G4cout<<"Field at point ("<<point[0]<<","<<point[1]<<","<<point[2]<<","<<point[3]<<" = "
|
||||
// << Bfield[0]/tesla<<", "<<Bfield[1]/tesla<<", "<<Bfield[2]/tesla<<G4endl;
|
||||
// }
|
||||
}
|
||||
|
||||
G4double lem4TabulatedField3D::GetFieldSetValue() {
|
||||
return ffieldValue;
|
||||
}
|
||||
|
||||
void lem4TabulatedField3D::SetFieldValue(double newFieldValue) {
|
||||
// // Rescale the magnetic field for a new value of the magnetic field
|
||||
// G4double factor = newFieldValue/ffieldValue;
|
||||
// for (G4int ix=0; ix<nx; ix++) {
|
||||
// for (G4int iy=0; iy<ny; iy++) {
|
||||
// for (G4int iz=0; iz<nz; iz++) {
|
||||
// xField[ix][iy][iz] = xField[ix][iy][iz] * factor;
|
||||
// yField[ix][iy][iz] = yField[ix][iy][iz] * factor;
|
||||
// zField[ix][iy][iz] = zField[ix][iy][iz] * factor;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
ffieldValue=newFieldValue;
|
||||
G4cout<<"lem4TabulatedField3D.cc: ffieldValue changed to="<< ffieldValue/tesla<<"T "<<G4endl;
|
||||
}
|
101
geant4/LEMuSR/src/lem4UniformField.cc
Normal file
101
geant4/LEMuSR/src/lem4UniformField.cc
Normal file
@ -0,0 +1,101 @@
|
||||
#include "globals.hh"
|
||||
|
||||
#include "G4GeometryManager.hh"
|
||||
|
||||
//#include "F04GlobalField.hh"
|
||||
#include "lem4UniformField.hh"
|
||||
///#include "lem4Parameters.hh" ///Is this really needed. TS ???
|
||||
|
||||
|
||||
///lem4UniformField::lem4UniformField(G4ThreeVector (Bfieldx,Bfieldy,Bfieldz), G4LogicalVolume* lv, G4ThreeVector c)
|
||||
lem4UniformField::lem4UniformField(G4double EMF[6], G4LogicalVolume* lv, G4ThreeVector c)
|
||||
///lem4UniformField::lem4UniformField(G4double Bz, G4LogicalVolume* lv, G4ThreeVector c)
|
||||
: F04ElementField(c,lv) ///, EMfield(EMF) /// ??? Why Bz is not enough??
|
||||
{
|
||||
for (int i = 0; i < 6; i++){
|
||||
EMfield[i] = EMF[i];
|
||||
}
|
||||
|
||||
/// Bfield = Bz; ///G4ThreeVector finalField(B[0],B[1],B[2]); G4ThreeVector B(0.0,0.0,Bfield);
|
||||
///G4ThreeVector BField(Bfieldx,Bfieldy,Bfieldz);
|
||||
|
||||
fieldLength = 2.*((G4Box*)lvolume->GetSolid())->GetZHalfLength();
|
||||
fieldWidth = 2.*((G4Box*)lvolume->GetSolid())->GetXHalfLength();
|
||||
fieldHeight = 2.*((G4Box*)lvolume->GetSolid())->GetYHalfLength();
|
||||
|
||||
G4cout << "\n-----------------------------------------------------------"
|
||||
<< "\n Uniform electromagnetic field"
|
||||
<< "\n-----------------------------------------------------------"
|
||||
<< G4endl;
|
||||
|
||||
G4String volName = lv->GetName().substr(4);
|
||||
G4cout << "\n ---> EM field in volume " << volName << " set to:" << G4endl;
|
||||
printf (" B = (%0.3g, %0.3g, %0.3g) T, E = (%0.3g, %0.3g, %0.3g) kV/mm\n",
|
||||
EMF[0]/tesla, EMF[1]/tesla, EMF[2]/tesla,
|
||||
EMF[3]/(kilovolt/mm), EMF[4]/(kilovolt/mm), EMF[5]/(kilovolt/mm));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void lem4UniformField::addFieldValue(const G4double point[4],
|
||||
G4double field[6]) const
|
||||
{
|
||||
G4ThreeVector global(point[0],point[1],point[2]);
|
||||
G4ThreeVector local;
|
||||
|
||||
local = global2local.TransformPoint(global);
|
||||
|
||||
if (isOutside(local)) return;
|
||||
|
||||
G4ThreeVector B(EMfield[0],EMfield[1],EMfield[2]);
|
||||
G4ThreeVector E(EMfield[3],EMfield[4],EMfield[5]);
|
||||
|
||||
B = global2local.Inverse().TransformAxis(B);
|
||||
E = global2local.Inverse().TransformAxis(E);
|
||||
|
||||
field[0] += B[0];
|
||||
field[1] += B[1];
|
||||
field[2] += B[2];
|
||||
|
||||
field[3] += E[0];
|
||||
field[4] += E[1];
|
||||
field[5] += E[2];
|
||||
|
||||
//printf (" EM field components: B = (%0.3g, %0.3g, %0.3g) T, E = (%0.3g, %0.3g, %0.3g) kV/mm\n",
|
||||
//field[0]/tesla, field[1]/tesla, field[2]/tesla,
|
||||
//field[3]/(kilovolt/mm), field[4]/(kilovolt/mm), field[5]/(kilovolt/mm));
|
||||
}
|
||||
|
||||
|
||||
|
||||
G4double lem4UniformField::GetNominalFieldValue() {
|
||||
///G4double EMfield[6] = {0,0,0,0,0,0};
|
||||
///for (int i = 0; i < 6; i++){
|
||||
//return EMfield[i];
|
||||
return 0;
|
||||
///G4double nomFieldValue = (*i)->GetNominalFieldValue();
|
||||
///EMfield[i] = Bfield[i];
|
||||
//}
|
||||
///return Bfield; ///ffieldValue;
|
||||
}
|
||||
|
||||
void lem4UniformField::SetNominalFieldValue(G4double newFieldValue){ ///[6]) {
|
||||
///Bfield = newFieldValue; ///ffieldValue=newFieldValue;
|
||||
///for (int i = 0; i < 6; i++){
|
||||
///EMfield[i] = newFieldValue[i];
|
||||
///}
|
||||
G4cout<<"lem4UniformField.cc: SetNominalFieldValue method is NOT defined in this case!\n Dummy field value "<< newFieldValue << G4endl;
|
||||
//G4cout<<"lem4UnifromField.cc: ffieldValue changed to="<< Bfield/tesla<<"T "<<G4endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
G4bool lem4UniformField::isOutside(G4ThreeVector& local) const
|
||||
{
|
||||
return (std::fabs(local.z()) > fieldLength/2.0 || std::fabs(local.x()) > fieldWidth/2.0 || std::fabs(local.y()) > fieldHeight/2.0);
|
||||
}
|
||||
|
||||
G4bool lem4UniformField::isWithin(G4ThreeVector& local) const
|
||||
{
|
||||
return (std::fabs(local.z()) < fieldLength/2.0 && std::fabs(local.x()) < fieldWidth/2.0 && std::fabs(local.y()) < fieldHeight/2.0);
|
||||
}
|
115
geant4/LEMuSR/src/lem4VisManager.cc
Normal file
115
geant4/LEMuSR/src/lem4VisManager.cc
Normal file
@ -0,0 +1,115 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#ifdef G4VIS_USE
|
||||
|
||||
#include "lem4VisManager.hh"
|
||||
|
||||
// Supported drivers...
|
||||
|
||||
// Not needing external packages or libraries...
|
||||
#include "G4ASCIITree.hh"
|
||||
#include "G4DAWNFILE.hh"
|
||||
//#include "G4GAGTree.hh" // Class removed from ver. 4.9
|
||||
#include "G4HepRepFile.hh"
|
||||
#include "G4HepRep.hh"
|
||||
#include "G4RayTracer.hh"
|
||||
#include "G4VRML1File.hh"
|
||||
#include "G4VRML2File.hh"
|
||||
|
||||
// Needing external packages or libraries...
|
||||
|
||||
#ifdef G4VIS_USE_DAWN
|
||||
#include "G4FukuiRenderer.hh"
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_OPENGLX
|
||||
#include "G4OpenGLImmediateX.hh"
|
||||
#include "G4OpenGLStoredX.hh"
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_OPENGLWIN32
|
||||
#include "G4OpenGLImmediateWin32.hh"
|
||||
#include "G4OpenGLStoredWin32.hh"
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_OPENGLXM
|
||||
#include "G4OpenGLImmediateXm.hh"
|
||||
#include "G4OpenGLStoredXm.hh"
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_OIX
|
||||
#include "G4OpenInventorX.hh"
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_OIWIN32
|
||||
#include "G4OpenInventorWin32.hh"
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_VRML
|
||||
#include "G4VRML1.hh"
|
||||
#include "G4VRML2.hh"
|
||||
#endif
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4VisManager::lem4VisManager () {}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4VisManager::RegisterGraphicsSystems () {
|
||||
|
||||
// Graphics Systems not needing external packages or libraries...
|
||||
RegisterGraphicsSystem (new G4ASCIITree);
|
||||
RegisterGraphicsSystem (new G4DAWNFILE);
|
||||
//RegisterGraphicsSystem (new G4GAGTree); // Class removed from ver. 4.9
|
||||
RegisterGraphicsSystem (new G4HepRepFile);
|
||||
RegisterGraphicsSystem (new G4HepRep);
|
||||
RegisterGraphicsSystem (new G4RayTracer);
|
||||
RegisterGraphicsSystem (new G4VRML1File);
|
||||
RegisterGraphicsSystem (new G4VRML2File);
|
||||
|
||||
// Graphics systems needing external packages or libraries...
|
||||
|
||||
#ifdef G4VIS_USE_DAWN
|
||||
RegisterGraphicsSystem (new G4FukuiRenderer);
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_OPENGLX
|
||||
RegisterGraphicsSystem (new G4OpenGLImmediateX);
|
||||
RegisterGraphicsSystem (new G4OpenGLStoredX);
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_OPENGLWIN32
|
||||
RegisterGraphicsSystem (new G4OpenGLImmediateWin32);
|
||||
RegisterGraphicsSystem (new G4OpenGLStoredWin32);
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_OPENGLXM
|
||||
RegisterGraphicsSystem (new G4OpenGLImmediateXm);
|
||||
RegisterGraphicsSystem (new G4OpenGLStoredXm);
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_OIX
|
||||
RegisterGraphicsSystem (new G4OpenInventorX);
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_OIWIN32
|
||||
RegisterGraphicsSystem (new G4OpenInventorWin32);
|
||||
#endif
|
||||
|
||||
#ifdef G4VIS_USE_VRML
|
||||
RegisterGraphicsSystem (new G4VRML1);
|
||||
RegisterGraphicsSystem (new G4VRML2);
|
||||
#endif
|
||||
|
||||
if (fVerbose > 0) {
|
||||
G4cout <<
|
||||
"\nYou have successfully chosen to use the following graphics systems."
|
||||
<< G4endl;
|
||||
PrintAvailableGraphicsSystems ();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
1032
geant4/LEMuSR/src/meyer.cc
Normal file
1032
geant4/LEMuSR/src/meyer.cc
Normal file
File diff suppressed because it is too large
Load Diff
187
geant4/LEMuSR/src/musrEventAction.cc
Normal file
187
geant4/LEMuSR/src/musrEventAction.cc
Normal file
@ -0,0 +1,187 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
#include "lem4EventAction.hh"
|
||||
#include "G4Event.hh"
|
||||
#include "G4EventManager.hh"
|
||||
#include "G4TrajectoryContainer.hh"
|
||||
#include "G4Trajectory.hh"
|
||||
#include "G4VVisManager.hh"
|
||||
#include "G4ios.hh"
|
||||
#include "G4TransportationManager.hh"
|
||||
#include "G4FieldManager.hh"
|
||||
#include "lem4MagneticField.hh"
|
||||
#include "lem4TabulatedField3D.hh"
|
||||
#include "lem4TabulatedField2D.hh"
|
||||
#include "lem4RootOutput.hh"
|
||||
#include "lem4ErrorMessage.hh"
|
||||
#include "lem4SteppingAction.hh"
|
||||
#include "F04GlobalField.hh"
|
||||
//#include "F04ElementField.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool lem4EventAction::setRandomNrSeedAccordingEventNr=0;
|
||||
G4bool lem4EventAction::setRandomNrSeedFromFile=0;
|
||||
G4int lem4EventAction::nHowOftenToPrintEvent=10000;
|
||||
//vector<int> * lem4EventAction::RandomNrInitialisers=NULL;
|
||||
|
||||
//long lem4EventAction::myEventNr=0;
|
||||
|
||||
lem4EventAction::lem4EventAction() {
|
||||
pointer=this;
|
||||
fieldValueStart=0;
|
||||
pointerToSeedVector = new vector<int>;
|
||||
timeDependentField=false;
|
||||
lastFieldValue=-10000*tesla;
|
||||
pointerToMusrUniformField=NULL;
|
||||
pointerToTabulatedField3D=NULL;
|
||||
pointerToTabulatedField2D=NULL;
|
||||
latestEventNr=-1;
|
||||
}
|
||||
lem4EventAction* lem4EventAction::pointer=0;
|
||||
lem4EventAction* lem4EventAction::GetInstance() {
|
||||
return pointer;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
lem4EventAction::~lem4EventAction()
|
||||
{
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4EventAction::BeginOfEventAction(const G4Event* evt) {
|
||||
// test error
|
||||
// lem4ErrorMessage::GetInstance()->lem4Error(SERIOUS,"test error",true);
|
||||
//
|
||||
// G4cout<<"lem4EventAction::BeginOfEventAction: KAMIL"<<G4endl;
|
||||
lem4SteppingAction::GetInstance()->DoAtTheBeginningOfEvent();
|
||||
|
||||
long thisEventNr = (long) (evt->GetEventID());
|
||||
|
||||
if (F04GlobalField::Exists()) {
|
||||
// if (F04GlobalField::getObject() -> DoesAnyFieldValueNeedsToBeChanged(thisEventNr)) {
|
||||
// G4cout<<"We should check each Element Field Object whether its field needs to be changed:"<<G4endl;
|
||||
// Loop over all Element Fields and tell them to change their nominal field value, if that was foreseen.
|
||||
|
||||
// F04ElementField
|
||||
// }
|
||||
F04GlobalField::getObject() -> CheckWhetherAnyNominalFieldValueNeedsToBeChanged(thisEventNr);
|
||||
}
|
||||
|
||||
latestEventNr = thisEventNr;
|
||||
G4double actualFieldValue;
|
||||
if (timeDependentField) {
|
||||
// actualFieldValue=fieldAtEnd-fieldAtBeginning
|
||||
G4int i=int(double(thisEventNr)/double(maxEventNr)*fieldNrOfSteps); // i ... nr of actual step in the field
|
||||
actualFieldValue=fieldValueStart+fieldStep*i;
|
||||
if (actualFieldValue!=lastFieldValue) {
|
||||
lastFieldValue=actualFieldValue;
|
||||
// G4FieldManager* fieldMgr = G4TransportationManager::GetTransportationManager()->GetFieldManager();
|
||||
// // fieldMgr->SetFieldValue(actualFieldValue); //did not work
|
||||
// const G4Field* pointerToField = NULL;
|
||||
// pointerToField=fieldMgr->GetDetectorField();
|
||||
// pointerToField->GetFieldValue(0,0,0,0,
|
||||
if (pointerToMusrUniformField) {
|
||||
pointerToMusrUniformField->SetFieldValue(actualFieldValue);
|
||||
// pointerToField->SetFieldValue(actualFieldValue); does not work
|
||||
G4cout<<"Event "<<thisEventNr<<": Uniform field value changed to ";
|
||||
G4cout<<(actualFieldValue/tesla)<<"Tesla."<<G4endl;
|
||||
}
|
||||
else if (pointerToTabulatedField3D) {
|
||||
pointerToTabulatedField3D->SetFieldValue(actualFieldValue);
|
||||
G4cout<<"Event "<<thisEventNr<<": Tabulated Field (3D) value changed to ";
|
||||
G4cout<<(actualFieldValue/tesla)<<"Tesla."<<G4endl;
|
||||
}
|
||||
else if (pointerToTabulatedField2D) {
|
||||
pointerToTabulatedField2D->SetFieldValue(actualFieldValue);
|
||||
G4cout<<"Event "<<thisEventNr<<": Tabulated Field (2D) value changed to ";
|
||||
G4cout<<(actualFieldValue/tesla)<<"Tesla."<<G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {actualFieldValue=fieldValueStart;}
|
||||
lem4RootOutput* myRootOutput = lem4RootOutput::GetRootInstance();
|
||||
myRootOutput->SetFieldValue(actualFieldValue);
|
||||
|
||||
// if (lem4DetectorMessenger::setRandomNrSeedAccordingEventNr) {
|
||||
if (setRandomNrSeedFromFile) {
|
||||
// G4cout<<"RandomNrInitialisers.size()="<<RandomNrInitialisers->size()<<G4endl;
|
||||
if (thisEventNr < (long) pointerToSeedVector->size()) {
|
||||
G4cout <<"lem4EventAction.cc: seed will be set to="<< pointerToSeedVector->at(thisEventNr)<<G4endl;
|
||||
CLHEP::HepRandom::setTheSeed(pointerToSeedVector->at(thisEventNr));
|
||||
}
|
||||
}
|
||||
else if (setRandomNrSeedAccordingEventNr) {
|
||||
// long seeds[2];
|
||||
// seeds[0] = (long) 234567890+thisEventNr*117;
|
||||
// seeds[1] = (long) 333222111+thisEventNr*173;
|
||||
//
|
||||
// // seeds[1] = (long) (evt->GetEventID());
|
||||
// // seeds[0] = (long) 123456789; // This leads to a gap in the decay time histogram fro N=100000 events
|
||||
// // seeds[1] = (long) 333222111+thisEventNr; // ----------------------------||------------------------------------
|
||||
// thisEventNr++;
|
||||
// CLHEP::HepRandom::setTheSeeds(seeds);
|
||||
// // G4cout << "seed1: " << seeds[0] << "; seed2: " << seeds[1] << G4endl;
|
||||
//
|
||||
// G4cout <<" thisEventNr="<<thisEventNr;
|
||||
CLHEP::HepRandom::setTheSeed(thisEventNr);
|
||||
// G4cout <<" getTheSeed="<<CLHEP::HepRandom::getTheSeed()<< G4endl;
|
||||
CLHEP::RandGauss::setFlag(false);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void lem4EventAction::EndOfEventAction(const G4Event* evt) {
|
||||
// cout << ":." << flush;
|
||||
long thisEventNr = (long) evt->GetEventID();
|
||||
|
||||
// get number of stored trajectories
|
||||
//
|
||||
G4TrajectoryContainer* trajectoryContainer = evt->GetTrajectoryContainer();
|
||||
G4int n_trajectories = 0;
|
||||
if (trajectoryContainer) n_trajectories = trajectoryContainer->entries();
|
||||
|
||||
// G4cout << ">>> Event " << evt->GetEventID() << G4endl;
|
||||
|
||||
// periodic printing
|
||||
//
|
||||
// if (thisEventNr != 0 and thisEventNr%10000 == 0) {
|
||||
if (thisEventNr != 0 and thisEventNr%nHowOftenToPrintEvent == 0) {
|
||||
time_t curr=time(0);
|
||||
//char * ctime(const time_t * tp);
|
||||
G4cout << ">>> Event " << evt->GetEventID() <<" at "<< ctime(&curr);
|
||||
G4cout.flush();
|
||||
// G4cout << " seed set to "<< CLHEP::HepRandom::getTheSeed();//<< G4endl;
|
||||
}
|
||||
|
||||
// extract the trajectories and draw them
|
||||
//
|
||||
if (G4VVisManager::GetConcreteInstance()) {
|
||||
for (G4int i=0; i<n_trajectories; i++)
|
||||
{ G4Trajectory* trj = (G4Trajectory*)
|
||||
((*(evt->GetTrajectoryContainer()))[i]);
|
||||
trj->DrawTrajectory(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
vector<int> * lem4EventAction::pointerToSeedVector=NULL;
|
||||
vector<int> * lem4EventAction::GetPointerToSeedVector() {
|
||||
return pointerToSeedVector;
|
||||
}
|
||||
|
||||
|
||||
void lem4EventAction::SetTimeDependentField(G4bool setFieldToBeTimeDependend, G4double initialField,
|
||||
G4double finalField, G4int nrOfSteps) {
|
||||
timeDependentField = setFieldToBeTimeDependend;
|
||||
fieldValueStart = initialField;
|
||||
fieldValueEnd = finalField;
|
||||
fieldNrOfSteps = nrOfSteps;
|
||||
fieldStep = (finalField-initialField)/(nrOfSteps-1);
|
||||
G4cout<<"---&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&---"<<G4endl;
|
||||
}
|
102
geant4/LEMuSR/src/yields.cc
Normal file
102
geant4/LEMuSR/src/yields.cc
Normal file
@ -0,0 +1,102 @@
|
||||
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||
// Muonium yields as a function of initial mu+ energies.
|
||||
// The method GetYields is used by MuFormation.
|
||||
// Id : yields.cc, v 1.1
|
||||
// Author: Taofiq PARAISO, T. Shiroka
|
||||
// Date : 2007-12
|
||||
// Notes : First implemented in Fortran by A. Hofer
|
||||
// C++ conversion by T.K. Paraiso 04-2005
|
||||
// Slight modifications by T. Shiroka
|
||||
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||
|
||||
#include "yields.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
The Muonium Yield function as well as the parameters are taken from:
|
||||
M. Gonin, R. Kallenbach, P. Bochsler: "Charge exchange of hydrogen atoms
|
||||
in carbon foils at 0.4 - 120 keV", Rev.Sci.Instrum. 65 (3), March 1994
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
Yields:: Yields(){;}
|
||||
Yields::~Yields(){;}
|
||||
|
||||
void Yields::GetYields(
|
||||
double E, // kinetic energy in keV
|
||||
double mass, // mass in keV/c**2
|
||||
double yvector[3]) // pointer to the yields table
|
||||
|
||||
{
|
||||
// Parameter NAMES for the muonium yield function
|
||||
double a_zero, a_minus;
|
||||
double k_Fermi, k_zero, k_minus;
|
||||
double two_k_Fermi;
|
||||
double k_Fermi_Quad, k_zero_Quad, k_minus_Quad;
|
||||
double vc_minus, vc_plus, v_Bohr, v_rel;
|
||||
|
||||
// Parameter VALUES for the muonium yield function
|
||||
a_zero = 0.953;
|
||||
a_minus = 0.029;
|
||||
k_Fermi = 1.178; // [v_Bohr]
|
||||
k_Fermi_Quad = k_Fermi * k_Fermi;
|
||||
two_k_Fermi = 2. * k_Fermi;
|
||||
k_zero = 0.991*k_Fermi; // [v_Bohr]
|
||||
k_zero_Quad = k_zero * k_zero;
|
||||
k_minus = 0.989*k_Fermi; // [v_Bohr]
|
||||
k_minus_Quad = k_minus * k_minus;
|
||||
vc_minus = 0.284;
|
||||
vc_plus = 0.193; // [v_Bohr]
|
||||
v_Bohr = 7.2974E-3; // [c]
|
||||
|
||||
|
||||
// std::cout<<"E = "<< E <<std::endl;
|
||||
|
||||
// Abort in case of negative energies ---------------------------
|
||||
if (E < 0)
|
||||
{
|
||||
std::cout<< "Error in method ''Yields'':" <<std::endl;
|
||||
std::cout<< "E = "<< E <<" < 0!" <<std::endl;
|
||||
std::cout<< "-> ABORTED!" <<std::endl;
|
||||
return;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Definition of variables (aux_n are some auxiliary variables)
|
||||
// Calculate energy in (classical) terms of speed (in units of v_Bohr):
|
||||
|
||||
v_rel = sqrt(2.*E/mass)/ v_Bohr;
|
||||
|
||||
aux1 = v_rel*v_rel;
|
||||
aux2 = two_k_Fermi*v_rel;
|
||||
Q_zero = 1. + (k_zero_Quad - k_Fermi_Quad - aux1) / aux2;
|
||||
Q_minus = 1. + (k_minus_Quad - k_Fermi_Quad - aux1) / aux2;
|
||||
|
||||
aux1 = a_zero * Q_zero;
|
||||
aux2 = a_minus * Q_minus;
|
||||
aux3 = (1.-Q_zero)*(1.-Q_minus);
|
||||
D = aux1*(aux2 + (1.-Q_minus)) + aux3;
|
||||
|
||||
Yield_minus = aux1*aux2 / D;
|
||||
Yield_plus = aux3 / D;
|
||||
|
||||
Yield_minus = Yield_minus* exp(-vc_minus/v_rel);
|
||||
Yield_plus = Yield_plus * exp(-vc_plus /v_rel);
|
||||
|
||||
if(Yield_minus > exp(-vc_minus/v_rel)) Yield_minus=exp(-vc_minus/v_rel);
|
||||
if(Yield_plus > exp(-vc_plus/v_rel)) Yield_plus=exp(-vc_plus/v_rel);
|
||||
|
||||
Yield_zero = 1. - (Yield_minus + Yield_plus);
|
||||
|
||||
yvector[0]=Yield_plus;
|
||||
yvector[1]=Yield_zero;
|
||||
yvector[2]=Yield_minus;
|
||||
|
||||
// std::cout<<"Y+ : "<< Yield_plus << std::endl;
|
||||
// std::cout<<"Y0 : "<< Yield_zero << std::endl;
|
||||
}
|
Reference in New Issue
Block a user