Implementation of Spin Rotator.

This commit is contained in:
shiroka
2008-12-22 17:53:30 +00:00
parent 4c7938ed6d
commit 76c7f4062e
111 changed files with 409662 additions and 0 deletions

View File

@ -0,0 +1,40 @@
# $Id: GNUmakefile,v 1.1.1.1 2007/12/12 11:24:11 shiroka Exp $
# --------------------------------------------------------------
# GNUmakefile for examples module. Gabriele Cosmo, 06/04/98.
# --------------------------------------------------------------
name := sr1
G4TARGET := $(name)
G4EXLIB := true
##LDFLAGS := $(shell root-config --glibs)
#ROOTLIBS := ${shell root-config --glibs}
#LDFLAGS := -L./ ${ROOTLIBS}
# Root (exlude libNew and libpthread from library list)
#ROOTINC = -I$(ROOTSYS)/include
# Removed -lHtml for compatibility with root 5.18 (TS)
# Otherwise keep it, but add also -lThread.
##ROOTLIBS = $(shell $(ROOTSYS)/bin/root-config --glibs) -lMinuit -lHtml
##ROOTLIBS = $(shell $(ROOTSYS)/bin/root-config --glibs) -lMinuit -lHtml -lThread
ROOTLIBS = $(shell $(ROOTSYS)/bin/root-config --glibs) -lMinuit
ROOTLIBS := $(filter-out -lNew,$(ROOTLIBS))
ROOTLIBS := $(filter-out -lpthread,$(ROOTLIBS))
#
ROOTLIBS := $(filter-out -lThread,$(ROOTLIBS))
#ROOTLIBS := $(filter-out -lpthread,$(ROOTLIBS))
ROOTLIBS := $(filter-out -pthread,$(ROOTLIBS))
# Extra flags for G4
#CPPFLAGS += $(ROOTINC)
#LDLIBS += $(ROOTLIBS)
EXTRALIBS += $(ROOTLIBS)
CPPFLAGS += -g
ifndef G4INSTALL
G4INSTALL = ../../..
endif
.PHONY: all
all: lib bin
include $(G4INSTALL)/config/binmake.gmk

View File

@ -0,0 +1,181 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#ifndef F04ElementField_h
#define F04ElementField_h 1
#include "globals.hh"
#include "G4Navigator.hh"
#include "G4TransportationManager.hh"
#include "G4UserLimits.hh"
#include "G4VisAttributes.hh"
// class F04ElementField - interface for the EM field of one element
// This is the interface class used by GlobalField to compute the field
// value at a given point[].
// An element that represents an element with an EM field will
// derive a class from this one and implement the computation for the
// element. The construct() function will add the derived object into
// GlobalField.
class F04ElementField
{
private:
F04ElementField& operator=(const F04ElementField&);
public:
/// Constructor.
F04ElementField(const G4ThreeVector, G4LogicalVolume*);
/// the actual implementation constructs the F04ElementField
void construct();
/// Destructor.
virtual ~F04ElementField() { if (aNavigator) delete aNavigator; }
/// setMaxStep(G4double) sets the max. step size
void setMaxStep(G4double s)
{
maxStep = s;
userLimits->SetMaxAllowedStep(maxStep);
lvolume->SetUserLimits(userLimits);
}
/// getMaxStep() returns the max. step size
G4double getMaxStep() { return maxStep; }
/// setColor(G4String) sets the color
void setColor(G4String c)
{
color = c;
lvolume->SetVisAttributes(getVisAttribute(color));
}
/// getColor() returns the color
G4String getColor() { return color; }
/// getVisAttribute() returns the appropriate G4VisAttributes.
static G4VisAttributes* getVisAttribute(G4String color);
/// setGlobalPoint() ensures that the point is within the global
/// bounding box of this ElementField's global coordinates.
/// Normally called 8 times for the corners of the local bounding
/// box, after a local->global coordinate transform.
/// If never called, the global bounding box is infinite.
/// BEWARE: if called only once, the bounding box is just a point.
void setGlobalPoint(const G4double point[4])
{
if(minX == -DBL_MAX || minX > point[0]) minX = point[0];
if(minY == -DBL_MAX || minY > point[1]) minY = point[1];
if(minZ == -DBL_MAX || minZ > point[2]) minZ = point[2];
if(maxX == DBL_MAX || maxX < point[0]) maxX = point[0];
if(maxY == DBL_MAX || maxY < point[1]) maxY = point[1];
if(maxZ == DBL_MAX || maxZ < point[2]) maxZ = point[2];
}
/// isInBoundingBox() returns true if the point is within the
/// global bounding box - global coordinates.
bool isInBoundingBox(const G4double point[4]) const
{
if(point[2] < minZ || point[2] > maxZ) return false;
if(point[0] < minX || point[0] > maxX) return false;
if(point[1] < minY || point[1] > maxY) return false;
return true;
}
/// addFieldValue() will add the field value for this element to field[].
/// Implementations must be sure to verify that point[] is within
/// the field region, and do nothing if not.
/// point[] is in global coordinates and geant4 units; x,y,z,t.
/// field[] is in geant4 units; Bx,By,Bz,Ex,Ey,Ez.
/// For efficiency, the caller may (but need not) call
/// isInBoundingBox(point), and only call this function if that
/// returns true.
virtual void
addFieldValue(const G4double point[4], G4double field[6]) const = 0;
virtual G4double getLength() = 0;
virtual G4double getWidth() = 0;
virtual G4double getHeight() = 0;
///ADDED BY KAMIL. TS!!
void SetElementFieldName(G4String name) {elementFieldName=name;}
G4String GetElementFieldName() {return elementFieldName;}
void SetEventNrDependentField(G4double initialField, G4double finalField, G4int nrOfSteps);
std::map<G4int,G4double> GetEventNrDependentField() const {return changeFieldInStepsMap;}
// void SetElementFieldValueIfNeeded(G4int eventNr) const {
// std::map<G4int,G4double>::iterator itr;
// if ( (itr = changeFieldInStepsMap.find(eventNr)) != changeFieldInStepsMap.end() ) {
// G4double newNominalFieldValue = itr->second ;
//
// G4cout<<"Nominal Field changed for "<<elementFieldName<<" to value "<<newNominalFieldValue<<G4cout;
// }
// }
void SetElementFieldValueIfNeeded(G4int eventNr);
virtual G4double GetNominalFieldValue() = 0;
virtual void SetNominalFieldValue(G4double newFieldValue) =0;
protected:
G4LogicalVolume* lvolume;
G4AffineTransform global2local;
// F04ElementField(const F04ElementField&);
private:
static G4Navigator* aNavigator;
G4String color;
G4ThreeVector center;
G4double minX, minY, minZ, maxX, maxY,maxZ;
G4double maxStep;
G4UserLimits* userLimits;
G4String elementFieldName;
std::map<G4int,G4double> changeFieldInStepsMap;
};
#endif

View File

@ -0,0 +1,73 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#ifndef F04FieldMessenger_h
#define F04FieldMessenger_h 1
#include "globals.hh"
#include "G4UImessenger.hh"
class F04GlobalField;
class G4UIdirectory;
class G4UIcmdWithAString;
class G4UIcmdWithAnInteger;
class G4UIcmdWithADoubleAndUnit;
class G4UIcmdWithoutParameter;
class F04FieldMessenger: public G4UImessenger
{
public:
F04FieldMessenger(F04GlobalField* );
~F04FieldMessenger();
void SetNewValue(G4UIcommand*, G4String);
void SetNewValue(G4UIcommand*, G4int);
private:
F04GlobalField* fGlobalField;
G4UIdirectory* detDir;
G4UIcmdWithAnInteger* fStepperCMD;
G4UIcmdWithADoubleAndUnit* fMinStepCMD;
G4UIcmdWithADoubleAndUnit* fDeltaChordCMD;
G4UIcmdWithADoubleAndUnit* fDeltaOneStepCMD;
G4UIcmdWithADoubleAndUnit* fDeltaIntersectionCMD;
G4UIcmdWithADoubleAndUnit* fEpsMinCMD;
G4UIcmdWithADoubleAndUnit* fEpsMaxCMD;
G4UIcmdWithoutParameter* fUpdateCMD;
};
#endif

View File

@ -0,0 +1,193 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
//
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#ifndef F04GlobalField_h
#define F04GlobalField_h 1
#include <vector>
#include "G4FieldManager.hh"
#include "G4PropagatorInField.hh"
#include "G4MagIntegratorStepper.hh"
#include "G4ChordFinder.hh"
#include "G4MagneticField.hh"
#include "G4ElectroMagneticField.hh"
#include "G4Mag_EqRhs.hh"
#include "G4Mag_SpinEqRhs.hh"
#include "G4EqMagElectricField.hh"
#include "G4EqEMFieldWithSpin.hh"
#include "F04FieldMessenger.hh"
#include "F04ElementField.hh"
// F04GlobalField - handles the global ElectroMagnetic field
//
// There is a single G04GlobalField object.
//
// The field from each individual beamline element is given by a
// ElementField object. Any number of overlapping ElementField
// objects can be added to the global field. Any element that
// represents an element with an EM field must add the appropriate
// ElementField to the global GlobalField object.
typedef std::vector<F04ElementField*> FieldList;
class F04GlobalField : public G4ElectroMagneticField {
//class F04GlobalField : public G4MagneticField {
private:
F04GlobalField();
F04GlobalField(const F04GlobalField&);
~F04GlobalField();
F04GlobalField& operator=(const F04GlobalField&);
void setupArray();
public:
/// getObject() returns the single F04GlobalField object.
/// It is constructed, if necessary.
static F04GlobalField* getObject();
//
static G4bool Exists() {if (object==NULL) {return false;} else {return true;}; }
/// GetFieldValue() returns the field value at a given point[].
/// field is really field[6]: Bx,By,Bz,Ex,Ey,Ez.
/// point[] is in global coordinates: x,y,z,t.
void GetFieldValue(const G4double* point, G4double* field) const;
/// DoesFieldChangeEnergy() returns true.
G4bool DoesFieldChangeEnergy() const { return true; }
/// addElementField() adds the ElementField object for a single
/// element to the global field.
void addElementField(F04ElementField* f) { if (fields) fields->push_back(f); }
/// clear() removes all ElementField-s from the global object,
/// and destroys them. Used before the geometry is completely
/// re-created.
void clear();
/// updates all field tracking objects and clear()
void updateField();
/// Set the Stepper types
void SetStepperType( G4int i ) { fStepperType = i; }
/// Set the Stepper
void SetStepper();
/// Set the minimum step length
void SetMinStep(G4double s) { minStep = s; }
/// Set the delta chord length
void SetDeltaChord(G4double s) { deltaChord = s; }
/// Set the delta one step length
void SetDeltaOneStep(G4double s) { deltaOneStep = s; }
/// Set the delta intersection length
void SetDeltaIntersection(G4double s) { deltaIntersection = s; }
/// Set the minimum eps length
void SetEpsMin(G4double s) { epsMin = s; }
/// Set the maximum eps length
void SetEpsMax(G4double s) { epsMax = s; }
/// Return the list of Element Fields
FieldList* getFields() { return fields; }
// Additions by KS
// G4bool DoesAnyFieldValueNeedsToBeChanged(G4int eventNumber) {return globalChangeFieldInStepsMap[eventNumber];}
void CheckWhetherAnyNominalFieldValueNeedsToBeChanged(G4int eventNumber);
// Add point, at which user wishes to print out the field value
void AddPointForFieldTesting(G4ThreeVector point) {pointsAtWhichUserWantsToPrintFieldValue.push_back(point);}
// Print field value at all points user wished to be print out:
void PrintFieldAtRequestedPoints() const;
protected:
/// Get the global field manager
G4FieldManager* GetGlobalFieldManager();
private:
static F04GlobalField* object;
G4int nfp;
G4bool first;
FieldList* fields;
const F04ElementField **fp;
std::vector<G4ThreeVector> pointsAtWhichUserWantsToPrintFieldValue;
private:
G4int fStepperType;
G4double minStep;
G4double deltaChord;
G4double deltaOneStep;
G4double deltaIntersection;
G4double epsMin;
G4double epsMax;
// G4Mag_EqRhs* fEquation;
// G4Mag_SpinEqRhs* fEquation;
// G4EqMagElectricField* fEquation;
G4EqEMFieldWithSpin* fEquation;
G4FieldManager* fFieldManager;
G4PropagatorInField* fFieldPropagator;
G4MagIntegratorStepper* fStepper;
G4ChordFinder* fChordFinder;
F04FieldMessenger* fFieldMessenger;
std::map<G4int,G4bool> globalChangeFieldInStepsMap;
};
#endif

View File

@ -0,0 +1,66 @@
//
// ********************************************************************
// * 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: G4MuonDecayChannel.hh,v 1.6 2006/06/29 19:23:35 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
// ------------------------------------------------------------
#ifndef MuDecayChannel_h
#define MuDecayChannel_h 1
#include "G4ios.hh"
#include "globals.hh"
#include "G4VDecayChannel.hh"
class MuDecayChannel :public G4VDecayChannel
{
// Class Decription
// This class describes muon decay kinemtics.
// This version neglects muon polarization
// assumes the pure V-A coupling
// gives incorrect energy spectrum for neutrinos
//
public: // With Description
//Constructors
MuDecayChannel(const G4String& theParentName,
G4double theBR);
// Destructor
virtual ~MuDecayChannel();
public: // With Description
virtual G4DecayProducts *DecayIt(G4double);
};
#endif

View File

@ -0,0 +1,125 @@
//
// ********************************************************************
// * 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.
//
// ------------------------------------------------------------
#ifndef MuDecayChannelWithSpin_hh
#define MuDecayChannelWithSpin_hh 1
#include "globals.hh"
#include "G4ThreeVector.hh"
#include "MuDecayChannel.hh"
class MuDecayChannelWithSpin : public MuDecayChannel
{
// Class Decription
// This class describes muon decay kinemtics.
// This version assumes V-A coupling with 1st order radiative correctons,
// the standard model Michel parameter values, but
// gives incorrect energy spectrum for neutrinos
public: // With Description
//Constructors
MuDecayChannelWithSpin(const G4String& theParentName,
G4double theBR);
// Destructor
virtual ~MuDecayChannelWithSpin();
public: // With Description
virtual G4DecayProducts *DecayIt(G4double);
void SetPolarization(G4ThreeVector);
const G4ThreeVector& GetPolarization() const;
private:
G4ThreeVector parent_polarization;
// Radiative Correction Factors
G4double F_c(G4double x, G4double x0);
G4double F_theta(G4double x, G4double x0);
G4double R_c(G4double x);
G4double EMMU;
G4double EMASS;
};
inline void MuDecayChannelWithSpin::SetPolarization(G4ThreeVector polar)
{
parent_polarization = polar;
}
inline const G4ThreeVector& MuDecayChannelWithSpin::GetPolarization() const
{
return parent_polarization;
}
inline G4double MuDecayChannelWithSpin::F_c(G4double x, G4double x0)
{
G4double omega = std::log(EMMU/EMASS);
G4double f_c;
f_c = (5.+17.*x-34.*x*x)*(omega+std::log(x))-22.*x+34.*x*x;
f_c = (1.-x)/(3.*x*x)*f_c;
f_c = (6.-4.*x)*R_c(x)+(6.-6.*x)*std::log(x) + f_c;
f_c = (fine_structure_const/twopi) * (x*x-x0*x0) * f_c;
return f_c;
}
inline G4double MuDecayChannelWithSpin::F_theta(G4double x, G4double x0)
{
G4double omega = std::log(EMMU/EMASS);
G4double f_theta;
f_theta = (1.+x+34*x*x)*(omega+std::log(x))+3.-7.*x-32.*x*x;
f_theta = f_theta + ((4.*(1.-x)*(1.-x))/x)*std::log(1.-x);
f_theta = (1.-x)/(3.*x*x) * f_theta;
f_theta = (2.-4.*x)*R_c(x)+(2.-6.*x)*std::log(x)-f_theta;
f_theta = (fine_structure_const/twopi) * (x*x-x0*x0) * f_theta;
return f_theta;
}
#endif

View File

@ -0,0 +1,65 @@
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//*
// LOW ENERGY MUON SPIN RELAXATION, ROTATION, RADIATION Geant4 SIMULATION
// ID : MEYER.hh , v 1.0
// AUTHOR: Taofiq PARAISO
// DATE : 2005-04
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
//
// & &&&&&&&&&& &&&&&&& &&&&&&&&
// & & && && & &&
// & & & & & & &&
// & &&&&&&& & & &&&&&& &&&&&&&&
// & & & && & & &&
// & & && & & && && & &
// &&&&&&&&&& &&&&&&&&&& & &&&&& && &&&&&&& & &&
// &
// &
// &
// &
// MEYER
/*
fIRST IMPLEMENTATION BY ANLSEM,H. IN FORTRAN
C++ CONVERSION T.K.PARAISO 04-2005
!!! IMPORTANT !!!
Notice:
Tables definition changes between FORTRAN and C++:
1/ Fortran indices start at 1 and C++ indices start at 0
2/ Tables are defined as table[column][row] in Fortran
table[row][column] in c++
usefull reference
http://gershwin.ens.fr/vdaniel/Doc-Locale/Langages-Program-Scientific/Fortran/Tutorial/arrays.htm
*/
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
#ifndef meyer_h
#define meyer_h 1
#include <iomanip>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <ios>
#include "globals.hh"
class meyer
{
public:
meyer();
~meyer();
void GFunctions(double*, double*, double);
void Get_F_Function_Meyer(double tau, double Ekin, double Z1, double Z2, double m1, double m2);
void F_Functions_Meyer( double tau,double thetaSchlange,double *f1,double *f2);
void Get_F_Function(double tau,double theta, double Ekin, double Z1, double Z2, double m1, double m2, double* F);
};
#endif

View File

@ -0,0 +1,351 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1RootOutput_h
#define sr1RootOutput_h 1
//#include "G4UserRunAction.hh"
#include "globals.hh"
#include "G4ThreeVector.hh"
// ROOT
#include "TFile.h"
#include "TTree.h"
#include "TH1.h"
#include "TH2.h"
#include "TVectorD.h"
//
#include <map>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1RootOutput {
public:
sr1RootOutput();
~sr1RootOutput();
static sr1RootOutput* GetRootInstance();
public:
void BeginOfRunAction();
void EndOfRunAction();
void FillEvent();
void ClearAllRootVariables();
// void SetSensitiveDetectorMapping(std::string logivol, int volumeID);
void SetVolumeIDMapping(std::string logivol, int volumeID);
G4int ConvertVolumeToID(std::string logivol);
G4int ConvertProcessToID(std::string processName);
void SetSpecialSaveVolumeDefined() {boolIsAnySpecialSaveVolumeDefined=true;};
// Getting variables (just for debugging)
G4double GetDecayPositionZ() {return muDecayPosZ_t;};
G4double GetDecayTime() {return muDecayTime_t*microsecond;};
G4double GetTimeInTarget() {return muTargetTime_t*microsecond;};
// Setting variables common to the whole event:
void SetRunID (G4int id) {runID_t = id;};
void SetEventID (G4int id) {eventID_t = id;};
void SetDecayDetectorID (std::string detectorName) {muDecayDetID_t = SensDetectorMapping[detectorName];};
void SetBField (G4double F[6]) {B_t[0]=F[0]/tesla; B_t[1]=F[1]/tesla; B_t[2]=F[2]/tesla;
B_t[3]=F[3]/tesla; B_t[4]=F[4]/tesla; B_t[5]=F[5]/tesla;};
void SetDecayPolarisation (G4ThreeVector pol) {muDecayPolX_t=pol.x(); muDecayPolY_t=pol.y(); muDecayPolZ_t=pol.z();};
void SetDecayPosition (G4ThreeVector pos) {muDecayPosX_t=pos.x()/mm; muDecayPosY_t=pos.y()/mm;
muDecayPosZ_t=pos.z()/mm;};
// void SetGlobTime (G4double gt) {globalTime_t = gt/microsecond;};
// void SetEventWeight (G4int w) {weight_t *= w;}
void SetEventWeight (G4double w) {weight_t *= w;}
void SetDetectorInfo (G4int nDetectors, G4int ID, G4int particleID, G4double edep,
G4double edep_el, G4double edep_pos,
G4double edep_gam, G4double edep_mup,G4int nsteps, G4double length, G4double t1,
G4double t2, G4double x, G4double y, G4double z,
G4double ek, G4double ekVertex, G4double xVertex, G4double yVertex, G4double zVertex,
G4int idVolVertex, G4int idProcVertex, G4int idTrackVertex) ;
void SetDetectorInfoVvv (G4int nDetectors,
G4double ekVertex, G4double xVertex, G4double yVertex, G4double zVertex,
G4int idVolVertex, G4int idProcVertex, G4int idTrackVertex, G4int particleID) ;
void SetSaveDetectorInfo (G4int ID, G4int particleID, G4double x, G4double y, G4double z,
G4double px, G4double py, G4double pz) ;
void SetInitialMuonParameters(G4double x, G4double y, G4double z, G4double px, G4double py, G4double pz,
G4double xpolaris, G4double ypolaris, G4double zpolaris) {
muIniPosX_t=x; muIniPosY_t=y; muIniPosZ_t=z;
muIniMomX_t=px; muIniMomY_t=py; muIniMomZ_t=pz;
muIniPolX_t=xpolaris; muIniPolY_t=ypolaris; muIniPolZ_t=zpolaris;
}
void PrintInitialMuonParameters() {
G4cout<<"sr1RootOutput.hh: Initial muon parameters: x="<<muIniPosX_t<<", y="<<muIniPosY_t<<", z="<<muIniPosZ_t
<<", px="<<muIniMomX_t << ", py="<<muIniMomY_t<<", pz="<<muIniMomZ_t<<G4endl;
G4cout<<" polx="<<muIniPolX_t<<", poly="<<muIniPolY_t<<", polz="<<muIniPolZ_t<<G4endl;
G4cout<<" numberOfGeneratedEvents = "<<GeantParametersD[7]<<G4endl;
}
// void SetSubtrackInfo (G4int iSubtrack, G4int partID, G4int trID, G4int volID, G4double E,
// G4double xx, G4double yy, G4double zz, G4double xxPost, G4double yyPost, G4double zzPost,
// G4double Eki, G4double stepL, G4int nrOfSubst) {
// if ((iSubtrack<0)||(iSubtrack>=maxNSubTracks)) {
// G4cout<<"SERIOUS ERROR! sr1RootOutput.hh: iSubtrack="<<iSubtrack<<
// " is larger than maxNSubTracks="<<maxNSubTracks<<G4endl;
// return;
// }
// else {
// nSubTracks=iSubtrack+1;
// particleID_t[iSubtrack]=partID;
// trackID_t[iSubtrack]=trID;
// logicalVolumeID_t[iSubtrack]=volID;
// edep_t[iSubtrack]=E/MeV;
// x_t[iSubtrack]=xx/mm;
// y_t[iSubtrack]=yy/mm;
// z_t[iSubtrack]=zz/mm;
// post_x_t[iSubtrack]=xxPost/mm;
// post_y_t[iSubtrack]=yyPost/mm;
// post_z_t[iSubtrack]=zzPost/mm;
// kineticEnergy_t[iSubtrack]=Eki/MeV;
// stepLength_t[iSubtrack]=stepL/mm;
// nrOfSubsteps_t[iSubtrack]=nrOfSubst;
// }
// };
void SetPolInTarget(G4ThreeVector pol) {muTargetPolX_t=pol.x(); muTargetPolY_t=pol.y(); muTargetPolZ_t=pol.z();};
void SetTimeInTarget(G4double time) {muTargetTime_t = time/microsecond;};
void SetPolInM0(G4ThreeVector pol) {muM0PolX_t=pol.x(); muM0PolY_t=pol.y(); muM0PolZ_t=pol.z();};
void SetTimeInM0(G4double time) {muM0Time_t = time/microsecond;};
void SetPolInM1(G4ThreeVector pol) {muM1PolX_t=pol.x(); muM1PolY_t=pol.y(); muM1PolZ_t=pol.z();};
void SetTimeInM1(G4double time) {muM1Time_t = time/microsecond;};
void SetPolInM2(G4ThreeVector pol) {muM2PolX_t=pol.x(); muM2PolY_t=pol.y(); muM2PolZ_t=pol.z();};
void SetTimeInM2(G4double time) {muM2Time_t = time/microsecond;};
void SetInitialPositronMomentum(G4ThreeVector mom) {posIniMomx_t=mom.x(); posIniMomy_t=mom.y(); posIniMomz_t=mom.z();};
void SetDecayTime(G4double time) {muDecayTime_t=time/microsecond;};
// void SetFieldValue(G4double value) {fieldValue_t=value/tesla;};
void SetNrFieldNomVal(G4int n) {nFieldNomVal = n;}
void SetFieldNomVal(G4int i, G4double value);
G4int GetNrOfVolumes() {return det_nMax;}
void SetBFieldIntegral(G4double BxInt,G4double ByInt,G4double BzInt,G4double BzInt1,G4double BzInt2,G4double BzInt3) {
BxIntegral_t=BxInt/m/tesla; ByIntegral_t=ByInt/m/tesla; BzIntegral_t=BzInt/m/tesla;
BzIntegral1_t=BzInt1/m/tesla;BzIntegral2_t=BzInt2/mm;BzIntegral3_t=BzInt3/mm;
}
void StoreGeantParameter(Int_t i, Double_t value) {
if (i<maxNGeantParameters) { GeantParametersD[i]=value; }
else {G4cout<<"sr1RootOutput.hh::StoreGeantParameter: index="<<i<<" out of range"
<<" (maxNGeantParameters=" <<maxNGeantParameters<<")"<<G4endl;}
};
TH2F *htest1, *htest2;
TH1F *htest3, *htest4, *htest5, *htest6, *htest7, *htest8;
public:
static G4bool store_runID;
static G4bool store_eventID;
static G4bool store_weight;
static G4bool store_BFieldAtDecay;
static G4bool store_muIniPosX;
static G4bool store_muIniPosY;
static G4bool store_muIniPosZ;
static G4bool store_muIniMomX;
static G4bool store_muIniMomY;
static G4bool store_muIniMomZ;
static G4bool store_muIniPolX;
static G4bool store_muIniPolY;
static G4bool store_muIniPolZ;
static G4bool store_muDecayDetID;
static G4bool store_muDecayPosX;
static G4bool store_muDecayPosY;
static G4bool store_muDecayPosZ;
static G4bool store_muDecayTime;
static G4bool store_muDecayPolX;
static G4bool store_muDecayPolY;
static G4bool store_muDecayPolZ;
static G4bool store_muTargetTime;
static G4bool store_muTargetPolX;
static G4bool store_muTargetPolY;
static G4bool store_muTargetPolZ;
static G4bool store_muM0Time;
static G4bool store_muM0PolX;
static G4bool store_muM0PolY;
static G4bool store_muM0PolZ;
static G4bool store_muM1Time;
static G4bool store_muM1PolX;
static G4bool store_muM1PolY;
static G4bool store_muM1PolZ;
static G4bool store_muM2Time;
static G4bool store_muM2PolX;
static G4bool store_muM2PolY;
static G4bool store_muM2PolZ;
static G4bool store_posIniMomX;
static G4bool store_posIniMomY;
static G4bool store_posIniMomZ;
// static G4bool store_globalTime;
// static G4bool store_fieldValue;
static G4bool store_det_ID;
static G4bool store_det_edep;
static G4bool store_det_edep_el;
static G4bool store_det_edep_pos;
static G4bool store_det_edep_gam;
static G4bool store_det_edep_mup;
static G4bool store_det_nsteps;
static G4bool store_det_length;
static G4bool store_det_start;
static G4bool store_det_end;
static G4bool store_det_x;
static G4bool store_det_y;
static G4bool store_det_z;
static G4bool store_det_kine;
static G4bool store_det_VrtxKine;
static G4bool store_det_VrtxX;
static G4bool store_det_VrtxY;
static G4bool store_det_VrtxZ;
static G4bool store_det_VrtxVolID;
static G4bool store_det_VrtxProcID;
static G4bool store_det_VrtxTrackID;
static G4bool store_det_VrtxParticleID;
static G4bool store_det_VvvKine;
static G4bool store_det_VvvX;
static G4bool store_det_VvvY;
static G4bool store_det_VvvZ;
static G4bool store_det_VvvVolID;
static G4bool store_det_VvvProcID;
static G4bool store_det_VvvTrackID;
static G4bool store_det_VvvParticleID;
static G4bool store_fieldNomVal;
static G4bool store_fieldIntegralBx;
static G4bool store_fieldIntegralBy;
static G4bool store_fieldIntegralBz;
static G4bool store_fieldIntegralBz1;
static G4bool store_fieldIntegralBz2;
static G4bool store_fieldIntegralBz3;
static G4int oldEventNumberInG4EqEMFieldWithSpinFunction;
private:
TFile* rootFile;
TTree* rootTree;
static sr1RootOutput* pointerToRoot;
static const Int_t maxNGeantParameters=30;
Double_t GeantParametersD[maxNGeantParameters]; // parameters transfered from GEANT to Root
// 0 ... fieldOption: 0 ... no field, 1 ... uniform, 2 ... gaussian, 3 ... from table
// 1 ... fieldValue: intensity of the magnetic field
// 2 ... minimum of the generated decay time of the muon (in microsecond)
// 3 ... maximum of the generated decay time of the muon (in microsecond)
// 4 ... muon mean life time (in microsecond)
// 5 ... nr. of the last generated event
// 6 ... run number
// 7 ... numberOfGeneratedEvents (i.e. number of the generated events;
// in case of Turtle nr. of events tried);
// Variables common to the whole event:
Int_t runID_t;
Int_t eventID_t;
Double_t weight_t;
Double_t B_t[6];
Double_t muIniPosX_t, muIniPosY_t, muIniPosZ_t;
Double_t muIniMomX_t, muIniMomY_t, muIniMomZ_t;
Double_t muIniPolX_t, muIniPolY_t, muIniPolZ_t;
Int_t muDecayDetID_t;
Double_t muDecayPolX_t, muDecayPolY_t, muDecayPolZ_t;
Double_t muTargetTime_t, muTargetPolX_t, muTargetPolY_t, muTargetPolZ_t;
Double_t muM0Time_t, muM0PolX_t, muM0PolY_t, muM0PolZ_t;
Double_t muM1Time_t, muM1PolX_t, muM1PolY_t, muM1PolZ_t;
Double_t muM2Time_t, muM2PolX_t, muM2PolY_t, muM2PolZ_t;
Double_t muDecayPosX_t, muDecayPosY_t, muDecayPosZ_t;
Double_t muDecayTime_t;
Double_t posIniMomx_t, posIniMomy_t, posIniMomz_t;
// Double_t globalTime_t, ;
// Double_t fieldValue_t;
public:
static const Int_t maxNFieldnNominalValues=10;
private:
Int_t nFieldNomVal;
Double_t fieldNomVal[maxNFieldnNominalValues];
Double_t BxIntegral_t, ByIntegral_t, BzIntegral_t;
Double_t BzIntegral1_t, BzIntegral2_t, BzIntegral3_t;
// Variables for a particle in a given detector within the event
public:
static const Int_t maxNSubTracks=30;
private:
// Int_t nSubTracks;
// // Char_t particleName_t[6];
// Int_t particleID_t[maxNSubTracks];
// G4int trackID_t[maxNSubTracks];
// Double_t edep_t[maxNSubTracks];
// Double_t x_t[maxNSubTracks];
// Double_t y_t[maxNSubTracks];
// Double_t z_t[maxNSubTracks];
// Double_t post_x_t[maxNSubTracks];
// Double_t post_y_t[maxNSubTracks];
// Double_t post_z_t[maxNSubTracks];
// // Char_t logicalVolume_t[13];
// Int_t logicalVolumeID_t[maxNSubTracks];
// Double_t kineticEnergy_t[maxNSubTracks];
// Double_t stepLength_t[maxNSubTracks];
// Int_t nrOfSubsteps_t[maxNSubTracks];
// Variables for the activity inside a given detector
public:
static const Int_t det_nMax=100; // must be by 1 higher than the real number of detector "hits", because
// else the detector nr. 0 is counted (0 is used if no
// SensDetectorMapping correspond to a given logical volume).
private:
G4int det_n;
G4int det_ID[det_nMax];
G4double det_edep[det_nMax];
G4int det_nsteps[det_nMax];
G4double det_length[det_nMax];
G4double det_edep_el[det_nMax];
G4double det_edep_pos[det_nMax];
G4double det_edep_gam[det_nMax];
G4double det_edep_mup[det_nMax];
G4double det_time_start[det_nMax];
G4double det_time_end[det_nMax];
G4double det_x[det_nMax];
G4double det_y[det_nMax];
G4double det_z[det_nMax];
G4double det_kine[det_nMax];
G4double det_VrtxKine[det_nMax];
G4double det_VrtxX[det_nMax];
G4double det_VrtxY[det_nMax];
G4double det_VrtxZ[det_nMax];
G4int det_VrtxVolID[det_nMax];
G4int det_VrtxProcID[det_nMax];
G4int det_VrtxTrackID[det_nMax];
G4int det_VrtxParticleID[det_nMax];
G4double det_VvvKine[det_nMax];
G4double det_VvvX[det_nMax];
G4double det_VvvY[det_nMax];
G4double det_VvvZ[det_nMax];
G4int det_VvvVolID[det_nMax];
G4int det_VvvProcID[det_nMax];
G4int det_VvvTrackID[det_nMax];
G4int det_VvvParticleID[det_nMax];
// G4bool firstStepInVolume_t;
// G4bool lastStepInVolume_t;
public:
static const Int_t save_nMax=2000;
private:
G4int save_n;
G4int save_detID[save_nMax];
G4int save_particleID[save_nMax];
G4double save_x[save_nMax];
G4double save_y[save_nMax];
G4double save_z[save_nMax];
G4double save_px[save_nMax];
G4double save_py[save_nMax];
G4double save_pz[save_nMax];
G4bool boolIsAnySpecialSaveVolumeDefined;
std::map<std::string,int> SensDetectorMapping;
std::map<std::string,int> ProcessIDMapping;
};
//G4int sr1RootOutput::maxNSubTracks=30;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,57 @@
#ifndef sr1TabulatedElementField2D_h
#define sr1TabulatedElementField2D_h 1
#include "globals.hh"
////#include "G4MagneticField.hh"
#include "F04ElementField.hh"
#include "F04GlobalField.hh"
#include "G4ios.hh"
#include <fstream>
#include <vector>
#include <cmath>
class sr1TabulatedElementField2D : public F04ElementField
{
public:
sr1TabulatedElementField2D(const char* filename, G4double fieldValue, G4double lenUnit, G4double fieldNormalisation, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter);
// "lenUnit" is the unit in which the grid coordinates are specified in the table
// "fieldNormalisation" is the normalisation that has to be applied on the field values in the table
// such that the values correspond do 1T nominal value
// "fieldValue" is the field value (in T) that is required (i.e. values normalised to 1T will be
// multiplied by this value).
/// Destructor.
virtual ~sr1TabulatedElementField2D() {}
/// addFieldValue() adds the field for this solenoid into field[].
/// point[] is in global coordinates.
void addFieldValue( const G4double Point[4], G4double* field) const;
G4double GetNominalFieldValue();
void SetNominalFieldValue(G4double newFieldValue);
// getWidth(), getHeight(), getLength(), return the dimensions of the field
// (used to define the boundary of the field)
virtual G4double getWidth() { return 2*dx; } // x coordinate
virtual G4double getHeight() { return 2*dx; } // y coordinate
virtual G4double getLength() { return 2*dz; } // z coordinate
private:
// Storage space for the table
std::vector< std::vector< double > > xField;
std::vector< std::vector< double > > zField;
// The dimensions of the table
int nx,nz;
// The physical limits of the defined region
double minimumx, maximumx, minimumz, maximumz;
// The physical extent of the defined region
double dx, dz;
double ffieldValue;
void Invert(const char* indexToInvert);
};
#endif

View File

@ -0,0 +1,57 @@
#ifndef sr1TabulatedElementField3D_h
#define sr1TabulatedElementField3D_h 1
#include "globals.hh"
#include "F04ElementField.hh"
#include "F04GlobalField.hh"
#include "G4ios.hh"
#include <fstream>
#include <vector>
#include <cmath>
class sr1TabulatedElementField3D : public F04ElementField
{
public:
sr1TabulatedElementField3D(const char* filename, G4double fieldValue, G4double lenUnit, G4double fieldNormalisation, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter);
// "lenUnit" is the unit in which the grid coordinates are specified in the table
// "fieldNormalisation" is the normalisation that has to be applied on the field values in the table
// such that the values correspond do 1T nominal value
// "fieldValue" is the field value (in T) that is required (i.e. values normalised to 1T will be
// multiplied by this value).
/// Destructor.
virtual ~sr1TabulatedElementField3D() {}
/// addFieldValue() adds the field for this solenoid into field[].
/// point[] is in global coordinates.
void addFieldValue( const G4double Point[4], G4double* field) const;
G4double GetNominalFieldValue();
void SetNominalFieldValue(G4double newFieldValue);
// getWidth(), getHeight(), getLength(), return the dimensions of the field
// (used to define the boundary of the field)
virtual G4double getWidth() { return dx; } // x coordinate
virtual G4double getHeight() { return dy; } // y coordinate
virtual G4double getLength() { return dz; } // z coordinate
private:
// Storage space for the table
std::vector< std::vector< std::vector< double > > > xField;
std::vector< std::vector< std::vector< double > > > yField;
std::vector< std::vector< std::vector< double > > > zField;
// The dimensions of the table
int nx,ny,nz;
// The physical limits of the defined region
double minimumx, maximumx, minimumy, maximumy, minimumz, maximumz;
// The physical extent of the defined region
double dx, dy, dz;
double ffieldValue;
void Invert(const char* indexToInvert);
};
#endif

View File

@ -0,0 +1,52 @@
#include "globals.hh"
#include "G4MagneticField.hh"
#include "G4ios.hh"
//cks For the special case of muon decay:
//#include "G4EventManager.hh"
//#include "G4RunManagerKernel.hh"
//csk
#include <fstream>
#include <vector>
#include <cmath>
class sr1TabulatedField2D
#ifndef STANDALONE
: public G4MagneticField
#endif
{
// Storage space for the table
std::vector< std::vector< double > > xField;
std::vector< std::vector< double > > zField;
// The dimensions of the table
int nx,nz;
// The physical limits of the defined region
double minx, maxx, minz, maxz;
// The physical extent of the defined region
double dx, dz;
double ffieldValue;
bool invertX, invertZ;
double positionOffset[4];
static sr1TabulatedField2D* pointerToTabulatedField2D;
public:
static sr1TabulatedField2D* GetInstance();
sr1TabulatedField2D(const char* filename, double fieldValue, double lenUnit, double fieldNormalisation );
// "lenUnit" is the unit in which the grid coordinates are specified in the table
// "fieldNormalisation" is the normalisation that has to be applied on the field values in the table
// such that the values correspond do 1T nominal value
// "fieldValue" is the field value (in T) that is required (i.e. values normalised to 1T will be
// multiplied by this value).
void GetFieldValue( const double Point[4],
double *Bfield ) const;
G4double GetFieldSetValue();
void SetFieldValue(double newFieldValue);
void SetPositionOffset(double offset[4]) { positionOffset[0]=offset[0]; positionOffset[1]=offset[1];
positionOffset[2]=offset[2]; positionOffset[3]=offset[3];}
};

View File

@ -0,0 +1,46 @@
#include "globals.hh"
#include "G4MagneticField.hh"
#include "G4ios.hh"
#include <fstream>
#include <vector>
#include <cmath>
using namespace std;
class sr1TabulatedField3D
#ifndef STANDALONE
: public G4MagneticField
#endif
{
// Storage space for the table
vector< vector< vector< double > > > xField;
vector< vector< vector< double > > > yField;
vector< vector< vector< double > > > zField;
// The dimensions of the table
int nx,ny,nz;
// The physical limits of the defined region
double minx, maxx, miny, maxy, minz, maxz;
// The physical extent of the defined region
double dx, dy, dz;
double ffieldValue;
bool invertX, invertY, invertZ;
double positionOffset[4];
static sr1TabulatedField3D* pointerToTabulatedField3D;
public:
static sr1TabulatedField3D* GetInstance();
sr1TabulatedField3D(const char* filename, double fieldValue );
void GetFieldValue( const double Point[4],
double *Bfield ) const;
G4double GetFieldSetValue();
void SetFieldValue(double newFieldValue);
void SetPositionOffset(double offset[4]) { positionOffset[0]=offset[0]; positionOffset[1]=offset[1];
positionOffset[2]=offset[2]; positionOffset[3]=offset[3];}
};

View File

@ -0,0 +1,72 @@
#ifndef LEM3AXIAL2DELFIELD_H
#define LEM3AXIAL2DELFIELD_H 1
#include "F04ElementField.hh"
#include "F04GlobalField.hh" /// ATTENTION: USE GENERAL EM GLOBAL AND NOT MAGN. FIELD ONLY
///#include "G4MagneticField.hh"
///#include "G4ElectricField.hh"
#include "globals.hh"
#include "G4ios.hh"
#include <fstream>
#include <vector>
#include <cmath>
class sr1Axial2DElField : public F04ElementField ///G4ElectricField
{
//! Contructor from a single field map
// sr1ElectricField(G4double fieldval,G4String file,G4String map_length_unit,
//G4double Offset, G4double nx, G4double ny, G4double nz);
///sr1Axial2DElField(const G4String filename, double fieldValue, double lenUnit, double fieldNormalisation, double offset);
public:
// Class constructor for 2D axial field map (x, z, Er, Ez)
sr1Axial2DElField(const char* filename, G4double fieldValue, G4double lenUnit, G4double fieldNormalisation, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter);
// "lenUnit" is the unit in which the grid coordinates are specified in the table
// "fieldNormalisation" is the normalisation that has to be applied on the field values in the table
// such that when applying V_L3 = 1 kV the E values coincide with those in the table
// "fieldValue" is the field value (in kV) set by the user (i.e. values normalised to 1 kV will be
// multiplied by this value).
// Virtual destructor
virtual ~sr1Axial2DElField() {};
// addFieldValue() adds the field for THIS particular map into field[].
// point[] is expressed in GLOBAL coordinates.
void addFieldValue(const G4double point[4], G4double* field) const;
// Usual Set and Get functions
G4double GetNominalFieldValue();
void SetNominalFieldValue(G4double newFieldValue);
// getWidth(), getHeight(), getLength(), return the dimensions of the field
// (used to define the boundary of the field)
virtual G4double getWidth() { return 2*dr; } // x coordinate
virtual G4double getHeight() { return 2*dr; } // y coordinate
virtual G4double getLength() { return 2*dz; } // z coordinate
///void GetFieldValue(const double Point[4], double *Efield) const;
///void SetFieldValue(double newFieldValue);
/// G4double GetFieldSetValue();
private:
// Storage space for the table
std::vector < std::vector < double > > rField;
std::vector < std::vector < double > > zField;
// The dimensions of the table
int nr, nz;
// The physical limits of the defined region and the global offset
double minr, maxr, minz, maxz;
// The physical extent of the defined region
double dr, dz;
double ffieldValue; ///, zOffset; included in log_vol offset!
///bool invertR, invertZ; // substituted by the Invert function
// Utility function for inverting field map
void Invert(const char* indexToInvert);
};
#endif

View File

@ -0,0 +1,81 @@
#ifndef sr1DetectorConstruction_h
#define sr1DetectorConstruction_h 1
#include "globals.hh"
#include "G4VUserDetectorConstruction.hh"
#include "G4ThreeVector.hh"
#include "G4RotationMatrix.hh"
#include "G4FieldManager.hh"
#include <map>
class G4Tubs;
class G4Box;
class G4Cons;
class G4Trd;
class G4LogicalVolume;
class G4VPhysicalVolume;
class G4Material;
class sr1DetectorMessenger;
//class sr1TrackerSD;
//class sr1ShieldSD;
//class sr1IForwardSD;
//class sr1IBackwardSD;
class sr1ScintSD;
//class sr1UniformField; // Added by TS to implement uniform box field according to Gumplinger
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1DetectorConstruction : public G4VUserDetectorConstruction
{
public:
sr1DetectorConstruction();
~sr1DetectorConstruction();
public:
G4VPhysicalVolume* Construct();
void UpdateGeometry();
///ALL THESE ARE OLD FIELD SETTING METHODS. USE THAT OF GUMPLINGER INSTEAD! TS.
void SetMagField(const char* fieldTableType, const char* inputFileName, G4double fieldValue);
void SetUniformMagField(G4double);
void SetGaussianMagField(G4ThreeVector);
///void SetUniformElField(G4double); // Uniform Electric Field. TS
void SetInputParameterFileName(G4String fileName) {parameterFileName=fileName;};
void ReportGeometryProblem(char myString[501]);
void ReportProblemInStearingFile(char* myString); //!Changed -added
G4Material* CharToMaterial(char myString[100]);
G4LogicalVolume* FindLogicalVolume(G4String LogicalVolumeName);
void SetColourOfLogicalVolume(G4LogicalVolume* pLogVol,char* colour);
G4bool CheckIfStringContainsSubstring(char* string, char* substring); //!Changed -added
private:
G4String parameterFileName; // name of the file with the geometry parameters
G4bool checkOverlap; // parameter to check ovelaping volumes
G4double largestAcceptableStep; // parameter defining largest step in the magnetic field
//G4Material* TargetMater;// pointer to the target material
//G4Material* VacMater; // pointer to the target material
//G4Material* DetMater; // pointer to the target material
//G4Material* Al; // pointer to the target material
//G4Material* Pb; // pointer to the target material
//G4Material* AirMater; // pointer to the target material
//G4Material* Vacuum; // pointer to vacuum material
sr1ScintSD* aScintSD;
sr1DetectorMessenger* detectorMessenger; // pointer to the Messenger
std::map<std::string,G4RotationMatrix*> pointerToRotationMatrix;
std::map<std::string,G4FieldManager*> pointerToField;
private:
void DefineMaterials();
};
#endif

View File

@ -0,0 +1,57 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1DetectorMessenger_h
#define sr1DetectorMessenger_h 1
#include "globals.hh"
#include "G4UImessenger.hh"
class sr1DetectorConstruction;
class G4UIdirectory;
class G4UIcmdWithAString;
class G4UIcmdWithADoubleAndUnit;
class G4UIcmdWithAnInteger;
class G4UIcmdWithoutParameter;
class G4UIcmdWith3Vector;
class G4UIcmdWith3VectorAndUnit;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1DetectorMessenger: public G4UImessenger
{
public:
sr1DetectorMessenger(sr1DetectorConstruction*);
~sr1DetectorMessenger();
void SetNewValue(G4UIcommand*, G4String);
private:
sr1DetectorConstruction* myDetector;
G4UIdirectory* sr1Dir;
G4UIdirectory* detDir;
G4UIdirectory* runDir;
G4UIcmdWithAString* CommandCmd;
G4UIcmdWithAnInteger* RunIDSetCmd;
G4UIcmdWithAnInteger* RandomOptionCmd;
G4UIcmdWithAnInteger* HowOftenToPrintEventCmd;
// G4UIcmdWithAString* WhichProcessesCmd;
G4UIcmdWithoutParameter* UpdateCmd;
// G4UIcmdWithADoubleAndUnit* FieldCmd;
G4UIcmdWithADoubleAndUnit* UFieldCmd;
/// G4UIcmdWithADoubleAndUnit* UEFieldCmd; //Uniform Electric Field. TS
G4UIcmdWith3Vector* GFieldCmd;
public:
// cks: The two variables used for the random number initialisation each event (if required)
// long myEventNr;
// static G4bool setRandomNrSeedAccordingEventNr;
// void IncrementMyEventNr() {myEventNr++};
// long GetMyEventNr() {return myEventNr};
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,31 @@
#ifndef sr1ErrorMessage_h
#define sr1ErrorMessage_h 1
#include <map>
#include "globals.hh"
enum SEVERITY {INFO, WARNING, SERIOUS, FATAL};
typedef struct
{
SEVERITY mesSeverity;
int nTimes;
} ErrorStruct;
class sr1ErrorMessage {
public:
// enum SEVERITY {INFO, WARNING, SERIOUS, FATAL};
sr1ErrorMessage();
~sr1ErrorMessage();
static sr1ErrorMessage* GetInstance();
void sr1Error(SEVERITY severity, G4String message, G4bool silent);
void PrintErrorSummary();
private:
static sr1ErrorMessage* pointerToErrors;
G4int nErrors;
// std::map<G4String,int> ErrorMapping;
std::map<G4String,ErrorStruct> ErrorMapping;
std::map<SEVERITY,G4String> severityWord;
};
#endif

View File

@ -0,0 +1,67 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1EventAction_h
#define sr1EventAction_h 1
#include "globals.hh"
#include "G4UserEventAction.hh"
#include <vector>
using namespace std;
class G4Timer;
class G4Event;
class sr1MagneticField;
class G4ElectricField; // Unif. el. field. TS
class sr1TabulatedField3D;
class sr1TabulatedField2D;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1EventAction : public G4UserEventAction
{
public:
sr1EventAction();
~sr1EventAction();
public:
void BeginOfEventAction(const G4Event*);
void EndOfEventAction(const G4Event*);
static sr1EventAction* GetInstance();
private:
// pointer to this class
static sr1EventAction* pointer;
//
G4Timer* timer;
static vector<int> * pointerToSeedVector;
// Variables for the time-dependent magnetic field
G4bool timeDependentField;
G4double fieldValueStart, fieldValueEnd, fieldStep, lastFieldValue;
G4int fieldNrOfSteps;
G4int maxEventNr;
sr1MagneticField* pointerToMusrUniformField;
G4ElectricField* pointerToMusrUniformEField; // Pointer to uniform electric field. TS
sr1TabulatedField3D* pointerToTabulatedField3D;
sr1TabulatedField2D* pointerToTabulatedField2D;
G4int latestEventNr;
public:
static G4bool setRandomNrSeedAccordingEventNr;
static G4bool setRandomNrSeedFromFile;
static G4int nHowOftenToPrintEvent;
static vector<int> * GetPointerToSeedVector();
// void setMyEventNr(long n) {myEventNr=n;};
void SetTimeDependentField(G4bool setFieldToBeTimeDependend, G4double initialField,
G4double finalField, G4int nrOfSteps);
void SetNumberOfEventsInThisRun(G4int nrOfEventsInThisRun) {maxEventNr=nrOfEventsInThisRun;};
void SetPointerToMusrUniformField(sr1MagneticField* pointer) {pointerToMusrUniformField=pointer;};
void SetPointerToMusrUniformEField(G4ElectricField* pointer) {pointerToMusrUniformEField=pointer;}; // Unif. El. field. TS
void SetPointerToTabulatedField3D(sr1TabulatedField3D* pointer) {pointerToTabulatedField3D=pointer;};
void SetPointerToTabulatedField2D(sr1TabulatedField2D* pointer) {pointerToTabulatedField2D=pointer;};
G4int GetLatestEventNr(){return latestEventNr;};
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,16 @@
#include "globals.hh"
#include "G4MagneticField.hh"
class sr1GaussianField
#ifndef STANDALONE
: public G4MagneticField
#endif
{
private:
G4double ffieldValue;
G4double fieldMagnitude,RMS;
public:
sr1GaussianField(double fieldValue, double sigma);
void GetFieldValue( const double point[4], double *Bfield ) const;
G4double GetFieldSetValue();
};

View File

@ -0,0 +1,38 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1MagneticField_H
#define sr1MagneticField_H
#include "G4UniformMagField.hh"
class G4FieldManager;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1MagneticField: public G4UniformMagField
{
public:
sr1MagneticField(G4ThreeVector); // The value of the field
sr1MagneticField(); // A zero field
~sr1MagneticField();
//Set the field (fieldValue,0,0)
void SetFieldValue(G4double fieldValue);
void SetFieldValue(G4ThreeVector fieldVector);
G4ThreeVector GetConstantFieldValue();
protected:
// Find the global Field Manager
G4FieldManager* GetGlobalFieldManager(); // static
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif
G4bool CheckOverlaps(G4int res=1000, G4double tol=0., G4bool verbose=true);

View File

@ -0,0 +1,75 @@
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
// Muonium Formation according to yield.cc function (through GetYields method).
// Id : sr1MuFormation.hh, v 1.4
// Author: Taofiq PARAISO, T. Shiroka
// Date : 2007-12
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#ifndef sr1MuFormation_h
#define sr1MuFormation_h 1
#include "G4VDiscreteProcess.hh"
#include "G4ParticleTable.hh"
#include "yields.h"
/*! sr1MuFormation class defines the muonium formation process in the Carbon foil
* according to yields from Gonin's paper Sci. Rev. Instrum. 65(3), 648-652 (1994).
* \image html yields3.gif The muonium formation yields.
* The main parameters are the foil thickness and muon energy. For a given energy,
* a corresponding proportion of the muons will be converted into Muonium.
* Concretely, the muon is eliminated and replaced by a Muonium with identical
* properties, including time, energy, momentum, position etc.
*
* The process is executed at the END of a step, i.e. the muon is converted into
* Muonium AFTER flying through the Carbon foil (see also yields.h). */
class sr1MuFormation : public G4VDiscreteProcess
{
public:
sr1MuFormation(const G4String& name = "MuFormation", // process description
G4ProcessType aType = fElectromagnetic);
~sr1MuFormation();
//! - Main method. Muonium formation process is executed at the END of a step. */
G4VParticleChange* PostStepDoIt(
const G4Track&,
const G4Step&);
G4double GetMeanFreePath(const G4Track& aTrack,
G4double previousStepSize,
G4ForceCondition* condition);
//! Condition for process application (step Object).
G4bool CheckCondition(const G4Step& aStep);
//! Condition for process application (step Pointer).
G4bool CheckCondition(const G4Step* aStep);
G4String p_name;
G4bool condition;
void GetDatas( const G4Step* aStep);
// model parameters
G4ParticleTable* particleTable;
G4ParticleDefinition* particle;
Yields Gonin;
G4double yvector[3];
G4double rnd;
G4DynamicParticle *DP;
//! The particle change object.
G4VParticleChange fParticleChange;
void PrepareSecondary(const G4Track&);
G4Track* aSecondary;
void InitializeSecondaries(const G4Track&);
};
#endif

View File

@ -0,0 +1,52 @@
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
// Muonium "Scattering"
// Id : sr1MuScatter.hh, v 1.4
// Author: Taofiq PARAISO, T. Shiroka
// Date : 2007-12
// Notes : Simplified model for Mu scattering. Spin effects have been excluded.
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
/*!
* sr1MuScatter class defines the Muonium scattering process. It implements a very
* basic model which assumes Muonium looses its electron as soon as it enters any
* material (except for vacuum and CFoil). The class has only a PostStepDoIt method.
* The in-flight Muonium spin precession has been supressed. */
#ifndef sr1MuScatter_h
#define sr1MuScatter_h 1
#include "G4VDiscreteProcess.hh"
class sr1MuScatter : public G4VDiscreteProcess
{
public:
sr1MuScatter(const G4String& name="MuScatt", // process description
G4ProcessType aType = fGeneral);
~sr1MuScatter();
//! \mm The actions are taken at the end of the step.
G4VParticleChange* PostStepDoIt(const G4Track&,
const G4Step&);
G4double GetMeanFreePath(const G4Track& aTrack,
G4double previousStepSize,
G4ForceCondition* condition);
//! The condition for applying the process.
G4bool CheckCondition(const G4Step& aStep);
G4bool condition;
G4double itime, gtime, ftime,deltatime;
G4String p_name;
G4DynamicParticle *DP;
G4ParticleChange fParticleChange;
void PrepareSecondary(const G4Track&);
G4Track* aSecondary;
void InitializeSecondaries(const G4Track&);
};
#endif

View File

@ -0,0 +1,72 @@
//
// ********************************************************************
// * 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: sr1Muonium.hh,v 1.10 2006/06/29 19:20:21 gunter Exp $
// GEANT4 tag $Name: geant4-09-00 $
//
//
// ------------------------------------------------------------
// GEANT 4 class header file
//
// History: first implementation, based on object model of
// 4-th April 1996, G.Cosmo
// ****************************************************************
// New implementation as a utility class M.Asai, 26 July 2004
// ----------------------------------------------------------------
#ifndef sr1Muonium_h
#define sr1Muonium_h 1
#include "globals.hh"
#include "G4ios.hh"
#include "G4ParticleDefinition.hh"
// ######################################################################
// ### MUONIUM ###
// ######################################################################
class sr1Muonium : public G4ParticleDefinition
{
private:
static sr1Muonium* theInstance;
sr1Muonium(){}
~sr1Muonium(){}
public:
static sr1Muonium* Definition();
static sr1Muonium* MuoniumDefinition();
static sr1Muonium* Muonium();
};
#endif

View File

@ -0,0 +1,47 @@
#ifndef sr1Parameters_h
#define sr1Parameters_h 1
#include "globals.hh"
class sr1Parameters {
public:
///sr1Parameters();
sr1Parameters(G4String steeringFileName); // ADDED by TS - overloaded constructor
~sr1Parameters();
static sr1Parameters* GetInstance();
void SetMyTypeOfProcesses(G4String string) {typeOfProcesses=string;};
G4String GetMyTypeOfProcesses() {return typeOfProcesses;};
static G4bool storeOnlyEventsWithHits; // Variable specifying whether to store interesting
// or all events into the ROOT tree. (default = true)
static G4double signalSeparationTime; // Minimim time separation between two subsequent signal
static G4bool storeOnlyTheFirstTimeHit; // If true, only the hit that happened first will be
// stored, anything else will be ignored
// (useful in some special cases, not for a routine simulation)
static G4bool includeMuoniumProcesses; // If true, includes Muonium formation and all
// other Mu-related processes in the simulation
//ADDED by TS
static G4bool boolG4GeneralParticleSource;//If true, G4GeneralParticleSource will be initialised
//instead of G4ParticleGun - for simulating radioactive sources
static G4bool field_DecayWithSpin; // If true, then the routine for calculating the magnetic
// field will use a more precise argument.
// This variable is set to "true" by the SteppinAction
// and reset to "false" in the GetFieldValue.
// It is being changed on step by step basis.
static G4int nrOfEventsToBeGenerated; // Nr of events to be simulated in this run (set by /run/beamOn command)
private:
static sr1Parameters* pointerToParameters;
G4String typeOfProcesses; // Variable defining what kind of Physics processes to call:
// - Standard EM
// - LowEnergy (default)
// - Penelope
// - Coulomb
};
#endif

View File

@ -0,0 +1,48 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1PhysicsList_h
#define sr1PhysicsList_h 1
#include "G4VUserPhysicsList.hh"
#include "globals.hh"
//cks Added to have Geant default muon decay with spin
#include "G4DecayWithSpin.hh"
//#include "sr1DecayWithSpin.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1PhysicsList: public G4VUserPhysicsList
{
public:
sr1PhysicsList();
~sr1PhysicsList();
protected:
// Construct particle and physics
void ConstructParticle();
void ConstructProcess();
void SetCuts();
protected:
// these methods Construct particles
void ConstructBosons();
void ConstructLeptons();
void ConstructMesons();
void ConstructBaryons();
protected:
// these methods Construct physics processes and register them
void ConstructGeneral();
void ConstructEM();
// private:
// char myProcesses[100];
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,69 @@
#ifndef sr1PrimaryGeneratorAction_h
#define sr1PrimaryGeneratorAction_h 1
#include "G4VUserPrimaryGeneratorAction.hh"
#include "globals.hh"
#include "Randomize.hh"
#include "G4ThreeVector.hh"
#include <stdio.h>
//cksdel #include "sr1ParticleGun.hh"
class G4ParticleGun;
class G4Event;
class sr1DetectorConstruction;
class sr1PrimaryGeneratorMessenger;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
class sr1PrimaryGeneratorAction : public G4VUserPrimaryGeneratorAction
{
public:
sr1PrimaryGeneratorAction(sr1DetectorConstruction*);
~sr1PrimaryGeneratorAction();
public:
void GeneratePrimaries(G4Event*);
void SetRndmFlag(G4String val) {rndmFlag = val;}
void Setvertex(G4ThreeVector v) {x0=v[0]; y0=v[1]; z0=v[2];}
void SetvertexSigma(G4ThreeVector v) {xSigma=v[0]; ySigma=v[1]; zSigma=v[2];}
void SetvertexBoundary(G4ThreeVector v) {rMaxAllowed=v[0]; zMinAllowed=v[1]; zMaxAllowed=v[2];}
void SetEnergy(G4double val) {p0=std::sqrt(val*val + 2*mu_mass*val);} // {E0=val;}
void SetMomentum(G4double val) {p0=val;}
void SetMomentumSmearing(G4double val) {pSigma=val;}
void SetMomentumBoundary(G4ThreeVector v){pMinAllowed=v[0]; pMaxAllowed=v[1];}
void SetTilt(G4ThreeVector v) {xangle0=v[0]; yangle0=v[1];}
void SetSigmaTilt(G4ThreeVector v) {xangleSigma=v[0]; yangleSigma=v[1];}
void SetPitch(G4double val) {pitch=val;}
void SetInitialMuonPolariz(G4ThreeVector vIniPol);
void SetMuonDecayTimeLimits(G4ThreeVector decayTimeLimits);
void SetTurtleInput(G4String turtleFileName);
static G4String GetPrimaryName();
private:
G4ParticleGun* particleGun; // Pointer a to G4 service class
sr1DetectorConstruction* sr1Detector; // Pointer to the geometry
sr1PrimaryGeneratorMessenger* gunMessenger; // Messenger of this class
G4String rndmFlag; // Flag for a random impact point
G4double x0, y0, z0, xSigma, ySigma, zSigma, rMaxAllowed, zMinAllowed, zMaxAllowed;
G4double E0, p0, pSigma, pMinAllowed, pMaxAllowed;
G4double xangle0, yangle0, xangleSigma, yangleSigma, pitch;
G4bool UnpolarisedMuonBeam;
G4double xPolarisIni, yPolarisIni, zPolarisIni;
G4double muonDecayTimeMin;
G4double muonDecayTimeMax;
G4double muonMeanLife;
G4double mu_mass;
// For Turtle input
FILE* fTurtleFile;
G4bool takeMuonsFromTurtleFile;
static G4String thePrimaryParticleName;
public:
G4double decaytime;
};
#endif

View File

@ -0,0 +1,41 @@
#ifndef sr1PrimaryGeneratorMessenger_h
#define sr1PrimaryGeneratorMessenger_h 1
#include "G4UImessenger.hh"
#include "globals.hh"
class sr1PrimaryGeneratorAction;
class G4UIcmdWithAString;
class G4UIcmdWithADoubleAndUnit;
class G4UIcmdWithADouble;
class G4UIcmdWithAnInteger;
class G4UIcmdWith3VectorAndUnit;
class G4UIcmdWith3Vector;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
class sr1PrimaryGeneratorMessenger: public G4UImessenger
{
public:
sr1PrimaryGeneratorMessenger(sr1PrimaryGeneratorAction* sr1Gun);
~sr1PrimaryGeneratorMessenger();
void SetNewValue(G4UIcommand*, G4String newValue);
private:
sr1PrimaryGeneratorAction* sr1Action;
G4UIcmdWith3VectorAndUnit* setvertexCmd;
G4UIcmdWith3VectorAndUnit* setvertexSigmaCmd;
G4UIcmdWith3VectorAndUnit* setvertexBoundaryCmd;
G4UIcmdWithADoubleAndUnit* setEnergyCmd;
G4UIcmdWithADoubleAndUnit* setMomentumCmd;
G4UIcmdWithADoubleAndUnit* setMomentumSmearingCmd;
G4UIcmdWith3VectorAndUnit* setMomentumBoundaryCmd;
G4UIcmdWith3VectorAndUnit* setTiltAngleCmd;
G4UIcmdWith3VectorAndUnit* setSigmaTiltAngleCmd;
G4UIcmdWithADoubleAndUnit* setPitchCmd;
G4UIcmdWith3Vector* setMuonPolarizCmd;
G4UIcmdWith3VectorAndUnit* setMuonDecayTimeCmd;
G4UIcmdWithAString* setTurtleCmd;
};
#endif

View File

@ -0,0 +1,286 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1RootOutput_h
#define sr1RootOutput_h 1
//#include "G4UserRunAction.hh"
#include "globals.hh"
#include "G4ThreeVector.hh"
// ROOT
#include "TFile.h"
#include "TTree.h"
#include "TH1.h"
#include "TH2.h"
#include "TVectorD.h"
//
#include <map>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1RootOutput {
public:
sr1RootOutput();
~sr1RootOutput();
static sr1RootOutput* GetRootInstance();
public:
void BeginOfRunAction();
void EndOfRunAction();
void FillEvent();
void ClearAllRootVariables();
// void SetSensitiveDetectorMapping(std::string logivol, int volumeID);
void SetVolumeIDMapping(std::string logivol, int volumeID);
G4int ConvertVolumeToID(std::string logivol);
void SetSpecialSaveVolumeDefined() {boolIsAnySpecialSaveVolumeDefined=true;};
// Getting variables (just for debugging)
G4double GetDecayPositionZ() {return muDecayPosZ_t;};
G4double GetDecayTime() {return muDecayTime_t*microsecond;};
G4double GetTimeInTarget() {return muTargetTime_t*microsecond;};
// Setting variables common to the whole event:
void SetRunID (G4int id) {runID_t = id;};
void SetEventID (G4int id) {eventID_t = id;};
void SetDecayDetectorID (std::string detectorName) {muDecayDetID_t = SensDetectorMapping[detectorName];};
void SetBField (G4double F[6]) {B_t[0]=F[0]/tesla; B_t[1]=F[1]/tesla; B_t[2]=F[2]/tesla;
B_t[3]=F[3]/tesla; B_t[4]=F[4]/tesla; B_t[5]=F[5]/tesla;};
void SetDecayPolarisation (G4ThreeVector pol) {muDecayPolX_t=pol.x(); muDecayPolY_t=pol.y(); muDecayPolZ_t=pol.z();};
void SetDecayPosition (G4ThreeVector pos) {muDecayPosX_t=pos.x()/mm; muDecayPosY_t=pos.y()/mm;
muDecayPosZ_t=pos.z()/mm;};
void SetGlobTime (G4double gt) {globalTime_t = gt/microsecond;};
void SetDetectorInfo (G4int nDetectors, G4int ID, G4double edep, G4double edep_el, G4double edep_pos,
G4double edep_gam, G4double edep_mup,G4int nsteps, G4double length, G4double t1,
G4double t2, G4double x, G4double y, G4double z) {
if ((nDetectors<0)||(nDetectors>=(det_nMax-1))) {
G4cout<<"SERIOUS ERROR! sr1RootOutput.hh: nDetectors="<<nDetectors<<
" is larger than det_nMax="<<det_nMax<<G4endl;
return;
}
else {
det_n=nDetectors+1; det_ID[nDetectors]=ID; det_edep[nDetectors]=edep/MeV;
det_edep_el[nDetectors]=edep_el/MeV; det_edep_pos[nDetectors]=edep_pos/MeV;
det_edep_gam[nDetectors]=edep_gam/MeV; det_edep_mup[nDetectors]=edep_mup/MeV;
det_nsteps[nDetectors]=nsteps; det_length[nDetectors]=length/mm;
det_time_start[nDetectors]=t1/microsecond; det_time_end[nDetectors]=t2/microsecond;
det_x[nDetectors]=x/mm;det_y[nDetectors]=y/mm;det_z[nDetectors]=z/mm;
// G4cout << "Saved to root: eventID="<<eventID_t<<"; det_ID="<<det_ID[nDetectors]
// <<"; det_edep="<<det_edep[nDetectors]<<G4endl;
}
//G4cout << "eventID="<<eventID_t<<"; det_n="<<det_n<<"; det_ID="<<det_ID[nDetectors]<<"; "
// << "Deposited E (el, pos, gam, mu)="<<det_edep_el[nDetectors]<<", "
// << det_edep_pos[nDetectors]<<", "<< det_edep_gam[nDetectors]<<", "
// << det_edep_mup[nDetectors]<<G4endl;
//G4cout << " det_time_start="<<det_time_start[nDetectors]
// << " det_time_end="<<det_time_end[nDetectors] << G4endl;
};
void SetSaveDetectorInfo (G4int ID, G4int particleID, G4double x, G4double y, G4double z,
G4double px, G4double py, G4double pz) ;
void SetInitialMuonParameters(G4double x, G4double y, G4double z, G4double px, G4double py, G4double pz,
G4double xpolaris, G4double ypolaris, G4double zpolaris) {
muIniPosX_t=x; muIniPosY_t=y; muIniPosZ_t=z;
muIniMomX_t=px; muIniMomY_t=py; muIniMomZ_t=pz;
muIniPolX_t=xpolaris; muIniPolY_t=ypolaris; muIniPolZ_t=zpolaris;
}
// void SetSubtrackInfo (G4int iSubtrack, G4int partID, G4int trID, G4int volID, G4double E,
// G4double xx, G4double yy, G4double zz, G4double xxPost, G4double yyPost, G4double zzPost,
// G4double Eki, G4double stepL, G4int nrOfSubst) {
// if ((iSubtrack<0)||(iSubtrack>=maxNSubTracks)) {
// G4cout<<"SERIOUS ERROR! sr1RootOutput.hh: iSubtrack="<<iSubtrack<<
// " is larger than maxNSubTracks="<<maxNSubTracks<<G4endl;
// return;
// }
// else {
// nSubTracks=iSubtrack+1;
// particleID_t[iSubtrack]=partID;
// trackID_t[iSubtrack]=trID;
// logicalVolumeID_t[iSubtrack]=volID;
// edep_t[iSubtrack]=E/MeV;
// x_t[iSubtrack]=xx/mm;
// y_t[iSubtrack]=yy/mm;
// z_t[iSubtrack]=zz/mm;
// post_x_t[iSubtrack]=xxPost/mm;
// post_y_t[iSubtrack]=yyPost/mm;
// post_z_t[iSubtrack]=zzPost/mm;
// kineticEnergy_t[iSubtrack]=Eki/MeV;
// stepLength_t[iSubtrack]=stepL/mm;
// nrOfSubsteps_t[iSubtrack]=nrOfSubst;
// }
// };
void SetPosInTarget(G4ThreeVector pos) {muTargetPosX_t=pos.x(); muTargetPosY_t=pos.y(); muTargetPosZ_t=pos.z();};
void SetPolInTarget(G4ThreeVector pol) {muTargetPolX_t=pol.x(); muTargetPolY_t=pol.y(); muTargetPolZ_t=pol.z();};
void SetTimeInTarget(G4double time) {muTargetTime_t = time/microsecond;};
void SetInitialPositronMomentum(G4ThreeVector mom) {posIniMomx_t=mom.x(); posIniMomy_t=mom.y(); posIniMomz_t=mom.z();};
void SetDecayTime(G4double time) {muDecayTime_t=time/microsecond;};
void SetFieldValue(G4double value) {fieldValue_t=value/tesla;};
void SetNrFieldNomVal(G4int n) {nFieldNomVal = n;}
void SetFieldNomVal(G4int i, G4double value);
G4int GetNrOfVolumes() {return det_nMax;}
void StoreGeantParameter(Int_t i, Double_t value) {
if (i<maxNGeantParameters) { GeantParametersD[i]=value; }
else {G4cout<<"sr1RootOutput.hh::StoreGeantParameter: index="<<i<<" out of range"
<<" (maxNGeantParameters=" <<maxNGeantParameters<<")"<<G4endl;}
};
TH2F *htest1, *htest2;
TH1F *htest3, *htest4, *htest5, *htest6, *htest7, *htest8;
public:
static G4bool store_runID;
static G4bool store_eventID;
static G4bool store_BFieldAtDecay;
static G4bool store_muIniPosX;
static G4bool store_muIniPosY;
static G4bool store_muIniPosZ;
static G4bool store_muIniMomX;
static G4bool store_muIniMomY;
static G4bool store_muIniMomZ;
static G4bool store_muIniPolX;
static G4bool store_muIniPolY;
static G4bool store_muIniPolZ;
static G4bool store_muDecayDetID;
static G4bool store_muDecayPosX;
static G4bool store_muDecayPosY;
static G4bool store_muDecayPosZ;
static G4bool store_muDecayTime;
static G4bool store_muDecayPolX;
static G4bool store_muDecayPolY;
static G4bool store_muDecayPolZ;
static G4bool store_muTargetTime;
static G4bool store_muTargetPosX;
static G4bool store_muTargetPosY;
static G4bool store_muTargetPosZ;
static G4bool store_muTargetPolX;
static G4bool store_muTargetPolY;
static G4bool store_muTargetPolZ;
static G4bool store_posIniMomX;
static G4bool store_posIniMomY;
static G4bool store_posIniMomZ;
static G4bool store_globalTime;
static G4bool store_fieldValue;
static G4bool store_det_ID;
static G4bool store_det_edep;
static G4bool store_det_edep_el;
static G4bool store_det_edep_pos;
static G4bool store_det_edep_gam;
static G4bool store_det_edep_mup;
static G4bool store_det_nsteps;
static G4bool store_det_length;
static G4bool store_det_start;
static G4bool store_det_end;
static G4bool store_det_x;
static G4bool store_det_y;
static G4bool store_det_z;
static G4bool store_fieldNomVal;
private:
TFile* rootFile;
TTree* rootTree;
static sr1RootOutput* pointerToRoot;
static const Int_t maxNGeantParameters=30;
Double_t GeantParametersD[maxNGeantParameters]; // parameters transfered from GEANT to Root
// 0 ... fieldOption: 0 ... no field, 1 ... uniform, 2 ... gaussian, 3 ... from table
// 1 ... fieldValue: intensity of the magnetic field
// 2 ... minimum of the generated decay time of the muon (in microsecond)
// 3 ... maximum of the generated decay time of the muon (in microsecond)
// 4 ... muon mean life time (in microsecond)
// Variables common to the whole event:
Int_t runID_t;
Int_t eventID_t;
Double_t B_t[6];
Double_t muIniPosX_t, muIniPosY_t, muIniPosZ_t;
Double_t muIniMomX_t, muIniMomY_t, muIniMomZ_t;
Double_t muIniPolX_t, muIniPolY_t, muIniPolZ_t;
Int_t muDecayDetID_t;
Double_t muDecayPolX_t, muDecayPolY_t, muDecayPolZ_t;
Double_t muTargetPosX_t, muTargetPosY_t, muTargetPosZ_t;
Double_t muTargetPolX_t, muTargetPolY_t, muTargetPolZ_t;
Double_t muDecayPosX_t, muDecayPosY_t, muDecayPosZ_t;
Double_t muDecayTime_t;
Double_t posIniMomx_t, posIniMomy_t, posIniMomz_t;
Double_t globalTime_t, muTargetTime_t;
Double_t fieldValue_t;
public:
static const Int_t maxNFieldnNominalValues=30;
private:
Int_t nFieldNomVal;
Double_t fieldNomVal[maxNFieldnNominalValues];
// Variables for a particle in a given detector within the event
public:
static const Int_t maxNSubTracks=30;
private:
// Int_t nSubTracks;
// // Char_t particleName_t[6];
// Int_t particleID_t[maxNSubTracks];
// G4int trackID_t[maxNSubTracks];
// Double_t edep_t[maxNSubTracks];
// Double_t x_t[maxNSubTracks];
// Double_t y_t[maxNSubTracks];
// Double_t z_t[maxNSubTracks];
// Double_t post_x_t[maxNSubTracks];
// Double_t post_y_t[maxNSubTracks];
// Double_t post_z_t[maxNSubTracks];
// // Char_t logicalVolume_t[13];
// Int_t logicalVolumeID_t[maxNSubTracks];
// Double_t kineticEnergy_t[maxNSubTracks];
// Double_t stepLength_t[maxNSubTracks];
// Int_t nrOfSubsteps_t[maxNSubTracks];
// Variables for the activity inside a given detector
public:
static const Int_t det_nMax=100; // must be by 1 higher than the real number of detector "hits", because
// else the detector nr. 0 is counted (0 is used if no
// SensDetectorMapping correspond to a given logical volume).
private:
G4int det_n;
G4int det_ID[det_nMax];
G4double det_edep[det_nMax];
G4int det_nsteps[det_nMax];
G4double det_length[det_nMax];
G4double det_edep_el[det_nMax];
G4double det_edep_pos[det_nMax];
G4double det_edep_gam[det_nMax];
G4double det_edep_mup[det_nMax];
G4double det_time_start[det_nMax];
G4double det_time_end[det_nMax];
G4double det_x[det_nMax];
G4double det_y[det_nMax];
G4double det_z[det_nMax];
// G4bool firstStepInVolume_t;
// G4bool lastStepInVolume_t;
public:
static const Int_t save_nMax=1000;
private:
G4int save_n;
G4int save_detID[save_nMax];
G4int save_particleID[save_nMax];
G4double save_x[save_nMax];
G4double save_y[save_nMax];
G4double save_z[save_nMax];
G4double save_px[save_nMax];
G4double save_py[save_nMax];
G4double save_pz[save_nMax];
G4bool boolIsAnySpecialSaveVolumeDefined;
std::map<std::string,int> SensDetectorMapping;
};
//G4int sr1RootOutput::maxNSubTracks=30;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,282 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1RootOutput_h
#define sr1RootOutput_h 1
//#include "G4UserRunAction.hh"
#include "globals.hh"
#include "G4ThreeVector.hh"
// ROOT
#include "TFile.h"
#include "TTree.h"
#include "TH1.h"
#include "TH2.h"
#include "TVectorD.h"
//
#include <map>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1RootOutput {
public:
sr1RootOutput();
~sr1RootOutput();
static sr1RootOutput* GetRootInstance();
public:
void BeginOfRunAction();
void EndOfRunAction();
void FillEvent();
void ClearAllRootVariables();
// void SetSensitiveDetectorMapping(std::string logivol, int volumeID);
void SetVolumeIDMapping(std::string logivol, int volumeID);
G4int ConvertVolumeToID(std::string logivol);
void SetSpecialSaveVolumeDefined() {boolIsAnySpecialSaveVolumeDefined=true;};
// Getting variables (just for debugging)
G4double GetDecayPositionZ() {return muDecayPosZ_t;};
G4double GetDecayTime() {return muDecayTime_t*microsecond;};
G4double GetTimeInTarget() {return muTargetTime_t*microsecond;};
// Setting variables common to the whole event:
void SetRunID (G4int id) {runID_t = id;};
void SetEventID (G4int id) {eventID_t = id;};
void SetDecayDetectorID (std::string detectorName) {muDecayDetID_t = SensDetectorMapping[detectorName];};
void SetBField (G4double F[6]) {B_t[0]=F[0]/tesla; B_t[1]=F[1]/tesla; B_t[2]=F[2]/tesla;
B_t[3]=F[3]/tesla; B_t[4]=F[4]/tesla; B_t[5]=F[5]/tesla;};
void SetDecayPolarisation (G4ThreeVector pol) {muDecayPolX_t=pol.x(); muDecayPolY_t=pol.y(); muDecayPolZ_t=pol.z();};
void SetDecayPosition (G4ThreeVector pos) {muDecayPosX_t=pos.x()/mm; muDecayPosY_t=pos.y()/mm;
muDecayPosZ_t=pos.z()/mm;};
void SetGlobTime (G4double gt) {globalTime_t = gt/microsecond;};
void SetDetectorInfo (G4int nDetectors, G4int ID, G4double edep, G4double edep_el, G4double edep_pos,
G4double edep_gam, G4double edep_mup,G4int nsteps, G4double length, G4double t1,
G4double t2, G4double x, G4double y, G4double z) {
if ((nDetectors<0)||(nDetectors>=(det_nMax-1))) {
G4cout<<"SERIOUS ERROR! sr1RootOutput.hh: nDetectors="<<nDetectors<<
" is larger than det_nMax="<<det_nMax<<G4endl;
return;
}
else {
det_n=nDetectors+1; det_ID[nDetectors]=ID; det_edep[nDetectors]=edep/MeV;
det_edep_el[nDetectors]=edep_el/MeV; det_edep_pos[nDetectors]=edep_pos/MeV;
det_edep_gam[nDetectors]=edep_gam/MeV; det_edep_mup[nDetectors]=edep_mup/MeV;
det_nsteps[nDetectors]=nsteps; det_length[nDetectors]=length/mm;
det_time_start[nDetectors]=t1/microsecond; det_time_end[nDetectors]=t2/microsecond;
det_x[nDetectors]=x/mm;det_y[nDetectors]=y/mm;det_z[nDetectors]=z/mm;
// G4cout << "Saved to root: eventID="<<eventID_t<<"; det_ID="<<det_ID[nDetectors]
// <<"; det_edep="<<det_edep[nDetectors]<<G4endl;
}
//G4cout << "eventID="<<eventID_t<<"; det_n="<<det_n<<"; det_ID="<<det_ID[nDetectors]<<"; "
// << "Deposited E (el, pos, gam, mu)="<<det_edep_el[nDetectors]<<", "
// << det_edep_pos[nDetectors]<<", "<< det_edep_gam[nDetectors]<<", "
// << det_edep_mup[nDetectors]<<G4endl;
//G4cout << " det_time_start="<<det_time_start[nDetectors]
// << " det_time_end="<<det_time_end[nDetectors] << G4endl;
};
void SetSaveDetectorInfo (G4int ID, G4int particleID, G4double x, G4double y, G4double z,
G4double px, G4double py, G4double pz) ;
void SetInitialMuonParameters(G4double x, G4double y, G4double z, G4double px, G4double py, G4double pz,
G4double xpolaris, G4double ypolaris, G4double zpolaris) {
muIniPosX_t=x; muIniPosY_t=y; muIniPosZ_t=z;
muIniMomX_t=px; muIniMomY_t=py; muIniMomZ_t=pz;
muIniPolX_t=xpolaris; muIniPolY_t=ypolaris; muIniPolZ_t=zpolaris;
}
// void SetSubtrackInfo (G4int iSubtrack, G4int partID, G4int trID, G4int volID, G4double E,
// G4double xx, G4double yy, G4double zz, G4double xxPost, G4double yyPost, G4double zzPost,
// G4double Eki, G4double stepL, G4int nrOfSubst) {
// if ((iSubtrack<0)||(iSubtrack>=maxNSubTracks)) {
// G4cout<<"SERIOUS ERROR! sr1RootOutput.hh: iSubtrack="<<iSubtrack<<
// " is larger than maxNSubTracks="<<maxNSubTracks<<G4endl;
// return;
// }
// else {
// nSubTracks=iSubtrack+1;
// particleID_t[iSubtrack]=partID;
// trackID_t[iSubtrack]=trID;
// logicalVolumeID_t[iSubtrack]=volID;
// edep_t[iSubtrack]=E/MeV;
// x_t[iSubtrack]=xx/mm;
// y_t[iSubtrack]=yy/mm;
// z_t[iSubtrack]=zz/mm;
// post_x_t[iSubtrack]=xxPost/mm;
// post_y_t[iSubtrack]=yyPost/mm;
// post_z_t[iSubtrack]=zzPost/mm;
// kineticEnergy_t[iSubtrack]=Eki/MeV;
// stepLength_t[iSubtrack]=stepL/mm;
// nrOfSubsteps_t[iSubtrack]=nrOfSubst;
// }
// };
void SetPolInTarget(G4ThreeVector pol) {muTargetPolX_t=pol.x(); muTargetPolY_t=pol.y(); muTargetPolZ_t=pol.z();};
void SetTimeInTarget(G4double time) {muTargetTime_t = time/microsecond;};
void SetInitialPositronMomentum(G4ThreeVector mom) {posIniMomx_t=mom.x(); posIniMomy_t=mom.y(); posIniMomz_t=mom.z();};
void SetDecayTime(G4double time) {muDecayTime_t=time/microsecond;};
void SetFieldValue(G4double value) {fieldValue_t=value/tesla;};
void SetNrFieldNomVal(G4int n) {nFieldNomVal = n;}
void SetFieldNomVal(G4int i, G4double value);
G4int GetNrOfVolumes() {return det_nMax;}
void StoreGeantParameter(Int_t i, Double_t value) {
if (i<maxNGeantParameters) { GeantParametersD[i]=value; }
else {G4cout<<"sr1RootOutput.hh::StoreGeantParameter: index="<<i<<" out of range"
<<" (maxNGeantParameters=" <<maxNGeantParameters<<")"<<G4endl;}
};
TH2F *htest1, *htest2;
TH1F *htest3, *htest4, *htest5, *htest6, *htest7, *htest8;
public:
static G4bool store_runID;
static G4bool store_eventID;
static G4bool store_BFieldAtDecay;
static G4bool store_muIniPosX;
static G4bool store_muIniPosY;
static G4bool store_muIniPosZ;
static G4bool store_muIniMomX;
static G4bool store_muIniMomY;
static G4bool store_muIniMomZ;
static G4bool store_muIniPolX;
static G4bool store_muIniPolY;
static G4bool store_muIniPolZ;
static G4bool store_muDecayDetID;
static G4bool store_muDecayPosX;
static G4bool store_muDecayPosY;
static G4bool store_muDecayPosZ;
static G4bool store_muDecayTime;
static G4bool store_muDecayPolX;
static G4bool store_muDecayPolY;
static G4bool store_muDecayPolZ;
static G4bool store_muTargetTime;
static G4bool store_muTargetPolX;
static G4bool store_muTargetPolY;
static G4bool store_muTargetPolZ;
static G4bool store_posIniMomX;
static G4bool store_posIniMomY;
static G4bool store_posIniMomZ;
static G4bool store_globalTime;
static G4bool store_fieldValue;
static G4bool store_det_ID;
static G4bool store_det_edep;
static G4bool store_det_edep_el;
static G4bool store_det_edep_pos;
static G4bool store_det_edep_gam;
static G4bool store_det_edep_mup;
static G4bool store_det_nsteps;
static G4bool store_det_length;
static G4bool store_det_start;
static G4bool store_det_end;
static G4bool store_det_x;
static G4bool store_det_y;
static G4bool store_det_z;
static G4bool store_fieldNomVal;
private:
TFile* rootFile;
TTree* rootTree;
static sr1RootOutput* pointerToRoot;
static const Int_t maxNGeantParameters=30;
Double_t GeantParametersD[maxNGeantParameters]; // parameters transfered from GEANT to Root
// 0 ... fieldOption: 0 ... no field, 1 ... uniform, 2 ... gaussian, 3 ... from table
// 1 ... fieldValue: intensity of the magnetic field
// 2 ... minimum of the generated decay time of the muon (in microsecond)
// 3 ... maximum of the generated decay time of the muon (in microsecond)
// 4 ... muon mean life time (in microsecond)
// Variables common to the whole event:
Int_t runID_t;
Int_t eventID_t;
Double_t B_t[6];
Double_t muIniPosX_t, muIniPosY_t, muIniPosZ_t;
Double_t muIniMomX_t, muIniMomY_t, muIniMomZ_t;
Double_t muIniPolX_t, muIniPolY_t, muIniPolZ_t;
Int_t muDecayDetID_t;
Double_t muDecayPolX_t, muDecayPolY_t, muDecayPolZ_t;
Double_t muTargetPolX_t, muTargetPolY_t, muTargetPolZ_t;
Double_t muDecayPosX_t, muDecayPosY_t, muDecayPosZ_t;
Double_t muDecayTime_t;
Double_t posIniMomx_t, posIniMomy_t, posIniMomz_t;
Double_t globalTime_t, muTargetTime_t;
Double_t fieldValue_t;
public:
static const Int_t maxNFieldnNominalValues=30;
private:
Int_t nFieldNomVal;
Double_t fieldNomVal[maxNFieldnNominalValues];
// Variables for a particle in a given detector within the event
public:
static const Int_t maxNSubTracks=30;
private:
// Int_t nSubTracks;
// // Char_t particleName_t[6];
// Int_t particleID_t[maxNSubTracks];
// G4int trackID_t[maxNSubTracks];
// Double_t edep_t[maxNSubTracks];
// Double_t x_t[maxNSubTracks];
// Double_t y_t[maxNSubTracks];
// Double_t z_t[maxNSubTracks];
// Double_t post_x_t[maxNSubTracks];
// Double_t post_y_t[maxNSubTracks];
// Double_t post_z_t[maxNSubTracks];
// // Char_t logicalVolume_t[13];
// Int_t logicalVolumeID_t[maxNSubTracks];
// Double_t kineticEnergy_t[maxNSubTracks];
// Double_t stepLength_t[maxNSubTracks];
// Int_t nrOfSubsteps_t[maxNSubTracks];
// Variables for the activity inside a given detector
public:
static const Int_t det_nMax=100; // must be by 1 higher than the real number of detector "hits", because
// else the detector nr. 0 is counted (0 is used if no
// SensDetectorMapping correspond to a given logical volume).
private:
G4int det_n;
G4int det_ID[det_nMax];
G4double det_edep[det_nMax];
G4int det_nsteps[det_nMax];
G4double det_length[det_nMax];
G4double det_edep_el[det_nMax];
G4double det_edep_pos[det_nMax];
G4double det_edep_gam[det_nMax];
G4double det_edep_mup[det_nMax];
G4double det_time_start[det_nMax];
G4double det_time_end[det_nMax];
G4double det_x[det_nMax];
G4double det_y[det_nMax];
G4double det_z[det_nMax];
// G4bool firstStepInVolume_t;
// G4bool lastStepInVolume_t;
public:
static const Int_t save_nMax=1000;
private:
G4int save_n;
G4int save_detID[save_nMax];
G4int save_particleID[save_nMax];
G4double save_x[save_nMax];
G4double save_y[save_nMax];
G4double save_z[save_nMax];
G4double save_px[save_nMax];
G4double save_py[save_nMax];
G4double save_pz[save_nMax];
G4bool boolIsAnySpecialSaveVolumeDefined;
std::map<std::string,int> SensDetectorMapping;
};
//G4int sr1RootOutput::maxNSubTracks=30;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,36 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1RunAction_h
#define sr1RunAction_h 1
#include "G4UserRunAction.hh"
#include "globals.hh"
#include "sr1RootOutput.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class G4Timer;
class G4Run;
class sr1RunAction : public G4UserRunAction
{
public:
sr1RunAction();
~sr1RunAction();
public:
void BeginOfRunAction(const G4Run*);
void EndOfRunAction(const G4Run*);
private:
G4Timer* timer;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,128 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1ScintHit_h
#define sr1ScintHit_h 1
#include "G4VHit.hh"
#include "G4THitsCollection.hh"
#include "G4Allocator.hh"
#include "G4ThreeVector.hh"
#include "G4MagneticField.hh"
#include "globals.hh"
#include "G4ios.hh"
// ROOT
#include "TFile.h"
#include "TTree.h"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1ScintHit : public G4VHit
{
public:
sr1ScintHit();
~sr1ScintHit();
sr1ScintHit(const sr1ScintHit&);
const sr1ScintHit& operator=(const sr1ScintHit&);
G4int operator==(const sr1ScintHit&) const;
// bool operator() (sr1ScintHit hit1, sr1ScintHit hit2) { return (hit1.globalTime<hit2.globalTime);}
inline void* operator new(size_t);
inline void operator delete(void*);
void Draw();
void Print();
public:
void SetParticleName (G4String name) {particleName = name; };
void SetParticleID (G4int id) {particleID = id; };
void SetTrackID (G4int track) { trackID = track; };
void SetEdep (G4double de) { edep = de; };
void SetPrePos (G4ThreeVector xyz){ pre_pos = xyz; };
void SetPostPos (G4ThreeVector xyz){ post_pos = xyz; };
void SetPol (G4ThreeVector ijk){pol = ijk;};
void SetLogVolName (G4String logivol) {logicalVolume = logivol;};
void SetGlobTime (G4double gt) { globalTime = gt;};
void SetFirstStepInVolumeFlag (G4bool flag) { firstStepInVolume=flag;};
void SetLastStepInVolumeFlag (G4bool flag) { lastStepInVolume=flag;};
void SetKineticEnergy (G4double en) { kineticEnergy = en;};
void SetStepLength (G4double length) { stepLength = length;};
// void SetBField (G4double f[6]) {BF[0]=f[0]; BF[1]=f[1]; BF[2]=f[2]; BF[3]=f[3]; BF[4]=f[4]; BF[5]=f[5];};
void SetRunID(G4int i) {runID=i;};
void SetEventID(G4int i) {eventID=i;};
// void SetVerboseLevel (G4int n) { G4int sr1ScintHit::verboseLevel=n;};
G4String GetParticleName() {return particleName; };
G4int GetParticleID() {return particleID; };
G4int GetTrackID() { return trackID; };
G4double GetEdep() { return edep; };
G4ThreeVector GetPrePos(){ return pre_pos; };
G4ThreeVector GetPostPos(){ return post_pos; };
G4ThreeVector GetPol(){ return pol; };
G4String GetLogVolName() { return logicalVolume; };
G4double GetGlobalTime() { return globalTime; };
G4bool GetFirstStepInVolumeFlag() {return firstStepInVolume;};
G4bool GetLastStepInVolumeFlag() {return lastStepInVolume;};
G4double GetKineticEnergy() { return kineticEnergy; };
G4double GetStepLength() {return stepLength; };
G4double* GetBField () {return BF;};
G4int GetRunID() {return runID;};
G4int GetEventID() {return eventID;};
G4double point[4];
G4double B[6];
const G4Field *mfield;
private:
G4String particleName;
G4int particleID;
G4int trackID;
G4double edep;
G4ThreeVector pre_pos;
G4ThreeVector post_pos;
G4ThreeVector pol;
G4String logicalVolume;
G4double globalTime;
G4bool firstStepInVolume;
G4bool lastStepInVolume;
G4double kineticEnergy;
G4double stepLength;
G4int eventID;
G4int runID;
G4double BF[6];
static G4int ScintMultihit;
static G4int runIDoldScint;
static G4int eventIDoldScint;
static G4int NIS;
static G4int ScintChamberNbold;
static G4int verboseLevel;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
typedef G4THitsCollection<sr1ScintHit> sr1ScintHitsCollection;
extern G4Allocator<sr1ScintHit> sr1ScintHitAllocator;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline void* sr1ScintHit::operator new(size_t)
{
void *aHit;
aHit = (void *) sr1ScintHitAllocator.MallocSingle();
return aHit;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline void sr1ScintHit::operator delete(void *aHit)
{
sr1ScintHitAllocator.FreeSingle((sr1ScintHit*) aHit);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,42 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1ScintSD_h
#define sr1ScintSD_h 1
#include "G4VSensitiveDetector.hh"
#include "sr1ScintHit.hh"
#include "sr1RootOutput.hh"
//cksdel extern sr1RootOutput* myRootOutput;
class G4Step;
class G4HCofThisEvent;
//class sr1ScintHit;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1ScintSD : public G4VSensitiveDetector
{
public:
sr1ScintSD(G4String);
~sr1ScintSD();
void Initialize(G4HCofThisEvent*);
G4bool ProcessHits(G4Step*, G4TouchableHistory*);
void EndOfEvent(G4HCofThisEvent*);
// bool timeOrdering (sr1ScintHit* hit1, sr1ScintHit* hit2);
// bool myREMOVEfunction (int i,int j) { return (i<j); }
private:
sr1ScintHitsCollection* scintCollection;
G4bool myStoreOnlyEventsWithHits;
G4double mySignalSeparationTime;
G4bool myStoreOnlyTheFirstTimeHit;
// G4bool Positron_momentum_already_stored;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,92 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1ShieldHit_h
#define sr1ShieldHit_h 1
#include "G4VHit.hh"
#include "G4THitsCollection.hh"
#include "G4Allocator.hh"
#include "G4ThreeVector.hh"
#include "G4MagneticField.hh"
#include "globals.hh"
#include "G4ios.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1ShieldHit : public G4VHit
{
public:
sr1ShieldHit();
~sr1ShieldHit();
sr1ShieldHit(const sr1ShieldHit&);
const sr1ShieldHit& operator=(const sr1ShieldHit&);
G4int operator==(const sr1ShieldHit&) const;
inline void* operator new(size_t);
inline void operator delete(void*);
void Draw();
void Print();
public:
void SetTrackID (G4int track) { trackID = track; };
void SetParticleName (G4String name) {particle_name = name; };
void SetEdep (G4double de) { edep = de; };
void SetPos (G4ThreeVector xyz){ pos = xyz; };
void SetPol (G4ThreeVector ijk){pol = ijk;};
void SetLogVolName (G4String logivol) {logicalvolume = logivol;};
G4int GetTrackID() { return trackID; };
G4String GetParticleName() {return particle_name; };
G4double GetEdep() { return edep; };
G4ThreeVector GetPos(){ return pos; };
G4ThreeVector GetPol(){ return pol; };
G4String GetLogVolName() { return logicalvolume; };
G4double point[4];
G4double B[6];
const G4Field *mfield;
private:
G4int trackID;
G4String particle_name;
G4double edep;
G4ThreeVector pos;
G4ThreeVector pol;
G4String logicalvolume;
static G4int eventIDoldB;
static G4int Nb;
static G4int runIDoldB;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
typedef G4THitsCollection<sr1ShieldHit> sr1ShieldHitsCollection;
extern G4Allocator<sr1ShieldHit> sr1ShieldHitAllocator;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline void* sr1ShieldHit::operator new(size_t)
{
void *aHit;
aHit = (void *) sr1ShieldHitAllocator.MallocSingle();
return aHit;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
inline void sr1ShieldHit::operator delete(void *aHit)
{
sr1ShieldHitAllocator.FreeSingle((sr1ShieldHit*) aHit);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,32 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1ShieldSD_h
#define sr1ShieldSD_h 1
#include "G4VSensitiveDetector.hh"
#include "sr1ShieldHit.hh"
class G4Step;
class G4HCofThisEvent;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1ShieldSD : public G4VSensitiveDetector
{
public:
sr1ShieldSD(G4String);
~sr1ShieldSD();
void Initialize(G4HCofThisEvent*);
G4bool ProcessHits(G4Step*, G4TouchableHistory*);
void EndOfEvent(G4HCofThisEvent*);
private:
sr1ShieldHitsCollection* shieldCollection;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,47 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifndef sr1SteppingAction_h
#define sr1SteppingAction_h 1
#include "G4UserSteppingAction.hh"
#include "G4ProcessManager.hh"
#include "globals.hh"
#include <fstream>
class G4Timer;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1SteppingAction : public G4UserSteppingAction
{
public:
static sr1SteppingAction* GetInstance();
sr1SteppingAction();
~sr1SteppingAction();
void UserSteppingAction(const G4Step *theStep);
void DoAtTheBeginningOfEvent();
void SetLogicalVolumeAsSpecialSaveVolume(G4String logicName, G4int volumeID);
private:
G4Timer* timer;
static sr1SteppingAction* pointer;
// G4int oldEventID;
G4ProcessManager* muPlusProcessManager;
G4bool multipleToCoulombScatteringIsPossible;
G4bool coulombScatteringIsActive;
size_t multipleScatteringIndex;
size_t coulombScatteringIndex;
G4bool muAlreadyWasInTargetInThisEvent;
G4bool radioactiveElectronAlreadySavedInThisEvent;
G4bool boolIsAnySpecialSaveVolumeDefined;
std::map<G4String,G4int> saveVolumeMapping;
G4String lastActualVolume;
// G4int debugOldEventID;
// G4int nrOfSteps;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,26 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1SteppingVerbose;
#ifndef sr1SteppingVerbose_h
#define sr1SteppingVerbose_h 1
#include "G4SteppingVerbose.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1SteppingVerbose : public G4SteppingVerbose
{
public:
sr1SteppingVerbose();
~sr1SteppingVerbose();
void StepInfo();
void TrackingStarted();
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif

View File

@ -0,0 +1,73 @@
#ifndef sr1TabulatedElementField2D_h
#define sr1TabulatedElementField2D_h 1
#include "F04ElementField.hh"
#include "F04GlobalField.hh"
#include "globals.hh"
#include "G4ios.hh"
#include <fstream>
#include <vector>
#include <cmath>
class sr1TabulatedElementField2D : public F04ElementField
{
public: // with description
// Class constructor for 2D axial field map (r, z, EMr, EMz) - with EM = E or B; r - radial, z - longitudinal.
sr1TabulatedElementField2D(const char* filename, const char fieldType, G4double fieldValue, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter);
//
// "fieldType" is the type of EM field: electric - E, or magnetic - B
// "fieldValue" is the field to be applied (in T, or in kV/mm). The normalised field
// map values are multiplied by this value. The field-map itself has no units!
// "lenUnit" is the unit in which the grid coordinates of the field-map are specified
// "fieldNormalisation" is the normalisation factor that once applied to the tabulated field values
// satisfies the condition: (max. field value)*fieldNormalisation = 1
// To revert field direction, change its sign to negative.
// Virtual destructor
virtual ~sr1TabulatedElementField2D() {}
// addFieldValue() adds the field for THIS particular map into field[].
// point[] is expressed in GLOBAL coordinates.
void addFieldValue( const G4double Point[4], G4double* field) const;
// Usual Set and Get functions
G4double GetNominalFieldValue();
void SetNominalFieldValue(G4double newFieldValue);
// getWidth(), getHeight(), getLength(), return the dimensions of the field
// (used to define the boundary of the field)
virtual G4double getWidth() { return 2*dr; } // x coordinate
virtual G4double getHeight() { return 2*dr; } // y coordinate
virtual G4double getLength() { return dz; } // z coordinate
private:
// Storage space for the 2D table
std::vector< std::vector< double > > rField;
std::vector< std::vector< double > > zField;
// The field-map dimensions
int nr, nz;
// The field map Length unit (string and number)
G4String lUnit;
double lenUnit;
// The DEFAULT user-defined field units for E and B (kilovolt/mm and tesla)
G4String fUnit;
double fieUnit;
// The field-map Field normalisation factor
double fieldNormalisation;
// The physical limits of the defined region
double minimumr, maximumr, minimumz, maximumz;
// The physical extent of the defined region
double dr, dz;
// See the description under the class constructor
char fldType;
double ffieldValue;
void Invert(const char* indexToInvert);
};
#endif

View File

@ -0,0 +1,73 @@
#ifndef sr1TabulatedElementField2Df_h
#define sr1TabulatedElementField2Df_h 1
#include "F04ElementField.hh"
#include "F04GlobalField.hh"
#include "globals.hh"
#include "G4ios.hh"
#include <fstream>
#include <vector>
#include <cmath>
class sr1TabulatedElementField2Df : public F04ElementField
{
public: // with description
// Class constructor for r-axis FOLDED 2D axial field map (r, z, EMr, EMz) - with EM = E or B; r - radial, z - longit.
sr1TabulatedElementField2Df(const char* filename, const char fieldType, G4double fieldValue, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter);
//
// "fieldType" is the type of EM field: electric - E, or magnetic - B
// "fieldValue" is the field to be applied (in T, or in kV/mm). The normalised field
// map values are multiplied by this value. The field-map itself has no units!
// "lenUnit" is the unit in which the grid coordinates of the field-map are specified
// "fieldNormalisation" is the normalisation factor that once applied to the tabulated field values
// satisfies the condition: (max. field value)*fieldNormalisation = 1
// To revert field direction, change its sign to negative.
// Virtual destructor
virtual ~sr1TabulatedElementField2Df() {}
// addFieldValue() adds the field for THIS particular map into field[].
// point[] is expressed in GLOBAL coordinates.
void addFieldValue( const G4double Point[4], G4double* field) const;
// Usual Set and Get functions
G4double GetNominalFieldValue();
void SetNominalFieldValue(G4double newFieldValue);
// getWidth(), getHeight(), getLength(), return the dimensions of the field
// (used to define the boundary of the field)
virtual G4double getWidth() { return 2*dr; } // x coordinate
virtual G4double getHeight() { return 2*dr; } // y coordinate
virtual G4double getLength() { return 2*dz; } // z coordinate
private:
// Storage space for the 2D table
std::vector< std::vector< double > > rField;
std::vector< std::vector< double > > zField;
// The field-map dimensions
int nr, nz;
// The field map Length unit (string and number)
G4String lUnit;
double lenUnit;
// The DEFAULT user-defined field units for E and B (kilovolt/mm and tesla)
G4String fUnit;
double fieUnit;
// The field-map Field normalisation factor
double fieldNormalisation;
// The physical limits of the defined region
double minimumr, maximumr, minimumz, maximumz;
// The physical extent of the defined region
double dr, dz;
// See the description under the class constructor
char fldType;
double ffieldValue;
void Invert(const char* indexToInvert);
};
#endif

View File

@ -0,0 +1,76 @@
#ifndef sr1TabulatedElementField3D_h
#define sr1TabulatedElementField3D_h 1
#include "F04ElementField.hh"
#include "F04GlobalField.hh"
#include "globals.hh"
#include "G4ios.hh"
#include <fstream>
#include <vector>
#include <cmath>
// Class for reading 3D electric and magnetic field map, either with or without coordinates.
class sr1TabulatedElementField3D : public F04ElementField
{
public: // with description
// Class constructor for 3D field map (x, y, z, EMx, EMy, EMz) - with EM = E or B
sr1TabulatedElementField3D(const char* filename, const char fieldType, G4double fieldValue, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter);
//
// "fieldType" is the type of EM field: electric - E, or magnetic - B
// "fieldValue" is the field to be applied (in T, or in kV/mm). The normalised field
// map values are multiplied by this value. The field-map itself has no units!
// "lenUnit" is the unit in which the grid coordinates of the field-map are specified
// "fieldNormalisation" is the normalisation factor that once applied to the tabulated field values
// satisfies the condition: (max. field value)*fieldNormalisation = 1
// To revert field direction, change its sign to negative.
// Virtual destructor
virtual ~sr1TabulatedElementField3D() {}
// addFieldValue() adds the field for THIS particular map into field[].
// point[] is expressed in GLOBAL coordinates.
void addFieldValue( const G4double Point[4], G4double* field) const;
// Usual Set and Get functions
G4double GetNominalFieldValue();
void SetNominalFieldValue(G4double newFieldValue);
// getWidth(), getHeight(), getLength(), return the dimensions of the field
// (used to define the boundary of the field)
virtual G4double getWidth() { return dx; } // x coordinate
virtual G4double getHeight() { return dy; } // y coordinate
virtual G4double getLength() { return dz; } // z coordinate
private:
// Storage space for the 3D table
std::vector< std::vector< std::vector< double > > > xField;
std::vector< std::vector< std::vector< double > > > yField;
std::vector< std::vector< std::vector< double > > > zField;
// The field-map dimensions
int nx, ny, nz;
// The field map Length unit (string and number)
///G4String lUnit;
char lUnit[50];
double lenUnit;
// The DEFAULT user-defined field units for E and B (kilovolt/mm and tesla)
G4String fUnit;
double fieUnit;
// The field-map Field normalisation factor
double fieldNormalisation;
// The physical limits of the defined region
double minimumx, maximumx, minimumy, maximumy, minimumz, maximumz;
// The physical extent of the defined region
double dx, dy, dz;
// See the description under the class constructor
char fldType;
double ffieldValue;
void Invert(const char* indexToInvert);
};
#endif

View File

@ -0,0 +1,52 @@
#include "globals.hh"
#include "G4MagneticField.hh"
#include "G4ios.hh"
//cks For the special case of muon decay:
//#include "G4EventManager.hh"
//#include "G4RunManagerKernel.hh"
//csk
#include <fstream>
#include <vector>
#include <cmath>
class sr1TabulatedField2D
#ifndef STANDALONE
: public G4MagneticField
#endif
{
// Storage space for the table
std::vector< std::vector< double > > xField;
std::vector< std::vector< double > > zField;
// The dimensions of the table
int nx,nz;
// The physical limits of the defined region
double minx, maxx, minz, maxz;
// The physical extent of the defined region
double dx, dz;
double ffieldValue;
bool invertX, invertZ;
double positionOffset[4];
static sr1TabulatedField2D* pointerToTabulatedField2D;
public:
static sr1TabulatedField2D* GetInstance();
sr1TabulatedField2D(const char* filename, double fieldValue, double lenUnit, double fieldNormalisation );
// "lenUnit" is the unit in which the grid coordinates are specified in the table
// "fieldNormalisation" is the normalisation that has to be applied on the field values in the table
// such that the values correspond do 1T nominal value
// "fieldValue" is the field value (in T) that is required (i.e. values normalised to 1T will be
// multiplied by this value).
void GetFieldValue( const double Point[4],
double *Bfield ) const;
G4double GetFieldSetValue();
void SetFieldValue(double newFieldValue);
void SetPositionOffset(double offset[4]) { positionOffset[0]=offset[0]; positionOffset[1]=offset[1];
positionOffset[2]=offset[2]; positionOffset[3]=offset[3];}
};

View File

@ -0,0 +1,46 @@
#include "globals.hh"
#include "G4MagneticField.hh"
#include "G4ios.hh"
#include <fstream>
#include <vector>
#include <cmath>
using namespace std;
class sr1TabulatedField3D
#ifndef STANDALONE
: public G4MagneticField
#endif
{
// Storage space for the table
vector< vector< vector< double > > > xField;
vector< vector< vector< double > > > yField;
vector< vector< vector< double > > > zField;
// The dimensions of the table
int nx,ny,nz;
// The physical limits of the defined region
double minx, maxx, miny, maxy, minz, maxz;
// The physical extent of the defined region
double dx, dy, dz;
double ffieldValue;
bool invertX, invertY, invertZ;
double positionOffset[4];
static sr1TabulatedField3D* pointerToTabulatedField3D;
public:
static sr1TabulatedField3D* GetInstance();
sr1TabulatedField3D(const char* filename, double fieldValue );
void GetFieldValue( const double Point[4],
double *Bfield ) const;
G4double GetFieldSetValue();
void SetFieldValue(double newFieldValue);
void SetPositionOffset(double offset[4]) { positionOffset[0]=offset[0]; positionOffset[1]=offset[1];
positionOffset[2]=offset[2]; positionOffset[3]=offset[3];}
};

View File

@ -0,0 +1,43 @@
#ifndef UNIFORM_BFIELD_HH
#define UNIFORM_BFIELD_HH
#include "G4LogicalVolume.hh"
#include "G4Box.hh"
#include "F04ElementField.hh"
#include "F04GlobalField.hh"
// UniformField implements a constant electromagnetic field in any direction. TS
class sr1UniformField : public F04ElementField
{
public:
sr1UniformField(G4double EMF[6], G4LogicalVolume*, G4ThreeVector);
virtual ~sr1UniformField() {}
// TS: Define the two newly added VIRTUAL functions of F04ElementField
G4double GetNominalFieldValue();
void SetNominalFieldValue(G4double newFieldValue);
virtual G4double getLength() { return fieldLength; }
virtual G4double getWidth() { return fieldWidth; }
virtual G4double getHeight() { return fieldHeight; }
G4bool isOutside(G4ThreeVector& local) const;
G4bool isWithin (G4ThreeVector& local) const;
void addFieldValue(const G4double point[4], G4double field[6]) const;
private:
G4double EMfield[6];
G4double fieldLength;
G4double fieldWidth;
G4double fieldHeight;
};
#endif

View File

@ -0,0 +1,26 @@
#ifndef sr1VisManager_h
#define sr1VisManager_h 1
#ifdef G4VIS_USE
#include "G4VisManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
class sr1VisManager: public G4VisManager {
public:
sr1VisManager ();
private:
void RegisterGraphicsSystems ();
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#endif
#endif

View File

@ -0,0 +1,39 @@
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
// 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
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#ifndef Yields_h
#define Yield_h 1
#include "globals.hh"
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
class Yields
{
public:
Yields(); // Class constructor
~Yields(); // Class destructor
void GetYields(double E, double mass, double yvector[]);
private: // Some internal variables
double Q_zero, Q_minus, D;
double Yield_minus, Yield_zero, Yield_plus;
double aux1, aux2, aux3; // Auxiliary variables
};
#endif

View File

@ -0,0 +1,596 @@
# Macro file for sr1.cc - Construct detector, set fields and other parameters.
# Last modified by T. Shiroka: 17.03.2008
# How to run: sr1 10xx.mac (append "idle" for prompt after running)
# sr1 10xx.mac > fname.txt (stores output on a txt file)
###############################################################################################
# #
# Specify the geometry parameters in this file (all dimensions in mm) #
# a. Lines starting with hash marks "#" are comments #
# b Lines starting with #* are temporary comments. Remove/modify to change the configuration #
# c. Lines starting with /sr1/command are commands for the executable program #
# d. Lines starting with /vis, /gun, etc. are common macro commands #
# e. Beam-line components are ordered from exp. area (MCP2) to trigger detector (TD) #
#---------------------------------------------------------------------------------------------#
# Syntax example (following /sr1/command): #
# construct solid_type volume_name parameters_defining_solid material position mothers_name #
# (mothers_name starts with log_) #
###############################################################################################
# For the meaning of the acronyms see also the original G3 file ugeom.F at:
# http://savannah.psi.ch/viewcvs/trunk/simulation/geant3/src/lemsr/ugeom.F?root=nemu%2Flem&rev=2964&view=markup
################################################################################################################
# -- ROTATION MATRICES --
################################################################################################################
# 3 parameters -> Define Euler angles (the 4th par. is set to zero).
# 4 parameters -> Define axis + rotation.
# HEP computations ordinarily use the active rotation viewpoint (object is rotated NOT axes).
# Therefore, rotations about an axis imply ACTIVE COUNTER-CLOCKWISE rotation in this package.
# Rotation around a specified axis means counter-clockwise rot. around the positive direction of the axis.
# Define rotations for the field maps of Trigger and Ring Anode:
/sr1/command rotation rotTrig 0 1 0 -45
/sr1/command rotation rotRAnR 0 0 1 -90
/sr1/command rotation rotRAnL 0 0 1 90
/sr1/command rotation rotRAnD 0 0 1 180
################################################################################################################
# -- LEM GEOMETRY --
################################################################################################################
# WORLD = Laboratory reference frame
/sr1/command construct box World 250 250 2250 G4_Galactic 0 0 0 no_logical_volume norot dead -1
# MINIMUM WORD HALF LENGTH 1250 mm!
#/sr1/command construct box World 2000 2000 4000 G4_Galactic 0 0 0 no_logical_volume norot dead -1
# World visual attributes (optional)
/sr1/command visattributes log_World invisible
#===============================================================================================================
# Sc - Scintillators: U - up, D - down, L - left, R - right (with respect to muon's view - momentum direction)
# 8 Scintillators in two concentric rings - Inner and Outer (see also the convention for the Ring Anode)
#===============================================================================================================
## Inner Scintillators - I
#*/sr1/command construct tubs ScIU 90 95 130 45 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 011 nofield
#*/sr1/command construct tubs ScIR 90 95 130 135 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 012 nofield
#*/sr1/command construct tubs ScID 90 95 130 225 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 013 nofield
#*/sr1/command construct tubs ScIL 90 95 130 315 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 014 nofield
## Outer Scintillators - O
/sr1/command construct tubs ScOU 96 101 130 45 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 021 nofield
/sr1/command construct tubs ScOR 96 101 130 135 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 022 nofield
/sr1/command construct tubs ScOD 96 101 130 225 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 023 nofield
/sr1/command construct tubs ScOL 96 101 130 315 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 024 nofield
# Visual attributes (optional)
#*/sr1/command visattributes log_ScOU SCINT_style
#*/sr1/command visattributes log_ScOD dSCINT_style
#*/sr1/command visattributes log_ScOL darkred
#===============================================================================================================
# Experimental Area - Can host EITHER the Cryostat OR the MCP2 (For the tests we usually use the MCP)
# Delimited by the F160 and F100 (blank end) flanges
#===============================================================================================================
# MCP - Multi-Channel Plate 2 Chamber; V - Vacuum, S - Solid # Note: VERY IMPORTANT: mcpv_z = -92.5 mm!
# OLD way of assigning a field
#/sr1/command construct tubs MCPV 0 76.5 254.5 0 360 G4_Galactic 0 0 -92.5 log_World norot dead 100 MCPSfield
/sr1/command construct tubs MCPV 0 76.5 254.5 0 360 G4_Galactic 0 0 -92.5 log_World norot dead 100 nofield
/sr1/command construct tubs MCPS 76.5 79.5 162.0 0 360 Steel 0 0 0 log_World norot dead 101 nofield
# F - Flanges: F160, F100, F200 (used only when the Asymmetry check is OFF)
# F160 - 160 CF flange upstream of MCP2 tube
# F100 (Blank end flange) # OLD Value was 162.0
/sr1/command construct tubs F160 79.5 101.25 11 0 360 Steel 0 0 -151.0 log_World norot dead 901 nofield
/sr1/command construct tubs F100 0 76.5 10 0 360 Steel 0 0 172.0 log_World norot dead 902 nofield
# NOTE: Original F100 referred to MCPV (as shown below) was moved to World.
#/sr1/command construct tubs F100 0 76.5 10 0 360 Steel 0 0 264.5 log_MCPV norot dead 902 nofield
# Experimental Area visual attributes (optional)
/sr1/command visattributes log_MCPV invisible
/sr1/command visattributes log_MCPS invisible
/sr1/command visattributes log_F160 blue_style
/sr1/command visattributes log_F100 blue_style
#===============================================================================================================
# MCP - Micro Channel Plate Detector MCP2 (Used as an alternative to cryostat) # mcpv_z = -92.5 mm!
#===============================================================================================================
# MCPM1 - MCP Macor ring 1
# MCPD - electron multiplying glass disk (also known as target) # Sensitive surface at z = 14 mm wrt. World
# MCPM2 - MCP Macor ring 2
#*/sr1/command construct tubs MCPM1 24 32.5 0.75 0 360 Macor 0 0 105.75 log_MCPV norot dead 201 nofield
# Use it either as (DMCP-sr1/ScintSD) - no info on mu+ polariz., or as (target-dead) with info on mu+ polariz.
#*/sr1/command construct tubs target 0 25.0 1.50 0 360 MCPglass 0 0 108.0 log_MCPV norot dead 032 nofield
/sr1/command construct tubs MCPM2 24 32.5 0.75 0 360 Macor 0 0 110.25 log_MCPV norot dead 203 nofield
# NOTE: To intercept ALL the incoming muons, comment the DMCP and MCPM1 lines above and uncomment this one:
#*/sr1/command construct tubs DMCP 0 76.5 1.5 0 360 MCPglass 0 0 108 log_MCPV norot sr1/ScintSD 202 nofield
/sr1/command construct tubs target 0 76.5 1.5 0 360 MCPglass 0 0 108 log_MCPV norot sr1/ScintSD 202 nofield
# MCSR - Stainless Steel Ring for MCP2 mounting (modelled as a box with a circular hole)
# MCVR - "Vacuum Ring" (circular hole)
/sr1/command construct box MCSR 36.5 36.5 1 Steel 0 0 112.5 log_MCPV norot dead 204 nofield
/sr1/command construct tubs MCVR 0 27.5 1 0 360 G4_Galactic 0 0 0 log_MCSR norot dead 205 nofield
# MCPA = MCP Anode (modelled as a box with two symmetrically subtracted "vacuum" disks)
# ANVA1 - Anode "Vacuum" 1 - Part of MCP Anode
# ANVA2 - Anode "Vacuum" 2 - Part of MCP Anode
/sr1/command construct box MCPA 36.5 36.5 4 Steel 0 0 123.5 log_MCPV norot dead 206 nofield
/sr1/command construct tubs ANVA1 0 27.5 1.5 0 360 G4_Galactic 0 0 -2.5 log_MCPA norot dead 207 nofield
/sr1/command construct tubs ANVA2 0 27.5 1.5 0 360 G4_Galactic 0 0 2.5 log_MCPA norot dead 208 nofield
# MCSS - MCP Stainless Steel Support Ring
/sr1/command construct tubs MCSS 40 48 2.5 0 360 Steel 0 0 156.3 log_MCPV norot dead 209 nofield
# MCP2 visual attributes (optional)
#/sr1/command visattributes log_DMCP MCP_style
#*/sr1/command visattributes log_target MCP_style
#*/sr1/command visattributes log_MCPM1 MACOR_style
/sr1/command visattributes log_MCPM2 MACOR_style
#===============================================================================================================
# CRY - Cryostat - Used as an ALTERNATIVE to MCP2 - Uncomment lines with #*. (Offset = 0.0 cm)
#===============================================================================================================
# SAH - SAmple Holder components (Cu plate) Cu or Al plates 1. Cu plate (sample holder) on Cold finger, 0.5cm
# SAPH - SAPpHire plate mounted between 1st and 2nd Cu plates, 6 mm thick, 60 mm diameter.
# SAH3 is ignored because currently NOT use.
#*/sr1/command construct tubs SAH1 0 35 2.5 0 360 G4_Cu 0 0 119.0 log_MCPV norot dead 251 nofield
#*/sr1/command construct tubs SAH2 0 35 2 0 360 G4_Cu 0 0 108.5 log_MCPV norot dead 252 nofield
#/sr1/command construct tubs SAH3 20 35 0.5 0 360 G4_Cu 0 0 106.0 log_MCPV norot dead 253 nofield
#*/sr1/command construct tubs SAPH 0 30 3 0 360 G4_ALUMINUM_OXIDE 0 0 113.5 log_MCPV norot dead 254 nofield
# Other components of the CRYostat (dimensions and position of CRY4 are only approx. because unknown)
# COFI - COld FInger
# CRY1 - End plate of cryostat (7 mm thick, 30 mm diameter)
# CRY2 - Heat exchanger (assuming a 10 mm opening - Original dimensions not known.) # OLD pos. 160.0
# CRY3 - Mounting ring for He-shield
# CRY4 - 2 mm thick plate for mounting ring. This is just to close the downstream side.
# CRSH - Lateral He-shield
# CRSH2- Frontal He-shield Ring
#*/sr1/command construct tubs COFI 0 27.5 5 0 360 G4_Cu 0 0 126.5 log_MCPV norot dead 261 nofield
#*/sr1/command construct tubs CRY1 0 15 3.5 0 360 G4_Cu 0 0 135.0 log_MCPV norot dead 262 nofield
#*/sr1/command construct tubs CRY2 5 15 25 0 360 G4_Cu 0 0 163.5 log_MCPV norot dead 263 nofield
#*/sr1/command construct tubs CRY3 38 47 5.5 0 360 G4_Cu 0 0 143.5 log_MCPV norot dead 264 nofield
#*/sr1/command construct tubs CRY4 15 38 1 0 360 G4_Cu 0 0 143.5 log_MCPV norot dead 265 nofield
#*/sr1/command construct tubs CRSH 47 48 45 0 360 G4_Cu 0 0 108.5 log_MCPV norot dead 266 nofield
#*/sr1/command construct tubs CRSH2 30 48 0.5 0 360 G4_Cu 0 0 63.0 log_MCPV norot dead 267 nofield
# Electrical Field Guard Rings (distance between the guard rings: 16 mm)
#*/sr1/command construct tubs Guard1 29 38 1.5 0 360 G4_Cu 0 0 76.0 log_MCPV norot dead 271 nofield
#*/sr1/command construct tubs Guard2 29 38 1.5 0 360 G4_Cu 0 0 92.0 log_MCPV norot dead 272 nofield
# Cryostat visual attributes (optional)
#*/sr1/command visattributes log_SAH1 oxsteel
#*/sr1/command visattributes log_SAH2 oxsteel
#*/sr1/command visattributes log_SAPH MACOR_style
#/sr1/command visattributes log_SAH3 oxsteel
#/sr1/command visattributes log_CRSH invisible
#===============================================================================================================
# RA - Ring Anode, M - middle part (closer to Ground Anode), E - end part (farther from the Ground Anode)
# U - up, D - down, L - left, R - right (with respect to muon's view - momentum direction)
# Note: 3.0 mm HALF gap at 45.1469 mm half radius => delta_ang = asin(3.0/45.1469)*180/pi = 3.81 deg.
# Note: delta_ang = 3.1744 deg. for 2.5 mm HG. The angular extension goes e.g. from (45 + da) to (90 - 2*da).
# Note: Ring Anode - Ground Anode distance was 15 mm => CHANGED to 12 mm! (Positions: 11.5 -> 8.5, -33.5 -> -36.5)
#===============================================================================================================
# RA_Ez = -10.35+2.25 = -8.1 cm; RA_Mz= -10.35 - 2.25 = -12.6 cm; RA_Gz= -25.45+3.75 = -21.7 cm; mcpv_z = -9.25 cm
/sr1/command construct cones RA_EU 45.1469 62.5 33.5 39.0 22.5 48.81 82.38 Steel 0 0 8.5 log_MCPV norot dead 301 nofield
/sr1/command construct cones RA_MU 56.7937 62.5 45.147 62.5 22.5 48.81 82.38 Steel 0 0 -36.5 log_MCPV norot dead 302 nofield
/sr1/command construct cones RA_ER 45.1469 62.5 33.5 39.0 22.5 48.81 82.38 Steel 0 0 8.5 log_MCPV rotRAnR dead 303 nofield
/sr1/command construct cones RA_MR 56.7937 62.5 45.147 62.5 22.5 48.81 82.38 Steel 0 0 -36.5 log_MCPV rotRAnR dead 304 nofield
/sr1/command construct cones RA_ED 45.1469 62.5 33.5 39.0 22.5 48.81 82.38 Steel 0 0 8.5 log_MCPV rotRAnD dead 305 nofield
/sr1/command construct cones RA_MD 56.7937 62.5 45.147 62.5 22.5 48.81 82.38 Steel 0 0 -36.5 log_MCPV rotRAnD dead 306 nofield
/sr1/command construct cones RA_EL 45.1469 62.5 33.5 39.0 22.5 48.81 82.38 Steel 0 0 8.5 log_MCPV rotRAnL dead 307 nofield
/sr1/command construct cones RA_ML 56.7937 62.5 45.147 62.5 22.5 48.81 82.38 Steel 0 0 -36.5 log_MCPV rotRAnL dead 308 nofield
# Dummy, thin cylindres used for applying the SAME RA field-map (ROTATED by 90 deg.) to different anodes.
# NOTE: EM field cannot be applied to non simply connected bodies, as e.g. rings, cones, tori, etc.!
/sr1/command construct tubs RA_U 0 0.01 0.005 0 360 G4_Galactic 0 0 -50.50 log_MCPV norot dead 322 nofield
/sr1/command construct tubs RA_R 0 0.01 0.005 0 360 G4_Galactic 0 0 -50.52 log_MCPV rotRAnR dead 324 nofield
/sr1/command construct tubs RA_D 0 0.01 0.005 0 360 G4_Galactic 0 0 -50.54 log_MCPV rotRAnD dead 326 nofield
/sr1/command construct tubs RA_L 0 0.01 0.005 0 360 G4_Galactic 0 0 -50.56 log_MCPV rotRAnL dead 328 nofield
# RA_G - Ring Anode Ground Cylinder
/sr1/command construct tubs RA_G 58 62.5 58.0 0 360 G4_Cu 0 0 -129.0 log_MCPV norot dead 351 nofield
# Ring Anodes visual attributes (optional)
/sr1/command visattributes log_RA_EU oxsteel
/sr1/command visattributes log_RA_MR oxsteel
/sr1/command visattributes log_RA_G Grid_style
# Alternative placement using World as a mother volume (mcpv_z = -92.5 mm). Check latter. These values refer to a 5 mm GAP!
#/sr1/command construct cones RA_EU 45.1469 62.5 33.5 39.0 22.5 48.1711 83.6578 Steel 0 0 -81 log_World norot dead 301 nofield
#/sr1/command construct cones RA_MU 56.7937 62.5 45.147 62.5 22.5 48.1711 83.6578 Steel 0 0 -126 log_World norot dead 302 nofield
#===============================================================================================================
# Gate Valve Area - Hosts the Ground Anode (upstream part of the Ring Anode) - Delimited by L3F1 and F200 flanges
#===============================================================================================================
# GATS - 200 CF flange upstream of MCP2 tube covering the whole length of the gate valve chamber. For simplicity, we
# choose the INNER diameter of the GATe valve Steel tube the same as the OUTER diameter of F200 (200 CF flange)
/sr1/command construct tubs GATS 103.25 126.5 92.5 0 360 Steel 0 0 -254.5 log_World norot dead 371 nofield
# Vacuum "Ring" (to avoid intersections with MCPV) - Not needed if world is already filled with vacuum.
#*/sr1/command construct tubs GATV 76.5 103.25 92.5 0 360 G4_Galactic 0 0 -254.5 log_World norot dead 370 nofield
# F200 - 200 CF flange upstream of MCP2 tube to connect to gate valve chamber
/sr1/command construct tubs F200 76.5 103.25 12 0 360 Steel 0 0 -174.0 log_World norot dead 372 nofield
# NOTE: When using GATV comment the F200 above and uncomment the following (change mother to log_GATV).
#*/sr1/command construct tubs F200 76.5 103.25 12 0 360 Steel 0 0 80.5 log_GATV norot dead 372 nofield
# Gate Valve Area visual attributes (optional)
/sr1/command visattributes log_GATS SCINT_style
/sr1/command visattributes log_F200 blue_style
#===============================================================================================================
# L3 - 3rd Einzel Lens # L3z = -56.7 cm. ATT: DUMMY FIELD change to electric L3Efield!
#===============================================================================================================
# Lens Gap = 12.0 mm => G/D = 12/130 ~ 0.1 (Lens Gap = gap between Ground and Anode, D - Diameter)
# L3 envelope (Tube + Flanges)
# L3VA - Lens 3 Vacuum
# L3ST - Lens 3 Steel tube (inner dia: 200 mm, outer dia: 206 mm, length: 720 mm)
# L3F1 - Lens 3 Flange 1, z = L3z + 208 mm
# L3F2 - Lens 3 Flange 2, z = L3z - 208 mm
/sr1/command construct tubs L3VA 0 100 220 0 360 G4_Galactic 0 0 -567 log_World norot dead 400 nofield
/sr1/command construct tubs L3ST 100 103 220 0 360 Steel 0 0 -567 log_World norot dead 401 nofield
/sr1/command construct tubs L3F1 103 126.5 12 0 360 Steel 0 0 -359 log_World norot dead 402 nofield
/sr1/command construct tubs L3F2 103 126.5 12 0 360 Steel 0 0 -775 log_World norot dead 403 nofield
# GPn - Ground Potential Electrodes
# n = 1-4 and 5-8 - components of the Ground Electrodes
# GP1 - Ground Electrode (inner dia: 130 mm, outer dia: 134 mm, length: 133 mm)
# GP2 - outer electrode surface (LN2 cooling vessel)
# GP3 - first ring cap
# GP4 - second ring cap
# n = 1-4 - Ground Electrode 1 (further from TD). See above for the meaning of acronyms.
/sr1/command construct tubs L3GP1 65 67 66.5 0 360 Steel 0 0 133.5 log_L3VA norot dead 421 nofield
/sr1/command construct tubs L3GP2 81 83 66.5 0 360 Steel 0 0 133.5 log_L3VA norot dead 422 nofield
/sr1/command construct tubs L3GP3 67 81 4 0 360 Steel 0 0 196.0 log_L3VA norot dead 423 nofield
/sr1/command construct tubs L3GP4 67 81 4 0 360 Steel 0 0 71.0 log_L3VA norot dead 424 nofield
# n = 5-8 - Ground Electrode 2 (closer to TD). See above for the meaning of acronyms.
/sr1/command construct tubs L3GP5 65 67 66.5 0 360 Steel 0 0 -133.5 log_L3VA norot dead 431 nofield
/sr1/command construct tubs L3GP6 81 83 66.5 0 360 Steel 0 0 -133.5 log_L3VA norot dead 432 nofield
/sr1/command construct tubs L3GP7 67 81 4 0 360 Steel 0 0 -196.0 log_L3VA norot dead 433 nofield
/sr1/command construct tubs L3GP8 67 81 4 0 360 Steel 0 0 -71.0 log_L3VA norot dead 434 nofield
# HP - High Potential Electrode (Central Anode - usually at +8.7 kV, for a 15 keV muon beam)
/sr1/command construct tubs L3HP 65 83 55 0 360 Steel 0 0 0 log_L3VA norot dead 451 nofield
# Lens 3 visual attributes (optional)
/sr1/command visattributes log_L3VA invisible
/sr1/command visattributes log_L3ST invisible
/sr1/command visattributes log_L3HP darkred
#===============================================================================================================
# IP - Intermediate Piece (between Trigger Detector and Einzel Lens 3)
# Original name was CGate - B-field Coil Compensation Gate?! # CompGatez = -86.55 cm; // L3z - 22 - 7.85 cm
#===============================================================================================================
# IPV (but also others) are just empty volumes "filled" with vacuum. Sometimes used to apply EM fields to restricted areas.
/sr1/command construct tubs IPV 0 100 78.5 0 360 G4_Galactic 0 0 -865.5 log_World norot dead 500 nofield
# IPCF - Intermediate Piece Central Flange (same as L3 Flanges)
# IPST - Intermediate Piece Steel Tube (same diameter as L3 Steel Tube)
/sr1/command construct tubs IPCF 103 126.5 12.0 0 360 Steel 0 0 -865.5 log_World norot dead 501 nofield
/sr1/command construct tubs IPST 100 103 78.5 0 360 Steel 0 0 -865.5 log_World norot dead 502 nofield
# IP visual attributes (optional)
/sr1/command visattributes log_IPV invisible
/sr1/command visattributes log_IPCF blue_style
/sr1/command visattributes log_IPST gray
#===============================================================================================================
# Trigger - Trigger Detector # Triggerz = -1092 mm
#===============================================================================================================
# Trigger tube and relative vacuum
/sr1/command construct tubs TriggerV 0 100 148 0 360 G4_Galactic 0 0 -1092 log_World norot dead 600 nofield
/sr1/command construct tubs Trigger 100 103 148 0 360 Steel 0 0 -1092 log_World norot dead 601 nofield
# TF - Trigger tube flanges
/sr1/command construct tubs TF1 103 126.5 12 0 360 Steel 0 0 -956 log_World norot dead 611 nofield
/sr1/command construct tubs TF2 103 126.5 12 0 360 Steel 0 0 -1228 log_World norot dead 612 nofield
# Carbon Foil (default thickness 0.000005147 mm, see below).
# USE THE NAME CFoil or coulombCFoil, otherwise sr1MuFormation won't work!
/sr1/command construct box CFoil 60 60 0.000005147 G4_GRAPHITE 0 0 -45 log_TriggerV norot dead 621 nofield
###/sr1/command construct box coulombCFoil 60 60 0.000005147 G4_GRAPHITE 0 0 -45 log_TriggerV norot dead 621 nofield
# Notes: NIST tables use G4_GRAPHITE with 1.7 g/cm3 and 78 eV ioniz. energy.
# An area density of 1.75 ug/cm2 implies a CF thickn. = (1.75*1.e-6/1.70)*cm = 1.029e-5 mm - Total thickness
# If necessary, use Graphite as defined in sr1DetectorConstruction.cc and set any density.
# Electrical Field areas in the Trigger Detector
# En = Electrical Field n: TnFieldMgr (n = 1-3)
# Original TriggE2: [4.*sqrt(2), 4.5, 0.7/sqrt(2)] cm -> changed due to overlaps with E1 and E3
/sr1/command construct box TriggE1 45 45 4 G4_Galactic 0 0 -38.5 log_TriggerV norot dead 631 nofield
/sr1/command construct box TriggE2 45 45 4.9497 G4_Galactic 0 0 2.25 log_TriggerV rotTrig dead 632 nofield
/sr1/command construct box TriggE3 45 45 4 G4_Galactic 0 0 43.0 log_TriggerV norot dead 633
# Beam spot (just for having a visual idea!)
/sr1/command construct tubs BSpot 0 20 1 0 360 G4_Galactic 0 0 -48.0 log_TriggerV norot dead 650 nofield
# Trigger visual attributes (optional)
/sr1/command visattributes log_TriggerV invisible
/sr1/command visattributes log_Trigger invisible
#/sr1/command visattributes log_CFoil MACOR_style
/sr1/command visattributes log_BSpot fblue_style
# One can set visible attrib. also on a MATERIAL basis, rather than on log_VOL.
# E.g. /sr1/command visattributes Steel red
################################################################################################################
# -- Setting the ELECTRIC and MAGNETIC fields --
################################################################################################################
# Use ABSOLUTE coordinates to specify the field position (i.e. with respect to GLOBAL WORLD)!
# Default field units: Magnetic - T, Electric - kV/mm (or kV for E-field maps).
# NOTE: Applying a field to an invisible log_vol makes is visible!
### Electric field at TRIGGER Detector TD: Three different uniform fields
/sr1/command globalfield Trigg1_field 0. 0. -1130.5 uniform log_TriggE1 0 0 0 0 0 -0.02375
/sr1/command globalfield Trigg2_field 0. 0. -1089.75 uniform log_TriggE2 0 0 0 0 0 0.041416
/sr1/command globalfield Trigg3_field 0. 0. -1049.0 uniform log_TriggE3 0 0 0 0 0 -0.49375
### Electric field at Einzel LENS 3 - from folded 2D axial field map (f - folded, i.e. symmetric)
# Typically V = +8.7 kV for a muon beam at 15 keV. Use either 2DE L3_Erz.map or
/sr1/command globalfield Lens3_field 0. 0. -567. fromfile 2DEf L3_Erz4.map log_L3VA 8.7
# To change the field in regular steps (e.g. for testing) use (f_min f_max step_no), e.g.:
#*/sr1/command globalfield Lens3_field 0. 0. -567. fromfile 2DEf L3_Erz4.map log_L3VA 7 11 5
### Electric field at RING ANODE - from 3DE field map
# Typically set at +11.0 kV for a muon beam at 15 keV
# To create an arbitrary configuration, switch on all fields and set different potentials.
#######/sr1/command globalfield RngAnU_field 0. 0. -167.00 fromfile 3DE EM_3D_extc.map log_RA_U 11.0
/sr1/command globalfield RngAnU_field 0. 0. -143.00 fromfile 3DE EM_3D_ext_gridf.map log_RA_U 11.0
/sr1/command globalfield RngAnR_field 0. 0. -143.02 fromfile 3DE EM_3D_ext_gridf.map log_RA_R 11.0
/sr1/command globalfield RngAnD_field 0. 0. -143.04 fromfile 3DE EM_3D_ext_gridf.map log_RA_D 11.0
/sr1/command globalfield RngAnL_field 0. 0. -143.06 fromfile 3DE EM_3D_ext_gridf.map log_RA_L 11.0
### LAST FIELD OK: EM_3D_ext2f.map
# EXTENDED MAPS (from -28 to +20 mm) EM_3D_extc.map or EM_3D_extf.map (coord + field or field only)
# "Best" results with EM_RA_3D.map, even though this is not a precise map (poor meshing).
#RA_1kV_upf_raw.map
#RA_1kV_upf.map # EM_extendf2.map give rise to "strange spots" -> sr1_1047_RA13.eps
### Electric field at SAMPLE space. Three possible field maps: Sample, G1 and G2 (closest to sample)
# To create an arbitrary configuration, switch on all fields and set different potentials.
# Field extension along z: 50 mm. Center of MCPV at z = -92.5 mm. Sample face at: z = 108.5 (4 mm thick - SAH2).
# Position of the field: (-92.5 - 50/2) + (108.5 - 4/2) = -11 mm wrt. WORLD! =>
#*/sr1/command globalfield Sample_field 0. 0. -11.0 fromfile 2DE sample_Erz.map log_MCPV 9.0
#*/sr1/command globalfield Guard2_field 0. 0. -11.0 fromfile 2DE guard2_Erz.map log_MCPV 6.0
#*/sr1/command globalfield Guard1_field 0. 0. -11.0 fromfile 2DE guard1_Erz.map log_MCPV 3.0
### Magnetic field at SAMPLE space (use either a uniform field or a field map).
# Use either DMCP or MCPV to apply a CONSTANT field strictly to the sample or also to the surroundings, resp.!
#*/sr1/command globalfield Magnet_field 0. 0. 14.5 uniform log_DMCP 0 0.005 0 0 0 0
# Use field map to set field to 20 G TF
# Extended map has -100/100 cm z extension, field center at +70, original -85/85, center at +85
#####/sr1/command globalfield Magnet_field 0. 0. -836.0 fromfile 2DB sample_Brz.map log_IPV 0.002
/sr1/command globalfield Magnet_field 0. 0. -686.0 fromfile 2DB sample_Brz_ext.map log_L3VA 0.002
# Set parameters for particle tracking in an EM field
/sr1/command globalfield setparameter SetLargestAcceptableStep 5
/sr1/command globalfield setparameter SetMinimumEpsilonStep 5e-5
/sr1/command globalfield setparameter SetMaximumEpsilonStep 0.001
/sr1/command globalfield setparameter SetDeltaOneStep 0.1
/sr1/command globalfield setparameter SetDeltaIntersection 0.01
/sr1/command globalfield printparameters
################################################################################################################
# -- Testing the ELECTRIC and MAGNETIC fields (OPTIONAL) --
################################################################################################################
# FIELD CHECKS at different beam transport components (from trigg. to sample)
# All distances in mm and in GLOBAL coordinates (preferably at field center)
# The test points below are just some examples. Any point can be checked.
# Trigger 1
/sr1/command globalfield printFieldValueAtPoint 0. 0. -1130.5
# Trigger 2
/sr1/command globalfield printFieldValueAtPoint 0. 0. -1089.75
# Trigger 3
/sr1/command globalfield printFieldValueAtPoint 0. 0. -1049.0
# Einzel Lens 3 - L3 (center at -567.0, but max field at rel. +/-62 mm)
/sr1/command globalfield printFieldValueAtPoint 0. 0. -507.0
# Ring Anode - RA (center at -167.0, but max field at rel. -16/+132 mm)
/sr1/command globalfield printFieldValueAtPoint 0. 0. -35.0
# Sample space (center at -11.0, but max field at rel. +24 mm)
/sr1/command globalfield printFieldValueAtPoint 0. 0. 13.0
# Check magnetic field at sample space
#*/sr1/command globalfield printFieldValueAtPoint 10. 0. 13.0
# Check magnetic field at the lower field end limit
#*/sr1/command globalfield printFieldValueAtPoint 0. 20. -1680.
################################################################################################################
# -- Setting simulation PARAMETERS --
################################################################################################################
# Set processes from: lowenergy, penelope, coulombAndMultiple (default), coulomb (only for CFoil).
/sr1/command typeofprocesses lowenergy
#*/sr1/command typeofprocesses penelope
#*/sr1/command includeMuoniumProcesses false
# Set the overall range cut
#*/run/setCut 1 mm
# Set the range cut on particular volumes (in mm)
#*/sr1/command SetUserLimits log_target 0.01
#*/sr1/command SetUserLimits log_targetscint 0.01
#*/sr1/command SetUserLimits log_cryostatscint 0.01
# Set particle energy cuts on particular volumes (in eV)
/sr1/command SetUserMinEkine log_World 0.1
# Store ALL the events in a ROOT tree or just the interesting ones? (default is true)
#*/sr1/command storeOnlyEventsWithHits false
# Set the minimum time separation between two subsequent signals in the same detector (in ns)
/sr1/command signalSeparationTime 0.1
# Override runID number
#*/sr1/run/runID 21
# Set the frequency of event printing
/sr1/run/howOftenToPrintEvent 1000
# RANDOM option choices: (specify the random number generator initialisation)
# 0 ... no initialisation (default)
# 1 ... use actual computer time to initialise now
# 2 ... use event number to initialise at the beginning of each event
# 3 ... read in the random no. initial values for each event from a file
/sr1/run/randomOption 2
# VISUALIZATION options
# To enable or disable visualization uncomment one of these lines
# To modify visualization options edit the file vis.mac
#/vis/disable
/control/execute vis.mac
################################################################################################################
# -- Setting PARTICLE GUN parameters --
################################################################################################################
# Default momentum direction: 001, i.e. 0z.
# Default muon spin direction: 100, i.e. 0x.
# Default particle type: mu+ (can be changed to Mu)
# Set particle type
#*/gun/particle Mu
/gun/particle mu+
# Set beam vertex (to start after C Foil use z = -1130)
/gun/vertex 0. 0. -1170. mm
# A point-like uniform beam
/gun/vertexsigma -0.1 -0.1 0 mm
# Set beam transverse spread (default GAUSSIAN spread)
# If FWHM = 10 mm ==> sigma = 10/2.354 = 4.2481 mm (last 0 is a dummy value)
# Negative sigma values => random FLAT RECTANGULAR distribution (area 2x.2y)
# Use vertexboundary with (vb < sigma_xy) to obtain a CIRCULAR beam spot
# /gun/vertexsigma 0 0 0 mm ==> Very SLOW with mag. field ON and centered beam
#*/gun/vertexsigma 42.5 42.5 0 mm
/gun/vertexsigma -20 -20 0 mm
/gun/vertexboundary 30 -1e6 1e6 mm
# /gun/vertexboundary: rMaxAllowed, zMinAllowed, zMaxAllowed # Beam AND gating
#*/gun/vertexboundary 7 -1314.4 -1305 mm
# Without restrictions in z, but only on r:
#*/gun/vertexboundary 3 -1e6 1e6 mm
# Set beam momentum (USE only as an ALTERNATIVE to setting energy!)
# /gun/momentum 0 0 29.79 MeV
#*/gun/momentum 0 0 1.8 MeV
# Energy loss at p = 1.2 MeV/c (E = 6.8 keV) => 1.23 +/- 0.2 keV
# Energy loss at p = 1.8 MeV/c (E = 15.3 keV) => 1.25 +/- 0.3 keV
# 1.2 MeV/c -> 6.8 keV, 1.8 MeV/c -> 15.3 keV
# muon rest mass = 105.658 MeV/c2
# With Trigger ON use 15 keV, with Trigger OFF use 11.27 keV (15 - 3.73 = 11.27 keV)
/gun/kenergy 15 keV
# Set beam momentum direction
/gun/direction 0.0 0.0 1.0
# Set muon spin direction
/gun/muonPolarizVector 1 0 0
# Other useful test parameters:
#
# FWHM = 3% ==> sigma = 29.79*0.03/2.354 = 0.37965 MeV/c
#*/gun/momentumsmearing 0.37965 MeV
#---/gun/momentumboundary: pMinAllowed, pMaxAllowed, dummy
#*/gun/momentumboundary 20 40 0 MeV
#---/gun/tilt: xangle, yangle, dummy
#*/gun/tilt 0 0.5 0 deg
#---/gun/tiltsigma: xangleSigma, yangleSigma, dummy (1 degree at 1 m => 17 mm)
#*/gun/tiltsigma 0.2 0.2 0 deg
#*/gun/pitch 0.5 deg
#---/gun/decaytimelimits: decayMin, decayMax, decayTime
#*/gun/decaytimelimits 10400 10420 2197.03 ns
# BEAM ON
#*/run/beamOn 1000000
/run/beamOn 2
#/run/beamOn 10000

View File

@ -0,0 +1,612 @@
# Macro file for sr1.cc - Construct detector, set fields and other parameters.
# Last modified by T. Shiroka: 17.03.2008
# How to run: sr1 10xx.mac (append "idle" for prompt after running)
# sr1 10xx.mac > fname.txt (stores output on a txt file)
###############################################################################################
# #
# Specify the geometry parameters in this file (all dimensions in mm) #
# a. Lines starting with hash marks "#" are comments #
# b Lines starting with #* are temporary comments. Remove/modify to change the configuration #
# c. Lines starting with /sr1/command are commands for the executable program #
# d. Lines starting with /vis, /gun, etc. are common macro commands #
# e. Beam-line components are ordered from exp. area (MCP2) to trigger detector (TD) #
#---------------------------------------------------------------------------------------------#
# Syntax example (following /sr1/command): #
# construct solid_type volume_name parameters_defining_solid material position mothers_name #
# (mothers_name starts with log_) #
###############################################################################################
# For the meaning of the acronyms see also the original G3 file ugeom.F at:
# http://savannah.psi.ch/viewcvs/trunk/simulation/geant3/src/lemsr/ugeom.F?root=nemu%2Flem&rev=2964&view=markup
################################################################################################################
# -- ROTATION MATRICES --
################################################################################################################
# 3 parameters -> Define Euler angles (the 4th par. is set to zero).
# 4 parameters -> Define axis + rotation.
# HEP computations ordinarily use the active rotation viewpoint (object is rotated NOT axes).
# Therefore, rotations about an axis imply ACTIVE COUNTER-CLOCKWISE rotation in this package.
# Rotation around a specified axis means counter-clockwise rot. around the positive direction of the axis.
# Define rotations for the field maps of Trigger and Ring Anode:
/sr1/command rotation rotTrig 0 1 0 -45
/sr1/command rotation rotRAnR 0 0 1 -90
/sr1/command rotation rotRAnL 0 0 1 90
/sr1/command rotation rotRAnD 0 0 1 180
################################################################################################################
# -- LEM GEOMETRY --
################################################################################################################
# WORLD = Laboratory reference frame
/sr1/command construct box World 250 250 2250 G4_Galactic 0 0 0 no_logical_volume norot dead -1
# MINIMUM WORD HALF LENGTH 1250 mm!
#/sr1/command construct box World 2000 2000 4000 G4_Galactic 0 0 0 no_logical_volume norot dead -1
# World visual attributes (optional)
/sr1/command visattributes log_World invisible
#===============================================================================================================
# Sc - Scintillators: U - up, D - down, L - left, R - right (with respect to muon's view - momentum direction)
# 8 Scintillators in two concentric rings - Inner and Outer (see also the convention for the Ring Anode)
#===============================================================================================================
## Inner Scintillators - I
#*/sr1/command construct tubs ScIU 90 95 130 45 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 011 nofield
#*/sr1/command construct tubs ScIR 90 95 130 135 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 012 nofield
#*/sr1/command construct tubs ScID 90 95 130 225 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 013 nofield
#*/sr1/command construct tubs ScIL 90 95 130 315 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 014 nofield
## Outer Scintillators - O
/sr1/command construct tubs ScOU 96 101 130 45 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 021 nofield
/sr1/command construct tubs ScOR 96 101 130 135 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 022 nofield
/sr1/command construct tubs ScOD 96 101 130 225 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 023 nofield
/sr1/command construct tubs ScOL 96 101 130 315 90 G4_PLASTIC_SC_VINYLTOLUENE 0 0 0 log_World norot sr1/ScintSD 024 nofield
# Visual attributes (optional)
#*/sr1/command visattributes log_ScOU SCINT_style
#*/sr1/command visattributes log_ScOD dSCINT_style
#*/sr1/command visattributes log_ScOL darkred
#===============================================================================================================
# Experimental Area - Can host EITHER the Cryostat OR the MCP2 (For the tests we usually use the MCP)
# Delimited by the F160 and F100 (blank end) flanges
#===============================================================================================================
# MCP - Multi-Channel Plate 2 Chamber; V - Vacuum, S - Solid # Note: VERY IMPORTANT: mcpv_z = -92.5 mm!
# OLD way of assigning a field
#/sr1/command construct tubs MCPV 0 76.5 254.5 0 360 G4_Galactic 0 0 -92.5 log_World norot dead 100 MCPSfield
/sr1/command construct tubs MCPV 0 76.5 254.5 0 360 G4_Galactic 0 0 -92.5 log_World norot dead 100 nofield
/sr1/command construct tubs MCPS 76.5 79.5 162.0 0 360 Steel 0 0 0 log_World norot dead 101 nofield
# F - Flanges: F160, F100, F200 (used only when the Asymmetry check is OFF)
# F160 - 160 CF flange upstream of MCP2 tube
# F100 (Blank end flange) # OLD Value was 162.0
/sr1/command construct tubs F160 79.5 101.25 11 0 360 Steel 0 0 -151.0 log_World norot dead 901 nofield
/sr1/command construct tubs F100 0 76.5 10 0 360 Steel 0 0 172.0 log_World norot dead 902 nofield
# NOTE: Original F100 referred to MCPV (as shown below) was moved to World.
#/sr1/command construct tubs F100 0 76.5 10 0 360 Steel 0 0 264.5 log_MCPV norot dead 902 nofield
# Experimental Area visual attributes (optional)
/sr1/command visattributes log_MCPV invisible
/sr1/command visattributes log_MCPS invisible
/sr1/command visattributes log_F160 blue_style
/sr1/command visattributes log_F100 blue_style
#===============================================================================================================
# MCP - Micro Channel Plate Detector MCP2 (Used as an alternative to cryostat) # mcpv_z = -92.5 mm!
#===============================================================================================================
# MCPM1 - MCP Macor ring 1
# MCPD - electron multiplying glass disk (also known as target) # Sensitive surface at z = 14 mm wrt. World
# MCPM2 - MCP Macor ring 2
#*/sr1/command construct tubs MCPM1 24 32.5 0.75 0 360 Macor 0 0 105.75 log_MCPV norot dead 201 nofield
# Use it either as (DMCP-sr1/ScintSD) - no info on mu+ polariz., or as (target-dead) with info on mu+ polariz.
#*/sr1/command construct tubs target 0 25.0 1.50 0 360 MCPglass 0 0 108.0 log_MCPV norot dead 032 nofield
/sr1/command construct tubs MCPM2 24 32.5 0.75 0 360 Macor 0 0 110.25 log_MCPV norot dead 203 nofield
# NOTE: To intercept ALL the incoming muons, comment the DMCP and MCPM1 lines above and uncomment this one:
#*/sr1/command construct tubs DMCP 0 76.5 1.5 0 360 MCPglass 0 0 108 log_MCPV norot sr1/ScintSD 202 nofield
/sr1/command construct tubs target 0 76.5 1.5 0 360 MCPglass 0 0 108 log_MCPV norot sr1/ScintSD 202 nofield
# MCSR - Stainless Steel Ring for MCP2 mounting (modelled as a box with a circular hole)
# MCVR - "Vacuum Ring" (circular hole)
/sr1/command construct box MCSR 36.5 36.5 1 Steel 0 0 112.5 log_MCPV norot dead 204 nofield
/sr1/command construct tubs MCVR 0 27.5 1 0 360 G4_Galactic 0 0 0 log_MCSR norot dead 205 nofield
# MCPA = MCP Anode (modelled as a box with two symmetrically subtracted "vacuum" disks)
# ANVA1 - Anode "Vacuum" 1 - Part of MCP Anode
# ANVA2 - Anode "Vacuum" 2 - Part of MCP Anode
/sr1/command construct box MCPA 36.5 36.5 4 Steel 0 0 123.5 log_MCPV norot dead 206 nofield
/sr1/command construct tubs ANVA1 0 27.5 1.5 0 360 G4_Galactic 0 0 -2.5 log_MCPA norot dead 207 nofield
/sr1/command construct tubs ANVA2 0 27.5 1.5 0 360 G4_Galactic 0 0 2.5 log_MCPA norot dead 208 nofield
# MCSS - MCP Stainless Steel Support Ring
/sr1/command construct tubs MCSS 40 48 2.5 0 360 Steel 0 0 156.3 log_MCPV norot dead 209 nofield
# MCP2 visual attributes (optional)
#/sr1/command visattributes log_DMCP MCP_style
#*/sr1/command visattributes log_target MCP_style
#*/sr1/command visattributes log_MCPM1 MACOR_style
/sr1/command visattributes log_MCPM2 MACOR_style
#===============================================================================================================
# CRY - Cryostat - Used as an ALTERNATIVE to MCP2 - Uncomment lines with #*. (Offset = 0.0 cm)
#===============================================================================================================
# SAH - SAmple Holder components (Cu plate) Cu or Al plates 1. Cu plate (sample holder) on Cold finger, 0.5cm
# SAPH - SAPpHire plate mounted between 1st and 2nd Cu plates, 6 mm thick, 60 mm diameter.
# SAH3 is ignored because currently NOT use.
#*/sr1/command construct tubs SAH1 0 35 2.5 0 360 G4_Cu 0 0 119.0 log_MCPV norot dead 251 nofield
#*/sr1/command construct tubs SAH2 0 35 2 0 360 G4_Cu 0 0 108.5 log_MCPV norot dead 252 nofield
#/sr1/command construct tubs SAH3 20 35 0.5 0 360 G4_Cu 0 0 106.0 log_MCPV norot dead 253 nofield
#*/sr1/command construct tubs SAPH 0 30 3 0 360 G4_ALUMINUM_OXIDE 0 0 113.5 log_MCPV norot dead 254 nofield
# Other components of the CRYostat (dimensions and position of CRY4 are only approx. because unknown)
# COFI - COld FInger
# CRY1 - End plate of cryostat (7 mm thick, 30 mm diameter)
# CRY2 - Heat exchanger (assuming a 10 mm opening - Original dimensions not known.) # OLD pos. 160.0
# CRY3 - Mounting ring for He-shield
# CRY4 - 2 mm thick plate for mounting ring. This is just to close the downstream side.
# CRSH - Lateral He-shield
# CRSH2- Frontal He-shield Ring
#*/sr1/command construct tubs COFI 0 27.5 5 0 360 G4_Cu 0 0 126.5 log_MCPV norot dead 261 nofield
#*/sr1/command construct tubs CRY1 0 15 3.5 0 360 G4_Cu 0 0 135.0 log_MCPV norot dead 262 nofield
#*/sr1/command construct tubs CRY2 5 15 25 0 360 G4_Cu 0 0 163.5 log_MCPV norot dead 263 nofield
#*/sr1/command construct tubs CRY3 38 47 5.5 0 360 G4_Cu 0 0 143.5 log_MCPV norot dead 264 nofield
#*/sr1/command construct tubs CRY4 15 38 1 0 360 G4_Cu 0 0 143.5 log_MCPV norot dead 265 nofield
#*/sr1/command construct tubs CRSH 47 48 45 0 360 G4_Cu 0 0 108.5 log_MCPV norot dead 266 nofield
#*/sr1/command construct tubs CRSH2 30 48 0.5 0 360 G4_Cu 0 0 63.0 log_MCPV norot dead 267 nofield
# Electrical Field Guard Rings (distance between the guard rings: 16 mm)
#*/sr1/command construct tubs Guard1 29 38 1.5 0 360 G4_Cu 0 0 76.0 log_MCPV norot dead 271 nofield
#*/sr1/command construct tubs Guard2 29 38 1.5 0 360 G4_Cu 0 0 92.0 log_MCPV norot dead 272 nofield
# Cryostat visual attributes (optional)
#*/sr1/command visattributes log_SAH1 oxsteel
#*/sr1/command visattributes log_SAH2 oxsteel
#*/sr1/command visattributes log_SAPH MACOR_style
#/sr1/command visattributes log_SAH3 oxsteel
#/sr1/command visattributes log_CRSH invisible
#===============================================================================================================
# RA - Ring Anode, M - middle part (closer to Ground Anode), E - end part (farther from the Ground Anode)
# U - up, D - down, L - left, R - right (with respect to muon's view - momentum direction)
# Note: 3.0 mm HALF gap at 45.1469 mm half radius => delta_ang = asin(3.0/45.1469)*180/pi = 3.81 deg.
# Note: delta_ang = 3.1744 deg. for 2.5 mm HG. The angular extension goes e.g. from (45 + da) to (90 - 2*da).
# Note: Ring Anode - Ground Anode distance was 15 mm => CHANGED to 12 mm! (Positions: 11.5 -> 8.5, -33.5 -> -36.5)
#===============================================================================================================
# RA_Ez = -10.35+2.25 = -8.1 cm; RA_Mz= -10.35 - 2.25 = -12.6 cm; RA_Gz= -25.45+3.75 = -21.7 cm; mcpv_z = -9.25 cm
/sr1/command construct cones RA_EU 45.1469 62.5 33.5 39.0 22.5 48.81 82.38 Steel 0 0 8.5 log_MCPV norot dead 301 nofield
/sr1/command construct cones RA_MU 56.7937 62.5 45.147 62.5 22.5 48.81 82.38 Steel 0 0 -36.5 log_MCPV norot dead 302 nofield
/sr1/command construct cones RA_ER 45.1469 62.5 33.5 39.0 22.5 48.81 82.38 Steel 0 0 8.5 log_MCPV rotRAnR dead 303 nofield
/sr1/command construct cones RA_MR 56.7937 62.5 45.147 62.5 22.5 48.81 82.38 Steel 0 0 -36.5 log_MCPV rotRAnR dead 304 nofield
/sr1/command construct cones RA_ED 45.1469 62.5 33.5 39.0 22.5 48.81 82.38 Steel 0 0 8.5 log_MCPV rotRAnD dead 305 nofield
/sr1/command construct cones RA_MD 56.7937 62.5 45.147 62.5 22.5 48.81 82.38 Steel 0 0 -36.5 log_MCPV rotRAnD dead 306 nofield
/sr1/command construct cones RA_EL 45.1469 62.5 33.5 39.0 22.5 48.81 82.38 Steel 0 0 8.5 log_MCPV rotRAnL dead 307 nofield
/sr1/command construct cones RA_ML 56.7937 62.5 45.147 62.5 22.5 48.81 82.38 Steel 0 0 -36.5 log_MCPV rotRAnL dead 308 nofield
# Dummy, thin cylindres used for applying the SAME RA field-map (ROTATED by 90 deg.) to different anodes.
# NOTE: EM field cannot be applied to non simply connected bodies, as e.g. rings, cones, tori, etc.!
/sr1/command construct tubs RA_U 0 0.01 0.005 0 360 G4_Galactic 0 0 -50.50 log_MCPV norot dead 322 nofield
/sr1/command construct tubs RA_R 0 0.01 0.005 0 360 G4_Galactic 0 0 -50.52 log_MCPV rotRAnR dead 324 nofield
/sr1/command construct tubs RA_D 0 0.01 0.005 0 360 G4_Galactic 0 0 -50.54 log_MCPV rotRAnD dead 326 nofield
/sr1/command construct tubs RA_L 0 0.01 0.005 0 360 G4_Galactic 0 0 -50.56 log_MCPV rotRAnL dead 328 nofield
# RA_G - Ring Anode Ground Cylinder
/sr1/command construct tubs RA_G 58 62.5 58.0 0 360 G4_Cu 0 0 -129.0 log_MCPV norot dead 351 nofield
# Ring Anodes visual attributes (optional)
/sr1/command visattributes log_RA_EU oxsteel
/sr1/command visattributes log_RA_MR oxsteel
/sr1/command visattributes log_RA_G Grid_style
# Alternative placement using World as a mother volume (mcpv_z = -92.5 mm). Check latter. These values refer to a 5 mm GAP!
#/sr1/command construct cones RA_EU 45.1469 62.5 33.5 39.0 22.5 48.1711 83.6578 Steel 0 0 -81 log_World norot dead 301 nofield
#/sr1/command construct cones RA_MU 56.7937 62.5 45.147 62.5 22.5 48.1711 83.6578 Steel 0 0 -126 log_World norot dead 302 nofield
#===============================================================================================================
# Gate Valve Area - Hosts the Ground Anode (upstream part of the Ring Anode) - Delimited by L3F1 and F200 flanges
#===============================================================================================================
# GATS - 200 CF flange upstream of MCP2 tube covering the whole length of the gate valve chamber. For simplicity, we
# choose the INNER diameter of the GATe valve Steel tube the same as the OUTER diameter of F200 (200 CF flange)
/sr1/command construct tubs GATS 103.25 126.5 92.5 0 360 Steel 0 0 -254.5 log_World norot dead 371 nofield
# Vacuum "Ring" (to avoid intersections with MCPV) - Not needed if world is already filled with vacuum.
#*/sr1/command construct tubs GATV 76.5 103.25 92.5 0 360 G4_Galactic 0 0 -254.5 log_World norot dead 370 nofield
# F200 - 200 CF flange upstream of MCP2 tube to connect to gate valve chamber
/sr1/command construct tubs F200 76.5 103.25 12 0 360 Steel 0 0 -174.0 log_World norot dead 372 nofield
# NOTE: When using GATV comment the F200 above and uncomment the following (change mother to log_GATV).
#*/sr1/command construct tubs F200 76.5 103.25 12 0 360 Steel 0 0 80.5 log_GATV norot dead 372 nofield
# Gate Valve Area visual attributes (optional)
/sr1/command visattributes log_GATS SCINT_style
/sr1/command visattributes log_F200 blue_style
#===============================================================================================================
# L3 - 3rd Einzel Lens # L3z = -56.7 cm. ATT: DUMMY FIELD change to electric L3Efield!
#===============================================================================================================
# Lens Gap = 12.0 mm => G/D = 12/130 ~ 0.1 (Lens Gap = gap between Ground and Anode, D - Diameter)
# L3 envelope (Tube + Flanges)
# L3VA - Lens 3 Vacuum
# L3ST - Lens 3 Steel tube (inner dia: 200 mm, outer dia: 206 mm, length: 720 mm)
# L3F1 - Lens 3 Flange 1, z = L3z + 208 mm
# L3F2 - Lens 3 Flange 2, z = L3z - 208 mm
/sr1/command construct tubs L3VA 0 100 220 0 360 G4_Galactic 0 0 -567 log_World norot dead 400 nofield
/sr1/command construct tubs L3ST 100 103 220 0 360 Steel 0 0 -567 log_World norot dead 401 nofield
/sr1/command construct tubs L3F1 103 126.5 12 0 360 Steel 0 0 -359 log_World norot dead 402 nofield
/sr1/command construct tubs L3F2 103 126.5 12 0 360 Steel 0 0 -775 log_World norot dead 403 nofield
# GPn - Ground Potential Electrodes
# n = 1-4 and 5-8 - components of the Ground Electrodes
# GP1 - Ground Electrode (inner dia: 130 mm, outer dia: 134 mm, length: 133 mm)
# GP2 - outer electrode surface (LN2 cooling vessel)
# GP3 - first ring cap
# GP4 - second ring cap
# n = 1-4 - Ground Electrode 1 (further from TD). See above for the meaning of acronyms.
/sr1/command construct tubs L3GP1 65 67 66.5 0 360 Steel 0 0 133.5 log_L3VA norot dead 421 nofield
/sr1/command construct tubs L3GP2 81 83 66.5 0 360 Steel 0 0 133.5 log_L3VA norot dead 422 nofield
/sr1/command construct tubs L3GP3 67 81 4 0 360 Steel 0 0 196.0 log_L3VA norot dead 423 nofield
/sr1/command construct tubs L3GP4 67 81 4 0 360 Steel 0 0 71.0 log_L3VA norot dead 424 nofield
# n = 5-8 - Ground Electrode 2 (closer to TD). See above for the meaning of acronyms.
/sr1/command construct tubs L3GP5 65 67 66.5 0 360 Steel 0 0 -133.5 log_L3VA norot dead 431 nofield
/sr1/command construct tubs L3GP6 81 83 66.5 0 360 Steel 0 0 -133.5 log_L3VA norot dead 432 nofield
/sr1/command construct tubs L3GP7 67 81 4 0 360 Steel 0 0 -196.0 log_L3VA norot dead 433 nofield
/sr1/command construct tubs L3GP8 67 81 4 0 360 Steel 0 0 -71.0 log_L3VA norot dead 434 nofield
# HP - High Potential Electrode (Central Anode - usually at +8.7 kV, for a 15 keV muon beam)
/sr1/command construct tubs L3HP 65 83 55 0 360 Steel 0 0 0 log_L3VA norot dead 451 nofield
# Lens 3 visual attributes (optional)
/sr1/command visattributes log_L3VA invisible
/sr1/command visattributes log_L3ST invisible
/sr1/command visattributes log_L3HP darkred
#===============================================================================================================
# IP - Intermediate Piece (between Trigger Detector and Einzel Lens 3)
# Original name was CGate - B-field Coil Compensation Gate?! # CompGatez = -86.55 cm; // L3z - 22 - 7.85 cm
#===============================================================================================================
# IPV (but also others) are just empty volumes "filled" with vacuum. Sometimes used to apply EM fields to restricted areas.
/sr1/command construct tubs IPV 0 100 78.5 0 360 G4_Galactic 0 0 -865.5 log_World norot dead 500 nofield
# IPCF - Intermediate Piece Central Flange (same as L3 Flanges)
# IPST - Intermediate Piece Steel Tube (same diameter as L3 Steel Tube)
/sr1/command construct tubs IPCF 103 126.5 12.0 0 360 Steel 0 0 -865.5 log_World norot dead 501 nofield
/sr1/command construct tubs IPST 100 103 78.5 0 360 Steel 0 0 -865.5 log_World norot dead 502 nofield
# IP visual attributes (optional)
/sr1/command visattributes log_IPV invisible
/sr1/command visattributes log_IPCF blue_style
/sr1/command visattributes log_IPST gray
#===============================================================================================================
# Trigger - Trigger Detector # Triggerz = -1092 mm
#===============================================================================================================
# Trigger tube and relative vacuum
/sr1/command construct tubs TriggerV 0 100 148 0 360 G4_Galactic 0 0 -1092 log_World norot dead 600 nofield
/sr1/command construct tubs Trigger 100 103 148 0 360 Steel 0 0 -1092 log_World norot dead 601 nofield
# TF - Trigger tube flanges
/sr1/command construct tubs TF1 103 126.5 12 0 360 Steel 0 0 -956 log_World norot dead 611 nofield
/sr1/command construct tubs TF2 103 126.5 12 0 360 Steel 0 0 -1228 log_World norot dead 612 nofield
# Carbon Foil (default HALF-thickness 0.000005147 mm, see below => CFoil thick = 10.3 nm).
# USE THE NAME CFoil or coulombCFoil, otherwise sr1MuFormation won't work!
####/sr1/command construct box CFoil 60 60 0.000005147 G4_GRAPHITE 0 0 -45 log_TriggerV norot dead 621 nofield
/sr1/command construct box CFoil 60 60 0.000006471 G4_GRAPHITE 0 0 -45 log_TriggerV norot dead 621 nofield
####/sr1/command construct box coulombCFoil 60 60 0.000005147 G4_GRAPHITE 0 0 -45 log_TriggerV norot dead 621 nofield
# Notes: NIST tables use G4_GRAPHITE with 1.7 g/cm3 and 78 eV ioniz. energy.
# An area density of 2.20 ug/cm2 implies a CF thickn. = (2.20*1.e-6/1.70)*cm = 1.294e-5 mm - Total thickness
# An area density of 1.75 ug/cm2 implies a CF thickn. = (1.75*1.e-6/1.70)*cm = 1.029e-5 mm - Total thickness
# If necessary, use Graphite as defined in sr1DetectorConstruction.cc and set any density.
# Dummy plane to intercept outgoing muons from the Carbon foil.
/sr1/command construct box saveCFoil 60 60 5e-4 G4_Galactic 0 0 -44.995 log_TriggerV norot dead 623 nofield
# Electrical Field areas in the Trigger Detector
# En = Electrical Field n: TnFieldMgr (n = 1-3)
# Original TriggE2: [4.*sqrt(2), 4.5, 0.7/sqrt(2)] cm -> changed due to overlaps with E1 and E3
/sr1/command construct box TriggE1 45 45 4 G4_Galactic 0 0 -38.5 log_TriggerV norot dead 631 nofield
/sr1/command construct box TriggE2 45 45 4.9497 G4_Galactic 0 0 2.25 log_TriggerV rotTrig dead 632 nofield
/sr1/command construct box TriggE3 45 45 4 G4_Galactic 0 0 43.0 log_TriggerV norot dead 633
# Beam spot (just for having a visual idea!)
/sr1/command construct tubs BSpot 0 20 1 0 360 G4_Galactic 0 0 -48.0 log_TriggerV norot dead 650 nofield
# Trigger visual attributes (optional)
/sr1/command visattributes log_TriggerV invisible
/sr1/command visattributes log_Trigger invisible
#/sr1/command visattributes log_CFoil MACOR_style
/sr1/command visattributes log_BSpot fblue_style
# One can set visible attrib. also on a MATERIAL basis, rather than on log_VOL.
# E.g. /sr1/command visattributes Steel red
################################################################################################################
# -- Setting the ELECTRIC and MAGNETIC fields --
################################################################################################################
# Use ABSOLUTE coordinates to specify the field position (i.e. with respect to GLOBAL WORLD)!
# Default field units: Magnetic - T, Electric - kV/mm (or kV for E-field maps).
# NOTE: Applying a field to an invisible log_vol makes is visible!
### Electric field at TRIGGER Detector TD: Three different uniform fields
/sr1/command globalfield Trigg1_field 0. 0. -1130.5 uniform log_TriggE1 0 0 0 0 0 -0.02375
/sr1/command globalfield Trigg2_field 0. 0. -1089.75 uniform log_TriggE2 0 0 0 0 0 0.041416
/sr1/command globalfield Trigg3_field 0. 0. -1049.0 uniform log_TriggE3 0 0 0 0 0 -0.49375
### Electric field at Einzel LENS 3 - from folded 2D axial field map (f - folded, i.e. symmetric)
# Typically V = +8.7 kV for a muon beam at 15 keV. Use either 2DE L3_Erz.map or
#
# ATTENTION: The electric field is ANTI-symmetric: DO NOT use folded field map L3_Erz4.map!!
#
/sr1/command globalfield Lens3_field 0. 0. -567. fromfile 2DE L3_Erz.map log_L3VA 6.78
# To change the field in regular steps (e.g. for testing) use (f_min f_max step_no), e.g.:
#*/sr1/command globalfield Lens3_field 0. 0. -567. fromfile 2DE L3_Erz.map log_L3VA 7 11 5
### Electric field at RING ANODE - from 3DE field map
# Typically set at +11.0 kV for a muon beam at 15 keV
# To create an arbitrary configuration, switch on all fields and set different potentials.
#######/sr1/command globalfield RngAnU_field 0. 0. -167.00 fromfile 3DE EM_3D_extc.map log_RA_U 11.0
/sr1/command globalfield RngAnU_field 0. 0. -143.00 fromfile 3DE EM_3D_ext_gridf.map log_RA_U 8.6
/sr1/command globalfield RngAnR_field 0. 0. -143.02 fromfile 3DE EM_3D_ext_gridf.map log_RA_R 8.6
/sr1/command globalfield RngAnD_field 0. 0. -143.04 fromfile 3DE EM_3D_ext_gridf.map log_RA_D 8.6
/sr1/command globalfield RngAnL_field 0. 0. -143.06 fromfile 3DE EM_3D_ext_gridf.map log_RA_L 8.6
### LAST FIELD OK: EM_3D_ext2f.map
# EXTENDED MAPS (from -28 to +20 mm) EM_3D_extc.map or EM_3D_extf.map (coord + field or field only)
# "Best" results with EM_RA_3D.map, even though this is not a precise map (poor meshing).
#RA_1kV_upf_raw.map
#RA_1kV_upf.map # EM_extendf2.map give rise to "strange spots" -> sr1_1047_RA13.eps
### Electric field at SAMPLE space. Three possible field maps: Sample, G1 and G2 (closest to sample)
# To create an arbitrary configuration, switch on all fields and set different potentials.
# Field extension along z: 50 mm. Center of MCPV at z = -92.5 mm. Sample face at: z = 108.5 (4 mm thick - SAH2).
# Position of the field: (-92.5 - 50/2) + (108.5 - 4/2) = -11 mm wrt. WORLD! =>
#*/sr1/command globalfield Sample_field 0. 0. -11.0 fromfile 2DE sample_Erz.map log_MCPV 9.0
#*/sr1/command globalfield Guard2_field 0. 0. -11.0 fromfile 2DE guard2_Erz.map log_MCPV 6.0
#*/sr1/command globalfield Guard1_field 0. 0. -11.0 fromfile 2DE guard1_Erz.map log_MCPV 3.0
### Magnetic field at SAMPLE space (use either a uniform field or a field map).
# Use either DMCP or MCPV to apply a CONSTANT field strictly to the sample or also to the surroundings, resp.!
#*/sr1/command globalfield Magnet_field 0. 0. 14.5 uniform log_DMCP 0 0.005 0 0 0 0
# Use field map to set field to 20 G TF
# Extended map has -100/100 cm z extension, field center at +70, original -85/85, center at +85
#######/sr1/command globalfield Magnet_field 0. 0. -836.0 fromfile 2DB sample_Brz.map log_IPV 0.002
#*/sr1/command globalfield Magnet_field 0. 0. -686.0 fromfile 2DB sample_Brz_ext.map log_L3VA 0.002
# Set parameters for particle tracking in an EM field
/sr1/command globalfield setparameter SetLargestAcceptableStep 5
/sr1/command globalfield setparameter SetMinimumEpsilonStep 5e-5
/sr1/command globalfield setparameter SetMaximumEpsilonStep 0.001
/sr1/command globalfield setparameter SetDeltaOneStep 0.1
/sr1/command globalfield setparameter SetDeltaIntersection 0.01
/sr1/command globalfield printparameters
################################################################################################################
# -- Testing the ELECTRIC and MAGNETIC fields (OPTIONAL) --
################################################################################################################
# FIELD CHECKS at different beam transport components (from trigg. to sample)
# All distances in mm and in GLOBAL coordinates (preferably at field center)
# The test points below are just some examples. Any point can be checked.
# Trigger 1
/sr1/command globalfield printFieldValueAtPoint 0. 0. -1130.5
# Trigger 2
/sr1/command globalfield printFieldValueAtPoint 0. 0. -1089.75
# Trigger 3
/sr1/command globalfield printFieldValueAtPoint 0. 0. -1049.0
# Einzel Lens 3 - L3 (center at -567.0, but max field at rel. +/-62 mm)
/sr1/command globalfield printFieldValueAtPoint 0. 0. -507.0
# Ring Anode - RA (center at -167.0, but max field at rel. -16/+132 mm)
/sr1/command globalfield printFieldValueAtPoint 0. 0. -35.0
# Sample space (center at -11.0, but max field at rel. +24 mm)
/sr1/command globalfield printFieldValueAtPoint 0. 0. 13.0
# Check magnetic field at sample space
#*/sr1/command globalfield printFieldValueAtPoint 10. 0. 13.0
# Check magnetic field at the lower field end limit
#*/sr1/command globalfield printFieldValueAtPoint 0. 20. -1680.
################################################################################################################
# -- Setting simulation PARAMETERS --
################################################################################################################
# Set processes from: lowenergy, penelope, coulombAndMultiple (default, Coul. only for CFoil), coulomb (for all, very slow).
/sr1/command typeofprocesses coulombAndMultiple
#*/sr1/command typeofprocesses penelope
#*/sr1/command includeMuoniumProcesses false
# Set the overall range cut (default 0.1 mm)
#*/run/setCut 1 mm
# Set the range cut on particular volumes (in mm)
/sr1/command SetUserLimits log_CFoil 1e-8
#*/sr1/command SetUserLimits log_target 0.01
#*/sr1/command SetUserLimits log_targetscint 0.01
#*/sr1/command SetUserLimits log_cryostatscint 0.01
# Set particle energy cuts on particular volumes (in eV)
/sr1/command SetUserMinEkine log_World 0.1
# Store ALL the events in a ROOT tree or just the interesting ones? (default is true)
#*/sr1/command storeOnlyEventsWithHits false
# Set the minimum time separation between two subsequent signals in the same detector (in ns)
/sr1/command signalSeparationTime 0.1
# Override runID number
#*/sr1/run/runID 21
# Set the frequency of event printing
/sr1/run/howOftenToPrintEvent 1000
# RANDOM option choices: (specify the random number generator initialisation)
# 0 ... no initialisation (default)
# 1 ... use actual computer time to initialise now
# 2 ... use event number to initialise at the beginning of each event
# 3 ... read in the random no. initial values for each event from a file
/sr1/run/randomOption 2
# VISUALIZATION options
# To enable or disable visualization uncomment one of these lines
# To modify visualization options edit the file vis.mac
/vis/disable
#*/control/execute vis.mac
################################################################################################################
# -- Setting PARTICLE GUN parameters --
################################################################################################################
# Default momentum direction: 001, i.e. 0z.
# Default muon spin direction: 100, i.e. 0x.
# Default particle type: mu+ (can be changed to Mu)
# Set particle type
#*/gun/particle Mu
/gun/particle mu+
# Set beam vertex (CFoil at -1137. To start after C Foil use z = -1130, before -1170)
/gun/vertex 0. 0. -1138. mm
# A point-like uniform beam
/gun/vertexsigma -0.1 -0.1 0 mm
# Set beam transverse spread (default GAUSSIAN spread)
# If FWHM = 10 mm ==> sigma = 10/2.354 = 4.2481 mm (last 0 is a dummy value)
# Negative sigma values => random FLAT RECTANGULAR distribution (area 2x.2y)
# Use vertexboundary with (vb < sigma_xy) to obtain a CIRCULAR beam spot
# /gun/vertexsigma 0 0 0 mm ==> Very SLOW with mag. field ON and centered beam
#*/gun/vertexsigma 42.5 42.5 0 mm
/gun/vertexsigma -20 -20 0 mm
/gun/vertexboundary 20 -1e6 1e6 mm
# /gun/vertexboundary: rMaxAllowed, zMinAllowed, zMaxAllowed # Beam AND gating
#*/gun/vertexboundary 7 -1314.4 -1305 mm
# Without restrictions in z, but only on r:
#*/gun/vertexboundary 3 -1e6 1e6 mm
# Set beam momentum (USE only as an ALTERNATIVE to setting energy!)
# /gun/momentum 0 0 29.79 MeV
#*/gun/momentum 0 0 1.8 MeV
# Energy loss at p = 1.2 MeV/c (E = 6.8 keV) => 1.23 +/- 0.2 keV
# Energy loss at p = 1.8 MeV/c (E = 15.3 keV) => 1.25 +/- 0.3 keV
# 1.2 MeV/c -> 6.8 keV, 1.8 MeV/c -> 15.3 keV
# muon rest mass = 105.658 MeV/c2
# With Trigger ON use 15 keV, with Trigger OFF use 11.27 keV (15 - 3.73 = 11.27 keV)
/gun/kenergy 12.0 keV
# Set beam momentum direction
/gun/direction 0.0 0.0 1.0
# Set muon spin direction
/gun/muonPolarizVector 1 0 0
# Other useful test parameters:
#
# FWHM = 3% ==> sigma = 29.79*0.03/2.354 = 0.37965 MeV/c
#*/gun/momentumsmearing 0.37965 MeV
#---/gun/momentumboundary: pMinAllowed, pMaxAllowed, dummy
#*/gun/momentumboundary 20 40 0 MeV
#---/gun/tilt: xangle, yangle, dummy
#*/gun/tilt 0 0.5 0 deg
#---/gun/tiltsigma: xangleSigma, yangleSigma, dummy (1 degree at 1 m => 17 mm)
#*/gun/tiltsigma 0.2 0.2 0 deg
#*/gun/pitch 0.5 deg
#---/gun/decaytimelimits: decayMin, decayMax, decayTime
#*/gun/decaytimelimits 10400 10420 2197.03 ns
# Selectively inactivate or activate sensitive detectors
#*/hits/inactivate /sr1/ScintSD
# Only for code debugging!
#/tracking/verbose 1
# BEAM ON
#*/run/beamOn 1000000
#*/run/beamOn 2
/run/beamOn 10000

View File

@ -0,0 +1,289 @@
# Macro file for sr1.cc - Construct detector, set fields and other parameters.
# Last modified by T. Shiroka: 31.10.2008
# How to run: sr1 10xx.mac (append "idle" for prompt after running)
# sr1 10xx.mac > fname.txt (stores output on a txt file)
###############################################################################################
# #
# Specify the geometry parameters in this file (all dimensions in mm) #
# a. Lines starting with hash marks "#" are comments #
# b Lines starting with #* are temporary comments. Remove/modify to change the configuration #
# c. Lines starting with /sr1/command are commands for the executable program #
# d. Lines starting with /vis, /gun, etc. are common macro commands #
# e. Beam-line components are ordered from exp. area (MCP2) to trigger detector (TD) #
#---------------------------------------------------------------------------------------------#
# Syntax example (following /sr1/command): #
# construct solid_type volume_name parameters_defining_solid material position mothers_name #
# (mothers_name starts with log_) #
###############################################################################################
# For the meaning of the acronyms see also the original G3 file ugeom.F at:
# http://savannah.psi.ch/viewcvs/trunk/simulation/geant3/src/lemsr/ugeom.F?root=nemu%2Flem&rev=2964&view=markup
################################################################################################################
# -- ROTATION MATRICES --
################################################################################################################
# 3 parameters -> Define Euler angles (the 4th par. is set to zero).
# 4 parameters -> Define axis + rotation.
# HEP computations ordinarily use the active rotation viewpoint (object is rotated NOT axes).
# Therefore, rotations about an axis imply ACTIVE COUNTER-CLOCKWISE rotation in this package.
# Rotation around a specified axis means counter-clockwise rot. around the positive direction of the axis.
# Define rotations for the field maps of Trigger and Ring Anode:
/sr1/command rotation rotPole 1 0 0 90
/sr1/command rotation rotTrig 0 1 0 -90
/sr1/command rotation rotRAnR 0 0 1 -90
/sr1/command rotation rotRAnL 0 0 1 90
/sr1/command rotation rotRAnD 0 0 1 180
################################################################################################################
# -- SPIN ROTATOR GEOMETRY --
################################################################################################################
# WORLD = Laboratory reference frame
/sr1/command construct box World 250 250 500 G4_Galactic 0 0 0 no_logical_volume norot dead -1
# World visual attributes (optional)
/sr1/command visattributes log_World invisible
# Electromagnet with iron yoke
# U - up, D - down, L - left, R - right (with respect to muon's view - momentum direction)
/sr1/command construct box YokeU 200 25 50 G4_Fe 0 200 0 log_World norot dead 201 nofield
/sr1/command construct box YokeD 200 25 50 G4_Fe 0 -200 0 log_World norot dead 204 nofield
/sr1/command construct box YokeL 25 175 50 G4_Fe 175 0 0 log_World norot dead 203 nofield
/sr1/command construct box YokeR 25 175 50 G4_Fe -175 0 0 log_World norot dead 202 nofield
/sr1/command construct tubs NPole 0 100 25 0 360 G4_Fe 0 100 0 log_World rotPole dead 211 nofield
/sr1/command construct tubs NYoke 0 50 25 0 360 G4_Fe 0 150 0 log_World rotPole dead 212 nofield
/sr1/command construct tubs NCoil 50 60 25 0 360 G4_Cu 0 150 0 log_World rotPole dead 213 nofield
/sr1/command construct tubs SPole 0 100 25 0 360 G4_Fe 0 -100 0 log_World rotPole dead 221 nofield
/sr1/command construct tubs SYoke 0 50 25 0 360 G4_Fe 0 -150 0 log_World rotPole dead 222 nofield
/sr1/command construct tubs SCoil 50 60 25 0 360 G4_Cu 0 -150 0 log_World rotPole dead 223 nofield
# Capacitor
/sr1/command construct box Cap_p 0.5 50 150 Brass 50 0 0 log_World norot dead 301 nofield
/sr1/command construct box Cap_n 0.5 50 150 Brass -50 0 0 log_World norot dead 302 nofield
#*/sr1/command construct box Uniform 49 49 150 G4_Galactic 0 0 0 log_World norot dead 303 nofield
# Visualize Electric and Magnetic field volumes. COMMENT during normal run, otherwise the root file is empty!
#/sr1/command construct box Evol 50 50 300 G4_Galactic 0 0 0 log_World norot dead 311 nofield
#/sr1/command construct box Bvol 70 70 500 G4_Galactic 0 0 0 log_World norot dead 312 nofield
# Dummy, thin cylindres used for applying the field maps.
# NOTE: EM field cannot be applied to non simply connected bodies, as e.g. rings, cones, tori, etc.!
/sr1/command construct tubs EField 0 0.01 0.005 0 360 G4_Galactic 0 0 0.0 log_World norot dead 322 nofield
/sr1/command construct tubs BField 0 0.01 0.005 0 360 G4_Galactic 0 0 0.1 log_World norot dead 324 nofield
# Beam spot (just for having a visual idea!). Assume r = 3*sigma to intercept 99.73% of all events, with sigma = 6.83 mm
#/sr1/command construct tubs BSpot 0 30 1 0 360 G4_Galactic 0 0 -490 log_World norot dead 650 nofield
/sr1/command construct tubs saveBSpot 0 20.5 1 0 360 G4_Galactic 0 0 -490 log_World norot sr1/ScintSD 650 nofield
# Dummy plane or target to intercept muon events.
# Use it either as (DMCP-sr1/ScintSD) - with no info on mu+ polariz., or as (target-dead) with info on mu+ polariz.
#/sr1/command construct box saveCFoil 65 60 5e-4 G4_Galactic 0 0 -199 log_World norot dead 623 nofield
/sr1/command construct tubs target 0 65 1.5 0 360 G4_Galactic 0 0 490 log_World norot dead 101 nofield
#/sr1/command construct tubs DMCP 0 76.5 1.5 0 360 MCPglass 0 0 108 log_MCPV norot dead 202 nofield
# Visual attributes (optional)
/sr1/command visattributes log_NPole red
/sr1/command visattributes log_SPole lightblue
/sr1/command visattributes log_NCoil Grid_style
/sr1/command visattributes log_SCoil Grid_style
/sr1/command visattributes log_YokeR oxsteel
/sr1/command visattributes log_Cap_p darkred
/sr1/command visattributes log_Cap_n blue_style
#/sr1/command visattributes log_Uniform invisible
################################################################################################################
# -- Setting the ELECTRIC and MAGNETIC fields --
################################################################################################################
# Use ABSOLUTE coordinates to specify the field position (i.e. with respect to GLOBAL WORLD)!
# Default field units: Magnetic - T, Electric - kV/mm (or kV for E-field maps).
# NOTE: Applying a field to an invisible log_vol makes is visible!
### Uniform Electric and Magnetic field at Spin Rotator:
#*/sr1/command globalfield UniMag_field 0. 0. 0. uniform log_Uniform 0 -0.036 0 0 0 0
#*/sr1/command globalfield UniEle_field 0. 0. 0. uniform log_Uniform 0 0 0 -0.21 0 0
#*/sr1/command globalfield UniEM_field 0. 0. 0. uniform log_Uniform 0 -0.036 0 -0.21 0 0
###15 cm gap /sr1/command globalfield Ele_field 0. 0. 0. fromfile 3DE E3D_capacitor.map log_EField 22.1
###1000-0 V /sr1/command globalfield Ele_field 0. 0. 0. fromfile 3DE E3D_capacitor.map log_EField 14.74
#*/sr1/command globalfield Ele_field 0. 0. 0. fromfile 3DE E3D_const.map log_EField 21.0
## Symmetric field map +/- 500 V.
/sr1/command globalfield Ele_field 0. 0. 0. fromfile 3DE E3D_cap_symm.map log_EField 21.0
/sr1/command globalfield Mag_field 0. 0. 0.1 fromfile 3DB B3D_iron2.map log_BField 0.036
# Set parameters for particle tracking in an EM field
/sr1/command globalfield setparameter SetLargestAcceptableStep 5
/sr1/command globalfield setparameter SetMinimumEpsilonStep 5e-5
/sr1/command globalfield setparameter SetMaximumEpsilonStep 0.001
/sr1/command globalfield setparameter SetDeltaOneStep 0.1
/sr1/command globalfield setparameter SetDeltaIntersection 0.01
/sr1/command globalfield printparameters
# TESTING EM FIELD
/sr1/command globalfield printFieldValueAtPoint 0. 0. 0.
################################################################################################################
# -- Setting simulation PARAMETERS --
################################################################################################################
# Set processes from: lowenergy, penelope, coulombAndMultiple (default, Coul. only for CFoil), coulomb (for all, very slow).
#**/sr1/command typeofprocesses coulombAndMultiple
#*/sr1/command typeofprocesses penelope
#*/sr1/command includeMuoniumProcesses false
# Set the overall range cut (default 0.1 mm)
#*/run/setCut 1 mm
# Set the range cut on particular volumes (in mm)
#*/sr1/command SetUserLimits log_target 0.01
#*/sr1/command SetUserLimits log_targetscint 0.01
#*/sr1/command SetUserLimits log_cryostatscint 0.01
# Set particle energy cuts on particular volumes (in eV)
#*/sr1/command SetUserMinEkine log_World 0.1
# Store ALL the events in a ROOT tree or just the interesting ones? (default is true)
#*/sr1/command storeOnlyEventsWithHits false
# Set the minimum time separation between two subsequent signals in the same detector (in ns)
/sr1/command signalSeparationTime 0.1
# Override runID number
#*/sr1/run/runID 21
# Set the frequency of event printing
/sr1/run/howOftenToPrintEvent 1000
# RANDOM option choices: (specify the random number generator initialisation)
# 0 ... no initialisation (default)
# 1 ... use actual computer time to initialise now # Pseudo-random numbers
# 2 ... use event number to initialise at the beginning of each event # Reproducible numbers
# 3 ... read in the random no. initial values for each event from a file
/sr1/run/randomOption 1
# VISUALIZATION options
# To enable or disable visualization uncomment one of these lines
# To modify visualization options edit the file vis.mac
/vis/disable
#*/control/execute vis.mac
#alias g4='export G4WORKDIR="/home/sedlak/bin_4.9.1"; source /home/geant4/4.9.1/env.sh;
#export G4VRMLFILE_VIEWER="vrmlview"; echo "On this machine the G4VRMLFILE_VIEWER=$G4VRMLFILE_VIEWER"'
################################################################################################################
# -- Setting PARTICLE GUN parameters --
################################################################################################################
# Default momentum direction: 001, i.e. 0z.
# Default muon spin direction: 100, i.e. 0x.
# Default particle type: mu+ (can be changed to Mu or proton)
# Set particle type
#*/gun/particle Mu
#*/gun/particle proton
/gun/particle mu+
# Set the position of the beam vertex
/gun/vertex 0. 0. -495. mm
# A point-like uniform beam
#*/gun/vertexsigma -0.1 -0.1 0 mm
# Set beam transverse spread (default GAUSSIAN spread)
# If FWHM = 10 mm ==> sigma = 10/2.354 = 4.2481 mm (last 0 is a dummy value)
# Negative sigma values => random FLAT RECTANGULAR distribution (area 2x.2y)
# Use vertexboundary with (vb < sigma_xy) to obtain a CIRCULAR beam spot
# /gun/vertexsigma 0 0 0 mm ==> Very SLOW with mag. field ON and centered beam
## The LEMUSR beam has a sigma of 6.83 mm => FWHM = 2.355*6.83 = 16.08 mm
/gun/vertexsigma 6.83 6.83 0 mm
#/gun/vertexsigma -20 -20 0 mm
#/gun/vertexboundary 20 -1e6 1e6 mm
# /gun/vertexboundary: rMaxAllowed, zMinAllowed, zMaxAllowed # Beam AND gating
#*/gun/vertexboundary 7 -1314.4 -1305 mm
# Without restrictions in z, but only on r:
#*/gun/vertexboundary 3 -1e6 1e6 mm
# Set beam momentum (USE only as an ALTERNATIVE to setting energy!)
# /gun/momentum 0 0 29.79 MeV
#*/gun/momentum 0 0 1.8 MeV
# Energy loss at p = 1.2 MeV/c (E = 6.8 keV) => 1.23 +/- 0.2 keV
# Energy loss at p = 1.8 MeV/c (E = 15.3 keV) => 1.25 +/- 0.3 keV
# 1.2 MeV/c -> 6.8 keV, 1.8 MeV/c -> 15.3 keV, 2.056 MeV/c -> 20 keV.
# muon rest mass = 105.658 MeV/c2
# With Trigger ON use 15 keV, with Trigger OFF use 11.27 keV (15 - 3.73 = 11.27 keV)
#/gun/kenergy 3.4 MeV
/gun/kenergy 16.27 keV
# Set beam momentum direction
/gun/direction 0.0 0.0 1.0
# Set muon spin direction
/gun/muonPolarizVector 1 0 0
# Other useful test parameters:
#
# FWHM = 3% ==> sigma = 29.79*0.03/2.354 = 0.37965 MeV/c
#*/gun/momentumsmearing 0.37965 MeV
#---/gun/momentumboundary: pMinAllowed, pMaxAllowed, dummy
#*/gun/momentumboundary 20 40 0 MeV
#---/gun/tilt: xangle, yangle, dummy
#*/gun/tilt 0 0.5 0 deg
#---/gun/tiltsigma: xangleSigma, yangleSigma, dummy (1 degree at 1 m => 17 mm)
#*/gun/tiltsigma 0.2 0.2 0 deg
#*/gun/pitch 0.5 deg
#---/gun/decaytimelimits: decayMin, decayMax, decayTime
#*/gun/decaytimelimits 10400 10420 2197.03 ns
# Selectively inactivate or activate sensitive detectors
#*/hits/inactivate /sr1/ScintSD
# Only for code debugging!
#/tracking/verbose 1
# BEAM ON
#*/run/beamOn 1000000
#/run/beamOn 2
#/run/beamOn 1000000
/run/beamOn 5000

View File

@ -0,0 +1,367 @@
# Macro file for sr1.cc - Construct detector, set fields and other parameters.
# Last modified by T. Shiroka: 31.10.2008
# How to run: sr1 10xx.mac (append "idle" for prompt after running)
# sr1 10xx.mac > fname.txt (stores output on a txt file)
###############################################################################################
# #
# Specify the geometry parameters in this file (all dimensions in mm) #
# a. Lines starting with hash marks "#" are comments #
# b Lines starting with #* are temporary comments. Remove/modify to change the configuration #
# c. Lines starting with /sr1/command are commands for the executable program #
# d. Lines starting with /vis, /gun, etc. are common macro commands #
# e. Beam-line components are ordered from exp. area (MCP2) to trigger detector (TD) #
#---------------------------------------------------------------------------------------------#
# Syntax example (following /sr1/command): #
# construct solid_type volume_name parameters_defining_solid material position mothers_name #
# (mothers_name starts with log_) #
###############################################################################################
# For the meaning of the acronyms see also the original G3 file ugeom.F at:
# http://savannah.psi.ch/viewcvs/trunk/simulation/geant3/src/lemsr/ugeom.F?root=nemu%2Flem&rev=2964&view=markup
################################################################################################################
# -- ROTATION MATRICES --
################################################################################################################
# 3 parameters -> Define Euler angles (the 4th par. is set to zero).
# 4 parameters -> Define axis + rotation.
# HEP computations ordinarily use the active rotation viewpoint (object is rotated NOT axes).
# Therefore, rotations about an axis imply ACTIVE COUNTER-CLOCKWISE rotation in this package.
# Rotation around a specified axis means counter-clockwise rot. around the positive direction of the axis.
# Define rotations for the field maps of Trigger and Ring Anode:
/sr1/command rotation rotPole 1 0 0 90
/sr1/command rotation rotTrig 0 1 0 -90
/sr1/command rotation rotRAnR 0 0 1 -90
/sr1/command rotation rotRAnL 0 0 1 90
/sr1/command rotation rotRAnD 0 0 1 180
################################################################################################################
# -- SPIN ROTATOR GEOMETRY --
################################################################################################################
# WORLD = Laboratory reference frame
/sr1/command construct box World 350 250 900 G4_Galactic 0 0 0 no_logical_volume norot dead -1
# World visual attributes (optional)
/sr1/command visattributes log_World invisible
# Electromagnet with iron yoke
# U - up, D - down, L - left, R - right (with respect to muon's view - momentum direction)
/sr1/command construct box NPole 200 20 150 G4_Fe 0 95 0 log_World norot dead 201 nofield
/sr1/command construct box NYoke 150 30 50 G4_Fe 0 145 0 log_World norot dead 202 nofield
/sr1/command construct box NConn 75 17.5 50 G4_Fe 225 157.5 0 log_World norot dead 203 nofield
/sr1/command construct box YokeL 25 175 50 G4_Fe 325 0 0 log_World norot dead 210 nofield
/sr1/command construct box SPole 200 20 150 G4_Fe 0 -95 0 log_World norot dead 205 nofield
/sr1/command construct box SYoke 150 30 50 G4_Fe 0 -145 0 log_World norot dead 206 nofield
/sr1/command construct box SConn 75 17.5 50 G4_Fe 225 -157.5 0 log_World norot dead 207 nofield
# Front shield
/sr1/command construct box FShU 225 50 5 G4_Fe 0 125 -175 log_World norot dead 301 nofield
/sr1/command construct box FShD 225 50 5 G4_Fe 0 -125 -175 log_World norot dead 302 nofield
/sr1/command construct box FShL 75 75 5 G4_Fe 150 0 -175 log_World norot dead 303 nofield
/sr1/command construct box FShR 75 75 5 G4_Fe -150 0 -175 log_World norot dead 304 nofield
# Back shield
/sr1/command construct box BShU 225 50 5 G4_Fe 0 125 175 log_World norot dead 321 nofield
/sr1/command construct box BShD 225 50 5 G4_Fe 0 -125 175 log_World norot dead 322 nofield
/sr1/command construct box BShL 75 75 5 G4_Fe 150 0 175 log_World norot dead 323 nofield
/sr1/command construct box BShR 75 75 5 G4_Fe -150 0 175 log_World norot dead 324 nofield
# Top coils
/sr1/command construct box TCoil1 170 12.5 10 G4_Cu 0 127.5 -60 log_World norot dead 401 nofield
/sr1/command construct box TCoil2 170 12.5 10 G4_Cu 0 127.5 60 log_World norot dead 402 nofield
/sr1/command construct box TCoil3 10 12.5 50 G4_Cu 160 127.5 0 log_World norot dead 403 nofield
/sr1/command construct box TCoil4 10 12.5 50 G4_Cu -160 127.5 0 log_World norot dead 404 nofield
# Bottom coils
/sr1/command construct box BCoil1 170 12.5 10 G4_Cu 0 -127.5 -60 log_World norot dead 421 nofield
/sr1/command construct box BCoil2 170 12.5 10 G4_Cu 0 -127.5 60 log_World norot dead 422 nofield
/sr1/command construct box BCoil3 10 12.5 50 G4_Cu 160 -127.5 0 log_World norot dead 423 nofield
/sr1/command construct box BCoil4 10 12.5 50 G4_Cu -160 -127.5 0 log_World norot dead 424 nofield
# Capacitor
/sr1/command construct box Cap_p 0.5 50 150 Brass 50 0 0 log_World norot dead 501 nofield
/sr1/command construct box Cap_n 0.5 50 150 Brass -50 0 0 log_World norot dead 502 nofield
#*/sr1/command construct box Uniform 49 49 150 G4_Galactic 0 0 0 log_World norot dead 503 nofield
# Lens 1 - 1st Einzel Lens # L1z = -(38 + 25) = -63 cm.
# Gap = 10.0 mm => G/D = 10/80 = 0.125 (Lens Gap = gap between Ground and Anode, D - Diameter)
# L1ENV - Lens 1 envelope - for easy positioning of lens parts (outer dia: 100 mm, length: 300 mm)
/sr1/command construct tubs L1ENV 0 50 150 0 360 G4_Galactic 0 0 -630 log_World norot dead 600 nofield
# GPn - Ground Potential Electrodes. (n = 1-2, inner dia: 80 mm, outer dia: 84 mm, length: 100 mm)
# n = 1 - Ground Electrode 1 (further from SR).
/sr1/command construct tubs L1GP1 40 44 50 0 360 Steel 0 0 -100 log_L1ENV norot dead 651 nofield
# n = 2 - Ground Electrode 2 (closer to SR).
/sr1/command construct tubs L1GP2 40 44 50 0 360 Steel 0 0 100 log_L1ENV norot dead 653 nofield
# HP - High Potential Electrode (Central Anode - usually at +8.5 kV, for a 15 keV muon beam)
/sr1/command construct tubs L1HP 40 44 40 0 360 Steel 0 0 0 log_L1ENV norot dead 652 nofield
# Lens 1 visual attributes (optional)
/sr1/command visattributes log_L1ENV invisible
/sr1/command visattributes log_L1HP darkred
# Dummy, thin cylindres used for applying the field maps.
# NOTE: EM field cannot be applied to non simply connected bodies, as e.g. rings, cones, tori, etc.!
/sr1/command construct tubs EField 0 0.01 0.005 0 360 G4_Galactic 0 0 0.0 log_World norot dead 702 nofield
/sr1/command construct tubs BField 0 0.01 0.005 0 360 G4_Galactic 0 0 0.1 log_World norot dead 704 nofield
/sr1/command construct tubs LField 0 0.01 0.005 0 360 G4_Galactic 0 0 0.0 log_L1ENV norot dead 706 nofield
# Visualize Electric and Magnetic field volumes. COMMENT during normal run, otherwise the root file is empty!
#*/sr1/command construct box Evol 50 50 300 G4_Galactic 0 0 0 log_World norot dead 752 nofield
#*/sr1/command construct box Bvol 70 70 500 G4_Galactic 0 0 0 log_World norot dead 754 nofield
#*/sr1/command construct tubs Lvol 0 38 180 0 360 G4_Galactic 0 0 -630 log_World norot dead 756 nofield
# Beam spot (just for having a visual idea!).
# Assume r = 3*sigma to intercept 99.73% of all events, with sigma = 6.83 mm
#/sr1/command construct tubs BSpot 0 30 1 0 360 G4_Galactic 0 0 -490 log_World norot dead 800 nofield
#*/sr1/command construct tubs saveBSpot 0 20.5 1 0 360 G4_Galactic 0 0 -490 log_World norot sr1/ScintSD 800 nofield
/sr1/command construct tubs saveBSpot 0 20.5 1 0 360 G4_Galactic 0 0 -835 log_World norot sr1/ScintSD 800 nofield
# Dummy plane or target to intercept muon events.
# Use it either as (DMCP-sr1/ScintSD) - with no info on mu+ polariz., or as (target-dead) with info on mu+ polariz.
#/sr1/command construct box saveCFoil 65 60 5e-4 G4_Galactic 0 0 -199 log_World norot dead 851 nofield
/sr1/command construct tubs target 0 65 1.5 0 360 G4_Galactic 0 0 490 log_World norot dead 851 nofield
/sr1/command construct tubs saveIT 0 40 1 0 360 G4_Galactic 0 0 -300 log_World norot sr1/ScintSD 900 nofield
# Visual attributes (optional)
/sr1/command visattributes log_NPole red
/sr1/command visattributes log_SPole lightblue
#/sr1/command visattributes log_NCoil Grid_style
#/sr1/command visattributes log_SCoil Grid_style
/sr1/command visattributes log_YokeL oxsteel
/sr1/command visattributes log_TCoil1 Grid_style
/sr1/command visattributes log_TCoil2 Grid_style
/sr1/command visattributes log_TCoil3 Grid_style
/sr1/command visattributes log_TCoil4 Grid_style
/sr1/command visattributes log_BCoil1 Grid_style
/sr1/command visattributes log_BCoil2 Grid_style
/sr1/command visattributes log_BCoil3 Grid_style
/sr1/command visattributes log_BCoil4 Grid_style
/sr1/command visattributes log_Cap_p darkred
/sr1/command visattributes log_Cap_n blue_style
#/sr1/command visattributes log_Uniform invisible
################################################################################################################
# -- Setting the ELECTRIC and MAGNETIC fields --
################################################################################################################
# Use ABSOLUTE coordinates to specify the field position (i.e. with respect to GLOBAL WORLD)!
# Default field units: Magnetic - T, Electric - kV/mm (or kV for E-field maps).
# NOTE: Applying a field to an invisible log_vol makes is visible!
### Uniform Electric and Magnetic field at Spin Rotator:
#*/sr1/command globalfield UniMag_field 0. 0. 0. uniform log_Uniform 0 -0.036 0 0 0 0
#*/sr1/command globalfield UniEle_field 0. 0. 0. uniform log_Uniform 0 0 0 -0.21 0 0
#*/sr1/command globalfield UniEM_field 0. 0. 0. uniform log_Uniform 0 -0.036 0 -0.21 0 0
###15 cm gap /sr1/command globalfield Ele_field 0. 0. 0. fromfile 3DE E3D_capacitor.map log_EField 22.1
###1000-0 V /sr1/command globalfield Ele_field 0. 0. 0. fromfile 3DE E3D_capacitor.map log_EField 14.74
# E_0 = 20 keV, E = 21 kV, B = 360 G
# E_0 = 15 keV, E = 18.1865 kV, B = 311.7691 G (= sqrt(15/20))
# CONSTANT Electric and Magnetic fields (15 keV 15.7 0.0312 T; 20 keV 21.0 0.036 T) (16.6 if with B map)
#/sr1/command globalfield Ele_field 0. 0. 0. fromfile 3DE E3D_const.map log_EField 16.6
#/sr1/command globalfield Mag_field 0. 0. 0.1 fromfile 3DB B3D_const.map log_BField 0.03117691
# FIELD MAPS (using symmetric E-field map +/- 500 V). E3D_cap_symm.map or E3D_cap_symm_edge.map
# E0 = 20 keV
#*/sr1/command globalfield Ele_field 0. 0. 0. fromfile 3DE E3D_cap_symm_edge.map log_EField 21.0
#*/sr1/command globalfield Mag_field 0. 0. 0.1 fromfile 3DB B3D_iron2.map log_BField 0.036
# E0 = 15 keV
#/sr1/command globalfield Ele_field 0. 0. 0. fromfile 3DE E3D_cap_symm_edge.map log_EField 15.8
/sr1/command globalfield Ele_field 0. 0. 0. fromfile 3DE E3D_edge_rod.map log_EField 15.9
#*/sr1/command globalfield Ele_field 0. 0. 0. fromfile 3DE E3D_edge_3rods.map log_EField 15.2
/sr1/command globalfield Mag_field 0. 0. 0.1 fromfile 3DB B3D_iron2.map log_BField 0.0312
# LENS 1. Best L1 settings: 8.5 kV for 15 keV muons, 11.33 kV for 20 keV muons
/sr1/command globalfield L1E_field 0. 0. -630 fromfile 2DE L1_Erz.map log_L1ENV 0.
# Set parameters for particle tracking in an EM field
/sr1/command globalfield setparameter SetLargestAcceptableStep 5
/sr1/command globalfield setparameter SetMinimumEpsilonStep 5e-5
/sr1/command globalfield setparameter SetMaximumEpsilonStep 0.001
/sr1/command globalfield setparameter SetDeltaOneStep 0.1
/sr1/command globalfield setparameter SetDeltaIntersection 0.01
/sr1/command globalfield printparameters
# TESTING EM FIELD
/sr1/command globalfield printFieldValueAtPoint 0. 0. 0.
/sr1/command globalfield printFieldValueAtPoint 0. 35. -670.
################################################################################################################
# -- Setting simulation PARAMETERS --
################################################################################################################
# Set processes from: lowenergy, penelope, coulombAndMultiple (default, Coul. only for CFoil), coulomb (for all, very slow).
#**/sr1/command typeofprocesses coulombAndMultiple
#*/sr1/command typeofprocesses penelope
#*/sr1/command includeMuoniumProcesses false
# Set the overall range cut (default 0.1 mm)
#*/run/setCut 1 mm
# Set the range cut on particular volumes (in mm)
#*/sr1/command SetUserLimits log_target 0.01
#*/sr1/command SetUserLimits log_targetscint 0.01
#*/sr1/command SetUserLimits log_cryostatscint 0.01
# Set particle energy cuts on particular volumes (in eV)
#*/sr1/command SetUserMinEkine log_World 0.1
# Store ALL the events in a ROOT tree or just the interesting ones? (default is true)
#*/sr1/command storeOnlyEventsWithHits false
# Set the minimum time separation between two subsequent signals in the same detector (in ns)
/sr1/command signalSeparationTime 0.1
# Override runID number
#*/sr1/run/runID 21
# Set the frequency of event printing
/sr1/run/howOftenToPrintEvent 1000
# RANDOM option choices: (specify the random number generator initialisation)
# 0 ... no initialisation (default)
# 1 ... use actual computer time to initialise now # Pseudo-random numbers
# 2 ... use event number to initialise at the beginning of each event # Reproducible numbers
# 3 ... read in the random no. initial values for each event from a file
/sr1/run/randomOption 2
# VISUALIZATION options
# To enable or disable visualization uncomment one of these lines
# To modify visualization options edit the file vis.mac
/vis/disable
#*/control/execute vis.mac
#alias g4='export G4WORKDIR="/home/sedlak/bin_4.9.1"; source /home/geant4/4.9.1/env.sh;
#export G4VRMLFILE_VIEWER="vrmlview"; echo "On this machine the G4VRMLFILE_VIEWER=$G4VRMLFILE_VIEWER"'
################################################################################################################
# -- Setting PARTICLE GUN parameters --
################################################################################################################
# Default momentum direction: 001, i.e. 0z.
# Default muon spin direction: 100, i.e. 0x.
# Default particle type: mu+ (can be changed to Mu or proton)
# Set particle type
#*/gun/particle Mu
#*/gun/particle proton
/gun/particle mu+
# Set the position of the beam vertex
# For use only with SR: d = -495 mm, when L1 is included d = -835 mm.
#/gun/vertex 0. 0. -495. mm
/gun/vertex 0. 0. -835. mm
# A point-like uniform beam
#*/gun/vertexsigma -0.1 -0.1 0 mm
# Set beam transverse spread (default GAUSSIAN spread)
# If FWHM = 10 mm ==> sigma = 10/2.354 = 4.2481 mm (last 0 is a dummy value)
# Negative sigma values => random FLAT RECTANGULAR distribution (area 2x.2y)
# Use vertexboundary with (vb < sigma_xy) to obtain a CIRCULAR beam spot
# /gun/vertexsigma 0 0 0 mm ==> Very SLOW with mag. field ON and centered beam
## The LEMUSR beam has a sigma of 6.83 mm => FWHM = 2.355*6.83 = 16.08 mm
/gun/vertexsigma 6.83 6.83 0 mm
#/gun/vertexsigma -20 -20 0 mm
#/gun/vertexboundary 20 -1e6 1e6 mm
# /gun/vertexboundary: rMaxAllowed, zMinAllowed, zMaxAllowed # Beam AND gating
#*/gun/vertexboundary 7 -1314.4 -1305 mm
# Without restrictions in z, but only on r:
#*/gun/vertexboundary 3 -1e6 1e6 mm
# Set beam momentum (USE only as an ALTERNATIVE to setting energy!)
# /gun/momentum 0 0 29.79 MeV
#*/gun/momentum 0 0 1.8 MeV
# Energy loss at p = 1.2 MeV/c (E = 6.8 keV) => 1.23 +/- 0.2 keV
# Energy loss at p = 1.8 MeV/c (E = 15.3 keV) => 1.25 +/- 0.3 keV
# 1.2 MeV/c -> 6.8 keV, 1.8 MeV/c -> 15.3 keV, 2.056 MeV/c -> 20 keV.
# muon rest mass = 105.658 MeV/c2
#/gun/kenergy 3.4 MeV
/gun/kenergy 15.0 keV
# Set beam momentum direction
/gun/direction 0.0 0.0 1.0
# Set muon spin direction
/gun/muonPolarizVector 1 0 0
# Other useful test parameters:
#
# FWHM = 3% ==> sigma = 29.79*0.03/2.354 = 0.37965 MeV/c
#*/gun/momentumsmearing 0.37965 MeV
#---/gun/momentumboundary: pMinAllowed, pMaxAllowed, dummy
#*/gun/momentumboundary 20 40 0 MeV
#---/gun/tilt: xangle, yangle, dummy
#*/gun/tilt 0 0.5 0 deg
#---/gun/tiltsigma: xangleSigma, yangleSigma, dummy (1 degree at 1 m => 17 mm)
/gun/tiltsigma 1.4 1.4 0 deg
#*/gun/pitch 0.5 deg
#---/gun/decaytimelimits: decayMin, decayMax, decayTime
#*/gun/decaytimelimits 10400 10420 2197.03 ns
# Selectively inactivate or activate sensitive detectors
#*/hits/inactivate /sr1/ScintSD
# Only for code debugging!
#/tracking/verbose 1
# For running a batch see the files v1.mac and changefield.mac in /home/l_shiroka/geant4/musim_alc2
# BEAM ON
#*/run/beamOn 1000000
#*/run/beamOn 2
#/run/beamOn 1000000
/run/beamOn 10000

View File

@ -0,0 +1,14 @@
2 2 2 cm 1
% nx ny nz length_unit norm_fact
% Bx(T) By(T) Bz (T)
% A norm_fact 1 means that the magnetic field is expressed in Tesla.
%
% x(cm) y(cm) z(cm) Bx_emqv(V/m) By_emqv(V/m) Bz_emqv(V/m)
-4.9 -4.9 -15.0 0 -1 0
-4.9 -4.9 15.0 0 -1 0
-4.9 4.9 -15.0 0 -1 0
-4.9 4.9 15.0 0 -1 0
4.9 -4.9 -15.0 0 -1 0
4.9 -4.9 15.0 0 -1 0
4.9 4.9 -15.0 0 -1 0
4.9 4.9 15.0 0 -1 0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
2 2 2 cm 1e-4
%nx ny nz length_unit norm_fact
% Ex (V/m) Ey(V/m) Ez (V/m)
% A norm_fact 1e-6 converts V/m (FL) to kV/mm (G4).
% This FemLab model uses cm, therefore norm_fact = norm_fact*1e2.
%
% Exported from capacitor.fl
% x(cm) y(cm) z(cm) Ex_emqv(V/m) Ey_emqv(V/m) Ez_emqv(V/m)
-4.9 -4.9 -15.0 -100 0 0
-4.9 -4.9 15.0 -100 0 0
-4.9 4.9 -15.0 -100 0 0
-4.9 4.9 15.0 -100 0 0
4.9 -4.9 -15.0 -100 0 0
4.9 -4.9 15.0 -100 0 0
4.9 4.9 -15.0 -100 0 0
4.9 4.9 15.0 -100 0 0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,191 @@
#define analysis_cxx
#include "analysis.h"
#include <TH2.h>
#include <TStyle.h>
#include <TCanvas.h>
void analysis::Loop()
{
// In a ROOT session, you can do:
// Root > .L analysis.C
// Root > analysis t
// Root > t.GetEntry(12); // Fill t data members with entry number 12
// Root > t.Show(); // Show values of entry 12
// Root > t.Show(16); // Read and show values of entry 16
// Root > t.Loop(); // Loop on all entries <- Very Important!
// Root > .ls // Shows what histos are available for plotting
//
// This is the loop skeleton where:
// jentry is the global entry number in the chain
// ientry is the entry number in the current Tree
// Note that the argument to GetEntry must be:
// jentry for TChain::GetEntry
// ientry for TTree::GetEntry and TBranch::GetEntry
//
// To read only selected branches, insert statements as:
// METHOD1:
// fChain->SetBranchStatus("*",0); // disable all branches
// fChain->SetBranchStatus("branchname",1); // activate branchname
// METHOD2: replace line
// fChain->GetEntry(jentry); //read all branches
// b_branchname->GetEntry(ientry); //read only this branch
//
//
// To create TEMPLATE files for analysis proceed as follows:
// 1. Load the root file containing all the variables, e.g.:
// TFile* f=new TFile("data/lem4_1049.root");
// 2. Quickly check the Tree and Variable names:
// f->ls(); // Shows tree name (i.e. t1)
// t1->Print(); // Shows variable names
// 3. Create the template files .C and .h (t1 is the Tree name)
// t1->MakeClass("myAnalysis")
//
//
// How to write data to an EXTERNAL file (use cout instead of outdata for printing on screen):
// See also: www.bgsu.edu/departments/compsci/docs/index.html
//
// ofstream outdata;
// outdata.open("export.dat");
// for (Int_t i=0; i<hEdepositCF->GetNbinsX(); i++) {outdata<<hEdepositCF->GetBinContent(i)<<endl;}
// outdata.close();
//
if (fChain == 0) return;
//DEFINE HISTOGRAMS
TH1F* hEdeposited = new TH1F("hEdeposited","Energy spectrum; E [MeV]", 250,0.,2.5);
TH1F* hEdepositCF = new TH1F("hEdepositCF","Energy spectrum; E [MeV]", 250,0.,3.0);
TH1F* hEdepTrig = new TH1F("hEdepTrig", "Radioactive electron kin. energy",250,0.,2.5);
TH1F* hDettUp = new TH1F("hDettUp", "Muon arrival times Up (#mus)", 250,0.,10);
TH1F* hDettDown = new TH1F("hDettDown", "Muon arrival times Down (#mus)", 250,0.,10);
TH1F* hDettRight = new TH1F("hDettRight", "Muon arrival times Right (#mus)", 250,0.,10);
TH1F* hDettLeft = new TH1F("hDettLeft", "Muon arrival times Left (#mus)", 250,0.,10);
TH1F* hEdepoTest = new TH1F("hEdepoTest", "Number of events in coincidence", 100,0.,1.);
hEdeposited->Sumw2();
hEdepositCF->Sumw2();
hEdepTrig->Sumw2();
Long64_t nentries = fChain->GetEntriesFast();
//nentries=1000;
Long64_t nbytes = 0, nb = 0;
for (Long64_t jentry=0; jentry<nentries;jentry++) {
Long64_t ientry = LoadTree(jentry);
if (ientry < 0) break;
nb = fChain->GetEntry(jentry); nbytes += nb;
// FILL IN HISTOGRAMS
// ATTENTION: change 11.27 to the starting muon energy:
hEdepositCF->Fill(11.27 + 3.73-save_ke[0]/1e3);
//for (Int_t i=0; i<det_n; i++)
// { if (det_ID[i]==623) { hEdeposited->Fill(save_ke[i]);}
// }
// Coincidence between Up scintillators
for (Int_t i=0; i<det_n; i++) {
if (det_ID[i]==21) {
for (Int_t j=0; j<det_n; j++)
if (det_ID[j]==11) {
hDettUp->Fill(det_time_start[j]);
///hEdeposited->Fill(det_edep[i]);
// if (electronEscaped[i]) {
// hEdepTrig->Fill(det_edep[i]);
// }
}
}
}
// Coincidence between Down scintillators
for (Int_t i=0; i<det_n; i++) {
if (det_ID[i]==23) {
for (Int_t j=0; j<det_n; j++)
if (det_ID[j]==13) {
hDettDown->Fill(det_time_start[j]);
}
}
}
// Coincidence between Right scintillators
for (Int_t i=0; i<det_n; i++) {
if (det_ID[i]==22) {
for (Int_t j=0; j<det_n; j++)
if (det_ID[j]==12) {
hDettRight->Fill(det_time_start[j]);
}
}
}
// Coincidence between Left scintillators
for (Int_t i=0; i<det_n; i++) {
if (det_ID[i]==24) {
for (Int_t j=0; j<det_n; j++)
if (det_ID[j]==14) {
hDettLeft->Fill(det_time_start[j]);
}
}
}
// Testing event coincidence with SciFi
Bool_t twentyone= false;
Bool_t twozero7 = false;
Bool_t twozero8 = false;
Int_t ikk=0;
for (Int_t i=0; i<det_n; i++) {
if ((det_ID[i]== 21)&&(det_edep[i]>0.0)) {twentyone = true; ikk = i;}
if ((det_ID[i]==207)&&(det_edep[i]>0.0)) twozero7 = true;
if ((det_ID[i]==208)&&(det_edep[i]>0.0)) twozero8 = true;
}
//if (twentyone) hEdepoTest->Fill(det_edep[ikk]); // Fiber hits
//if (twozero7&& twozero8) hEdepoTest->Fill(det_edep[ikk]); // Coincidence
if (twentyone&&twozero7&& twozero8) hEdepoTest->Fill(det_edep[ikk]); // Fibre hits + coincidence
}
// PLOT HISTOGRAMS
TCanvas* c1= new TCanvas("c1","canvas 1");
// hEdeposited->Scale(1/(number_of_generated_events*hEdeposited->GetBinWidth(1)));
TH1F *htemp1 = (TH1F*) hDettUp->Clone(); htemp1->SetName("htemp1");
TH1F *htemp2 = (TH1F*) hDettUp->Clone(); htemp2->SetName("htemp2");
TH1F *htemp3 = (TH1F*) hDettUp->Clone(); htemp3->SetName("htemp3");
TH1F *htemp4 = (TH1F*) hDettUp->Clone(); htemp4->SetName("htemp4");
TH1F *htemp5 = (TH1F*) hDettUp->Clone(); htemp5->SetName("htemp5");
htemp5->SetTitle("Muon decay asymmetry U-D/R-L; Time (#mus); Asymmetry");
TH1F *htemp6 = (TH1F*) hDettUp->Clone(); htemp6->SetName("htemp6");
//htemp6->SetTitle("Muon decay asymmetry U-D; Time (#mus); Asymmetry");
htemp1->Add(hDettUp,hDettDown,1.,-1.);
htemp2->Add(hDettUp,hDettDown,1., 1.);
htemp5->Divide(htemp1,htemp2,1.,1.);
htemp3->Add(hDettLeft,hDettRight,1.,-1.);
htemp4->Add(hDettLeft,hDettRight,1., 1.);
htemp6->Divide(htemp3,htemp4,1.,1.);
htemp5->SetLineWidth(2);
htemp5->SetLineColor(2);
htemp5->SetAxisRange(-0.8,0.8,"Y");
htemp5->Draw("hist");
htemp6->SetLineWidth(2);
htemp6->SetLineColor(4);
htemp6->SetAxisRange(-0.8,0.8,"Y");
htemp6->Draw("same");
hEdepositCF->SetLineWidth(2);
hEdepositCF->SetLineColor(2);
hEdepositCF->Draw("hist");
hEdepositCF->Fit("gaus");
TCanvas* c2= new TCanvas("c2","canvas 2");
hEdepoTest->Draw();
// sprintf(filenamePrint,"musrSrClass_%s.ps",fileNr);
// c1->Print(filenamePrint);
}

View File

@ -0,0 +1,304 @@
//////////////////////////////////////////////////////////
// This class has been automatically generated on
// Fri Oct 26 16:55:39 2007 by ROOT version 5.08/00
// from TTree t1/a simple Tree with simple variables
// found on file: musr_200003.root
//////////////////////////////////////////////////////////
#ifndef analysis_h
#define analysis_h
#include <TROOT.h>
#include <TChain.h>
#include <TFile.h>
class analysis {
public :
TTree *fChain; //!pointer to the analyzed TTree or TChain
Int_t fCurrent; //!current Tree number in a TChain
// Declaration of leave types
Int_t runID;
Int_t eventID;
Double_t BFieldAtDecay_Bx;
Double_t BFieldAtDecay_By;
Double_t BFieldAtDecay_Bz;
Double_t BFieldAtDecay_B3;
Double_t BFieldAtDecay_B4;
Double_t BFieldAtDecay_B5;
Double_t muIniPosX;
Double_t muIniPosY;
Double_t muIniPosZ;
Double_t muIniMomX;
Double_t muIniMomY;
Double_t muIniMomZ;
Double_t muIniPolX;
Double_t muIniPolY;
Double_t muIniPolZ;
Int_t muDecayDetID;
Double_t muDecayPosX;
Double_t muDecayPosY;
Double_t muDecayPosZ;
Double_t muDecayTime;
Double_t muDecayPolX;
Double_t muDecayPolY;
Double_t muDecayPolZ;
Double_t muTargetTime;
Double_t muTargetPolX;
Double_t muTargetPolY;
Double_t muTargetPolZ;
Double_t fieldValue;
Int_t det_n;
Int_t det_ID[50]; //[det_n]
Double_t det_edep[50]; //[det_n]
Int_t det_nsteps[50]; //[det_n]
Double_t det_length[50]; //[det_n]
Double_t det_time_start[50]; //[det_n]
Double_t det_time_end[50]; //[det_n]
Double_t det_x[50]; //[det_n]
Double_t det_y[50]; //[det_n]
Double_t det_z[50]; //[det_n]
Int_t save_n;
Int_t save_detID[10]; //[save_n]
Int_t save_particleID[10]; //[save_n]
Double_t save_ke[10]; //[save_n]
Double_t save_x[10]; //[save_n]
Double_t save_y[10]; //[save_n]
Double_t save_z[10]; //[save_n]
Double_t save_px[10]; //[save_n]
Double_t save_py[10]; //[save_n]
Double_t save_pz[10]; //[save_n]
// List of branches
TBranch *b_runID; //!
TBranch *b_eventID; //!
TBranch *b_BFieldAtDecay; //!
TBranch *b_muIniPosX; //!
TBranch *b_muIniPosY; //!
TBranch *b_muIniPosZ; //!
TBranch *b_muIniMomX; //!
TBranch *b_muIniMomY; //!
TBranch *b_muIniMomZ; //!
TBranch *b_muIniPolX; //!
TBranch *b_muIniPolY; //!
TBranch *b_muIniPolZ; //!
TBranch *b_muDecayDetID; //!
TBranch *b_muDecayPosX; //!
TBranch *b_muDecayPosY; //!
TBranch *b_muDecayPosZ; //!
TBranch *b_muDecayTime; //!
TBranch *b_muDecayPolX; //!
TBranch *b_muDecayPolY; //!
TBranch *b_muDecayPolZ; //!
TBranch *b_muTargetTime; //!
TBranch *b_muTargetPolX; //!
TBranch *b_muTargetPolY; //!
TBranch *b_muTargetPolZ; //!
TBranch *b_fieldValue; //!
TBranch *b_det_n; //!
TBranch *b_det_ID; //!
TBranch *b_det_edep; //!
TBranch *b_det_nsteps; //!
TBranch *b_det_length; //!
TBranch *b_det_time_start; //!
TBranch *b_det_time_end; //!
TBranch *b_det_x; //!
TBranch *b_det_y; //!
TBranch *b_det_z; //!
TBranch *b_save_n; //!
TBranch *b_save_detID; //!
TBranch *b_save_particleID; //!
TBranch *b_save_ke; //!
TBranch *b_save_x; //!
TBranch *b_save_y; //!
TBranch *b_save_z; //!
TBranch *b_save_px; //!
TBranch *b_save_py; //!
TBranch *b_save_pz; //!
analysis(TTree *tree=0);
virtual ~analysis();
virtual Int_t Cut(Long64_t entry);
virtual Int_t GetEntry(Long64_t entry);
virtual Long64_t LoadTree(Long64_t entry);
virtual void Init(TTree *tree);
virtual void Loop();
virtual Bool_t Notify();
virtual void Show(Long64_t entry = -1);
};
#endif
#ifdef analysis_cxx
analysis::analysis(TTree *tree)
{
// if parameter tree is not specified (or zero), connect the file
// used to generate this class and read the Tree.
if (tree == 0) {
TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject("data/sr_1091.root");
if (!f) {
//f = new TFile("musr_200003.root");
f = new TFile("data/sr1_1091.root"); //1049
}
tree = (TTree*)gDirectory->Get("t1");
}
Init(tree);
}
analysis::~analysis()
{
if (!fChain) return;
delete fChain->GetCurrentFile();
}
Int_t analysis::GetEntry(Long64_t entry)
{
// Read contents of entry.
if (!fChain) return 0;
return fChain->GetEntry(entry);
}
Long64_t analysis::LoadTree(Long64_t entry)
{
// Set the environment to read one entry
if (!fChain) return -5;
Long64_t centry = fChain->LoadTree(entry);
if (centry < 0) return centry;
if (fChain->IsA() != TChain::Class()) return centry;
TChain *chain = (TChain*)fChain;
if (chain->GetTreeNumber() != fCurrent) {
fCurrent = chain->GetTreeNumber();
Notify();
}
return centry;
}
void analysis::Init(TTree *tree)
{
// The Init() function is called when the selector needs to initialize
// a new tree or chain. Typically here the branch addresses of the tree
// will be set. It is normaly not necessary to make changes to the
// generated code, but the routine can be extended by the user if needed.
// Init() will be called many times when running with PROOF.
// Set branch addresses
if (tree == 0) return;
fChain = tree;
fCurrent = -1;
fChain->SetMakeClass(1);
fChain->SetBranchAddress("runID",&runID);
fChain->SetBranchAddress("eventID",&eventID);
fChain->SetBranchAddress("BFieldAtDecay",&BFieldAtDecay_Bx);
fChain->SetBranchAddress("muIniPosX",&muIniPosX);
fChain->SetBranchAddress("muIniPosY",&muIniPosY);
fChain->SetBranchAddress("muIniPosZ",&muIniPosZ);
fChain->SetBranchAddress("muIniMomX",&muIniMomX);
fChain->SetBranchAddress("muIniMomY",&muIniMomY);
fChain->SetBranchAddress("muIniMomZ",&muIniMomZ);
fChain->SetBranchAddress("muIniPolX",&muIniPolX);
fChain->SetBranchAddress("muIniPolY",&muIniPolY);
fChain->SetBranchAddress("muIniPolZ",&muIniPolZ);
fChain->SetBranchAddress("muDecayDetID",&muDecayDetID);
fChain->SetBranchAddress("muDecayPosX",&muDecayPosX);
fChain->SetBranchAddress("muDecayPosY",&muDecayPosY);
fChain->SetBranchAddress("muDecayPosZ",&muDecayPosZ);
fChain->SetBranchAddress("muDecayTime",&muDecayTime);
fChain->SetBranchAddress("muDecayPolX",&muDecayPolX);
fChain->SetBranchAddress("muDecayPolY",&muDecayPolY);
fChain->SetBranchAddress("muDecayPolZ",&muDecayPolZ);
fChain->SetBranchAddress("muTargetTime",&muTargetTime);
fChain->SetBranchAddress("muTargetPolX",&muTargetPolX);
fChain->SetBranchAddress("muTargetPolY",&muTargetPolY);
fChain->SetBranchAddress("muTargetPolZ",&muTargetPolZ);
fChain->SetBranchAddress("fieldValue",&fieldValue);
fChain->SetBranchAddress("det_n",&det_n);
fChain->SetBranchAddress("det_ID",det_ID);
fChain->SetBranchAddress("det_edep",det_edep);
fChain->SetBranchAddress("det_nsteps",det_nsteps);
fChain->SetBranchAddress("det_length",det_length);
fChain->SetBranchAddress("det_time_start",det_time_start);
fChain->SetBranchAddress("det_time_end",det_time_end);
fChain->SetBranchAddress("det_x",det_x);
fChain->SetBranchAddress("det_y",det_y);
fChain->SetBranchAddress("det_z",det_z);
fChain->SetBranchAddress("save_n", &save_n, &b_save_n);
fChain->SetBranchAddress("save_detID", save_detID, &b_save_detID);
fChain->SetBranchAddress("save_particleID", save_particleID, &b_save_particleID);
fChain->SetBranchAddress("save_ke", save_ke, &b_save_ke);
fChain->SetBranchAddress("save_x", save_x, &b_save_x);
fChain->SetBranchAddress("save_y", save_y, &b_save_y);
fChain->SetBranchAddress("save_z", save_z, &b_save_z);
fChain->SetBranchAddress("save_px", save_px, &b_save_px);
fChain->SetBranchAddress("save_py", save_py, &b_save_py);
fChain->SetBranchAddress("save_pz", save_pz, &b_save_pz);
Notify();
}
Bool_t analysis::Notify()
{
// The Notify() function is called when a new file is opened. This
// can be either for a new TTree in a TChain or when when a new TTree
// is started when using PROOF. Typically here the branch pointers
// will be retrieved. It is normaly not necessary to make changes
// to the generated code, but the routine can be extended by the
// user if needed.
// Get branch pointers
b_runID = fChain->GetBranch("runID");
b_eventID = fChain->GetBranch("eventID");
b_BFieldAtDecay = fChain->GetBranch("BFieldAtDecay");
b_muIniPosX = fChain->GetBranch("muIniPosX");
b_muIniPosY = fChain->GetBranch("muIniPosY");
b_muIniPosZ = fChain->GetBranch("muIniPosZ");
b_muIniMomX = fChain->GetBranch("muIniMomX");
b_muIniMomY = fChain->GetBranch("muIniMomY");
b_muIniMomZ = fChain->GetBranch("muIniMomZ");
b_muIniPolX = fChain->GetBranch("muIniPolX");
b_muIniPolY = fChain->GetBranch("muIniPolY");
b_muIniPolZ = fChain->GetBranch("muIniPolZ");
b_muDecayDetID = fChain->GetBranch("muDecayDetID");
b_muDecayPosX = fChain->GetBranch("muDecayPosX");
b_muDecayPosY = fChain->GetBranch("muDecayPosY");
b_muDecayPosZ = fChain->GetBranch("muDecayPosZ");
b_muDecayTime = fChain->GetBranch("muDecayTime");
b_muDecayPolX = fChain->GetBranch("muDecayPolX");
b_muDecayPolY = fChain->GetBranch("muDecayPolY");
b_muDecayPolZ = fChain->GetBranch("muDecayPolZ");
b_muTargetTime = fChain->GetBranch("muTargetTime");
b_muTargetPolX = fChain->GetBranch("muTargetPolX");
b_muTargetPolY = fChain->GetBranch("muTargetPolY");
b_muTargetPolZ = fChain->GetBranch("muTargetPolZ");
b_fieldValue = fChain->GetBranch("fieldValue");
b_det_n = fChain->GetBranch("det_n");
b_det_ID = fChain->GetBranch("det_ID");
b_det_edep = fChain->GetBranch("det_edep");
b_det_nsteps = fChain->GetBranch("det_nsteps");
b_det_length = fChain->GetBranch("det_length");
b_det_time_start = fChain->GetBranch("det_time_start");
b_det_time_end = fChain->GetBranch("det_time_end");
b_det_x = fChain->GetBranch("det_x");
b_det_y = fChain->GetBranch("det_y");
b_det_z = fChain->GetBranch("det_z");
return kTRUE;
}
void analysis::Show(Long64_t entry)
{
// Print contents of entry.
// If entry is not specified, print current entry
if (!fChain) return;
fChain->Show(entry);
}
Int_t analysis::Cut(Long64_t entry)
{
// This function may be called from Loop.
// returns 1 if entry is accepted.
// returns -1 otherwise.
return 1;
}
#endif // #ifdef analysis_cxx

View File

@ -0,0 +1,61 @@
% Electric field
% Read file (check the number of header lines) and assing variables.
filename = 'E3D_cap_symm.map';
[x y z Ex Ey Ez] = textread(filename,'%f %f %f %f %f %f','headerlines',8);
z_ind = find (x==0 & y==0); % Determine indices of the points along z axis.
z_p = z(z_ind); % z values along z axis
Ex_p = Ex(z_ind); % Ex field profile along z axis
plot(z_p,-Ex_p*0.8e-8,'m-');
%Calculate effective field length l_eff = Int(Ex dz) / max(Ex).
z_step = max(diff(z));
i_center = find (x==0 & y==0 & z==0); % Field center index
if Ex(i_center) < 0, % If the field at center is negative use min, otherwise max.
l_effE = sum(Ex_p)*z_step/min(Ex_p);
else
l_effE = sum(Ex_p)*z_step/max(Ex_p);
end
ylim = get(gca,'YLim');
hl1 = line([-l_effE/2 -l_effE/2],[ylim(1) ylim(2)]);
hl2 = line([ l_effE/2 l_effE/2],[ylim(1) ylim(2)]);
set(hl1,'Color','m'); set(hl2,'Color','m');
text(0.75,0.8,['Eff. length E = ',num2str(l_effE,3), ' cm'],'Units','Normal','Color','m')
xlabel('z coordinate (cm)','FontSize',14)
ylabel('EM Field (arb. unit)','FontSize',14)
title('Field profile along z axis','FontSize',16)
hold on
% Magnetic field
filename = 'B3D_iron1.map';
[x y z Bx By Bz] = textread(filename,'%f %f %f %f %f %f','headerlines',5);
z_ind = find (x==0 & y==0); % Determine indices of the points along z axis.
z_p = z(z_ind); % z values along z axis
By_p = By(z_ind); % By field profile along z axis
plot(z_p,-By_p,'b-');
%Calculate effective field length l_eff = Int(By dz) / max(By).
z_step = max(diff(z));
i_center = find (x==0 & y==0 & z==0); % Field center index
if By(i_center) < 0, % If the field at center is negative use min, otherwise max.
l_effB = sum(By_p)*z_step/min(By_p);
else
l_effB = sum(By_p)*z_step/max(By_p);
end
ylim = get(gca,'YLim');
hl3 = line([-l_effB/2 -l_effB/2],[ylim(1) ylim(2)]);
hl4 = line([ l_effB/2 l_effB/2],[ylim(1) ylim(2)]);
text(0.75,0.75,['Eff. length B = ',num2str(l_effB,3), ' cm'],'Units','Normal','Color','b')
text(0.03,0.8,{'C-magnet 20x40 cm poles','Symm. capacitor voltages'},'Units','Normal','FontSize',12)
set(gca,'FontSize',14)
axis([-50 50 0 8e-7])

View File

@ -0,0 +1,32 @@
[x y z bx by bz] = textread('sep_0nl.lis','%f %f %f %f %f %f', 'headerlines', 13);
[nx ny nz] = textread('sep_0nl.lis','%*s %*s %*s %*s %u %u %u', 1, 'headerlines', 10);
Bx = reshape(bx,nx,ny,nz);
By = reshape(by,nx,ny,nz);
Bz = reshape(bz,nx,ny,nz);
x1 = reshape(x,nx,ny,nz);
y1 = reshape(y,nx,ny,nz);
z1 = reshape(z,nx,ny,nz);
i=1:32;
test = [x1(i);y1(i);z1(i)]'
%min(x) max(x)
sx = max(diff(x)); % read step size along x
sy = max(diff(y)); % read step size along y
sz = max(diff(z)); % read step size along z
x2 = -x(end:-1:1);
x3 = -x(end:-1:1);
x4 = -x(end:-1:1);
x2 = reshape(x2,nx,ny,nz);
x3 = reshape(x3,nx,ny,nz);
x4 = reshape(x4,nx,ny,nz);
%p = [x(:)'; y(:)'; z(:)'];
%ind2sub
%[i j] = ind2sub(3,x1);

View File

@ -0,0 +1,36 @@
// From www-pnp.physics.ox.ac.uk/~west/root/plotting_with_style.html
// See also http://hep-www.px.tsukuba.ac.jp/~yuji/root/MyRootTips.html
void rootlogon ()
{
printf("rootlogon.C has been loaded.\n");
gStyle->SetCanvasColor(10); // or (kWhite) background is no longer mouse-dropping white
gStyle->SetPalette(1,0); // blue to red false color palette. Use 9 for b/w
gStyle->SetCanvasBorderMode(0); // turn off canvas borders
gStyle->SetPadBorderMode(0);
gStyle->SetPaintTextFormat("5.2f"); // What precision to put numbers if plotted with "TEXT"
gStyle->SetTitleColor(1);
//gStyle->SetFillColor(0);
//gStyle->SetPadColor(10);
gStyle->SetStatColor(10); // sets the filling of statistic box to white
gStyle->SetStatFont(62);
gStyle->SetStatBorderSize(0);
//gStyle->SetPaperSize(20,24);
//gStyle->SetLabelColor(6,"xy");
gStyle->SetTitleBorderSize(0);
gStyle->SetTitleFillColor(10);
//gStyle->SetTitleColor(4,"xy");
//gStyle->SetPadColor(23);
// For publishing:
gStyle->SetLineWidth(2.);
//gStyle->SetTextSize(1.1);
gStyle->SetLabelSize(0.05,"xy");
gStyle->SetTitleSize(0.05,"xy");
gStyle->SetTitleOffset(1.1,"x");
gStyle->SetTitleOffset(1.0,"y");
gStyle->SetPadTopMargin(0.1);
gStyle->SetPadRightMargin(0.1);
gStyle->SetPadBottomMargin(0.16);
gStyle->SetPadLeftMargin(0.12);
}

16
geant4/spin_rot/run/run_jobs Executable file
View File

@ -0,0 +1,16 @@
sr1 1100.mac > data/1100.txt
sr1 1101.mac > data/1101.txt
sr1 1102.mac > data/1102.txt
sr1 1103.mac > data/1103.txt
sr1 1104.mac > data/1104.txt
sr1 1105.mac > data/1105.txt
sr1 1106.mac > data/1106.txt
sr1 1107.mac > data/1107.txt
sr1 1108.mac > data/1108.txt
sr1 1109.mac > data/1109.txt
sr1 1110.mac > data/1110.txt
sr1 1111.mac > data/1111.txt
sr1 1112.mac > data/1112.txt
sr1 1113.mac > data/1113.txt
sr1 1114.mac > data/1114.txt
sr1 1115.mac > data/1115.txt

View File

@ -0,0 +1,161 @@
void spin_rot()
{
TFile* f1 = new TFile("data/sr1_1091.root");
TCanvas* c1 = new TCanvas("c1","Beam Spot",60,40,800,800);
gStyle->SetPalette(1,0);TCanvas* c1 = new TCanvas("c1","Beam Spot",60,40,800,800);
c1->Divide(2,2);
c1->SetGridx();
c1->SetGridy();
//c1->cd(1)->SetGridx();c1->cd(1)->SetGridy();
c1->cd(4)->SetGridx();c1->cd(4)->SetGridy(); // c1->cd(3);
t1->Draw("det_y[0]:det_x[0]>>bspot_hist(64,-40,40,64,-40,40)");
//t1->Draw("det_y:det_x>>bspot_hist(64,-80,80,64,-80,80)"); //t1->Draw("mcpHit.positiony*10:mcpHit.positionx*10>>bspot_hist(64,-40,40,64,-40,40)","mcpHit.positionz==2&&mcpHit.ID==0");
bspot_hist->SetTitle("Muon beam cross section [mm]");
//bspot_hist->Draw("cont0");
bspot_hist->Draw();
bspot_hist->Draw("cont0 same");
// t1->Draw("mcpHit.positionx*10:mcpHit.positiony*10>>bspot_hist(128,-12,12,128,-12,12)","","goff");
bspot_hist->ProjectionX("xsect",31,33);
bspot_hist->ProjectionY("ysect",31,33);
//pl=new TPaveLabel(2, 155, 16, 175, "RA_Up = 11 kV");
pl=new TPaveLabel(-75, 60, -15, 75, "#splitline{RA_Up = 8.6 kV}{L3 = 6.78 kV}");
pl->SetBorderSize(1);
pl->SetTextSize(0.43);
pl->Draw();
c1->cd(3);
ysect->SetTitle("y cross section [mm]");
ysect->SetFillStyle(1001);
//ysect->Draw("F");
ysect->SetFillColor(45);
ysect->Draw();
c1->cd(1);
t1->Draw("save_x","(save_detID==800)"); //xsect->SetTitle("x cross section [mm]");
htemp->SetTitle("Position 1 [mm]");
htemp->Draw("F");
htemp->SetFillStyle(1001);
htemp->SetFillColor(38);
htemp->Draw();
c1->cd(2);
//Energy loss in CFoil
//t1->Draw("10-det_edep_mup*1000","(det_n==1)&&(det_edep<0.1)&&(det_edep_mup*1000>0.1)");
t1->Draw("save_x","(save_detID==900)");
//t1->Draw("det_edep_mup*1000","(det_n==1)&&(det_edep<0.1)");
//t1->Draw("det_edep_mup*1000>>tmp_hist(64,-80,80)","(det_n==1)&&(det_edep<0.1)");
htemp->SetTitle("Position 2 [mm]");
htemp->Draw("F");
htemp->SetFillStyle(1001);
//htemp->SetFillColor(kBlue-5);
htemp->SetFillColor(kGreen-5);
htemp->Draw();
/// Plot of muon beam angular dispersion after lens 1:
TCanvas* c2 = new TCanvas("c2","Angular Dispersion",60,40,800,800);
//gStyle->SetPalette(1,0);
//c1->Divide(2,2);
c2->SetGridx();
c2->SetGridy();
//c2->SetFillColor(kWhite); // Fill background with white for printing
//c2->cd(1);
t1->Draw("save_pz","(save_detID==800)"); //xsect->SetTitle("x cross section [mm]");
htemp->SetTitle("Position 1 [mm]");
htemp->Draw("F");
htemp->SetFillStyle(1001);
htemp->SetFillColor(38);
htemp->Draw();
//t1->Draw("atan2(mcpHit.posyini,mcpHit.posxini)*57.29577951308:atan2(mcpHit.positiony,mcpHit.positionx)*57.29577951308>
// Double_t Pi = TMath::Pi(); // 180/Pi
//c2->cd(2)->SetGridx(); c1->cd(2)->SetGridy();
//t1->Draw("atan2(save_py,save_px)*57.29577951308:atan2(mcpHit.positiony,mcpHit.positionx)*57.29577951308>>bspot_hist3(64,-180,180,64,-180,180)","mcpHit.ID==0");
///t1->Draw("atan2(save_py,save_px)*57.29577951308");
//t1->Draw("det_y[0]:det_x[0]>>bspot_hist(64,-40,40,64,-40,40)");
t1->Draw("90-atan2(save_pz,sqrt(save_px^2 + save_py^2))*57.29577951308>>ang_hist(64,0,5)","(save_detID==900)");
//t1->Draw("90-atan2(save_pz,sqrt(save_px^2 + save_py^2))*57.29577951308");
//htemp->SetTitle("Correlation angle for L1 (8.7 kV, 15 keV); Final angle [deg.]; Inital angle [deg.]");
ang_hist->GetXaxis()->SetRangeUser(-5., 5.);
ang_hist->Draw("F");
ang_hist->SetFillStyle(1001);
ang_hist->SetFillColor(805);
ang_hist->SetTitleSize(0.025);
ang_hist->SetTitle("Muon angular distribution after L1");
ang_hist->GetXaxis()->SetNdivisions(206);
ang_hist->GetXaxis()->SetTickLength(0.018);
ang_hist->GetXaxis()->SetLabelSize(0.04);
ang_hist->GetXaxis()->SetTitleSize(0.045);
ang_hist->GetYaxis()->SetTitleOffset(1.0);
ang_hist->GetXaxis()->SetTitle("Angle (deg.)");
TAxis* yax = ang_hist->GetYaxis();
yax->SetNdivisions(206); // N2*100 + N1 (N2 = secondary, N1 = primary) //yax->SetNdivisions(410);
yax->SetTickLength(0.018);
yax->SetLabelSize(0.04);
yax->SetTitleSize(0.045);
yax->SetTitleOffset(1.3);
yax->SetTitle("Counts (arb. units)");
ang_hist->Draw();
TText *pt = new TText(3.2, 200., "Plane at -300 mm");
pt->SetTextSize(0.03);
pt->Draw();
//TPaveText *pt = new TPaveText(0.6,0.4,0.89, 0.45,"trNDC");
//pt->SetTextSize(0.03);
//pt->SetFillColor(0); //pt->SetFillColor(390);
//pt->SetBorderSize(0);
//pt->SetTextAlign(12);
//pte = pt->AddText("Plane at z = -300 mm");
//pt->Draw();
//c2->SaveAs("data/sr1_ang_dist_300.eps");
}
/// Insert simple text directly from command line
// TText text(3, 300, "Plane at -380 mm");
// text.SetTextSize(0.03);
// text.Draw();
/// Optional changes of statistics
// TPaveStats* sb2=(TPaveStats *)(ang_hist->GetListOfFunctions()->FindObject("stats"));
// sb2->SetTextSize(0.025);
// sb2->SetFillColor(390);
/// An easy way to plot functions
// (new TF1("fun1","(1-x)*sqrt(1-x*x)",-1,1))->Draw();
// (new TF2("fun2","(175/80)**2*(1-y)*(1-x**2)+(1+y)*(1-x)**2",-1,1,-1,1))->Draw("lego")
// From: www-pnp.physics.ox.ac.uk/~west/root/plotting_with_style.html#demo_background
/// For publishing (insert these lines in rootlogon.C):
// gStyle->SetLineWidth(2.);
// gStyle->SetTextSize(1.1);
// gStyle->SetLabelSize(0.06,"xy");
// gStyle->SetTitleSize(0.06,"xy");
// gStyle->SetTitleOffset(1.2,"x");
// gStyle->SetTitleOffset(1.0,"y");
// gStyle->SetPadTopMargin(0.1);
// gStyle->SetPadRightMargin(0.1);
// gStyle->SetPadBottomMargin(0.16);
// gStyle->SetPadLeftMargin(0.12);

View File

@ -0,0 +1,198 @@
// To run root without logon screen and script use: root -l -n
// To run a named macro in root use:
//.L sr_transm.C
// sr_transm("data/sr1_1100.root")
#include <string>
void sr_transm(char* fname)
//void sr_transm() /// Uncomment this and next line to run with a FIXED file name
{
//TFile* f1 = new TFile("data/sr1_1091.root");
TFile* f1 = new TFile(fname);
//TCanvas* c1 = new TCanvas("c1","Polarization and Transmission",60,40,800,800);
gStyle->SetPalette(1,0);
TCanvas* c1 = new TCanvas("c1","Polarization and Transmission",60,40,800,800);
c1->Divide(2,2);
c1->SetGridx();
c1->SetGridy();
//c1->cd(1)->SetGridx();c1->cd(1)->SetGridy();
c1->cd(4)->SetGridx();c1->cd(4)->SetGridy(); // c1->cd(3);
t1->Draw("muTargetPosY[0]:muTargetPosX[0]>>bspot_hist(64,-40,40,64,-40,40)","muTargetPolX > -2");
//t1->Draw("det_y:det_x>>bspot_hist(64,-80,80,64,-80,80)"); //t1->Draw("mcpHit.positiony*10:mcpHit.positionx*10>>bspot_hist(64,-40,40,64,-40,40)","mcpHit.positionz==2&&mcpHit.ID==0");
bspot_hist->SetTitle("Muon beam cross section [mm]");
//bspot_hist->Draw("cont0");
bspot_hist->Draw();
bspot_hist->Draw("cont0 same");
// t1->Draw("mcpHit.positionx*10:mcpHit.positiony*10>>bspot_hist(128,-12,12,128,-12,12)","","goff");
bspot_hist->ProjectionX("xsect",31,33);
bspot_hist->ProjectionY("ysect",31,33);
TText *pt = new TText(-36., 33., "L1 = 11.0 kV");
pt->SetTextSize(0.05);
pt->Draw();
//pl=new TPaveLabel(2, 155, 16, 175, "RA_Up = 11 kV");
//pl=new TPaveLabel(-75, 60, -15, 75, "#splitline{RA_Up = 8.6 kV}{L3 = 6.78 kV}");
//pl->SetBorderSize(1);
//pl->SetTextSize(0.43);
//pl->Draw();
c1->cd(3);
xsect->SetTitle("x cross section [mm]");
xsect->SetFillStyle(1001);
//xsect->Draw("F");
xsect->SetFillColor(45);
xsect->Draw();
c1->cd(2);
t1->Draw("muTargetPolZ >> pol_z(128, -1, -0.95)","(muTargetPolZ > -2)"); //-1., 1
pol_z->SetTitle("Polarization Z");
pol_z->GetXaxis()->SetNdivisions(405);
pol_z->GetYaxis()->SetNdivisions(406);
pol_z->GetXaxis()->SetTickLength(0.018);
pol_z->GetYaxis()->SetTickLength(0.018);
pol_z->Draw("F");
pol_z->SetFillStyle(1001);
pol_z->SetFillColor(38);
pol_z->Draw();
c1->cd(1);
//Energy loss in CFoil
//t1->Draw("10-det_edep_mup*1000","(det_n==1)&&(det_edep<0.1)&&(det_edep_mup*1000>0.1)");
t1->Draw("muTargetPolX >> pol_x(128, -0.4, 0)","(muTargetPolX > -2)"); //0, 2
//t1->Draw("det_edep_mup*1000","(det_n==1)&&(det_edep<0.1)");
//t1->Draw("det_edep_mup*1000>>tmp_hist(64,-80,80)","(det_n==1)&&(det_edep<0.1)");
pol_x->SetTitle("Polarization X");
pol_x->GetXaxis()->SetNdivisions(405);
pol_x->GetYaxis()->SetNdivisions(406);
pol_x->GetXaxis()->SetTickLength(0.018);
pol_x->GetYaxis()->SetTickLength(0.018);
pol_x->Draw("F");
pol_x->SetFillStyle(1001);
//pol_x->SetFillColor(kBlue-5);
pol_x->SetFillColor(kGreen-5);
pol_x->Draw();
/*
TAxis* yax = ang_hist->GetYaxis();
yax->SetNdivisions(206); // N2*100 + N1 (N2 = secondary, N1 = primary) //yax->SetNdivisions(410);
yax->SetTickLength(0.018);
yax->SetLabelSize(0.04);
yax->SetTitleSize(0.045);
yax->SetTitleOffset(1.3);
yax->SetTitle("Counts (arb. units)");
*/
c1->SaveAs("data/sr_bspot_0.eps");
}
/*
/// Plot of muon beam angular dispersion after lens 1:
TCanvas* c2 = new TCanvas("c2","Angular Dispersion",60,40,800,800);
//gStyle->SetPalette(1,0);
//c1->Divide(2,2);
c2->SetGridx();
c2->SetGridy();
//c2->SetFillColor(kWhite); // Fill background with white for printing
//c2->cd(1);
t1->Draw("save_pz","(save_detID==800)"); //xsect->SetTitle("x cross section [mm]");
htemp->SetTitle("Position 1 [mm]");
htemp->Draw("F");
htemp->SetFillStyle(1001);
htemp->SetFillColor(38);
htemp->Draw();
//t1->Draw("atan2(mcpHit.posyini,mcpHit.posxini)*57.29577951308:atan2(mcpHit.positiony,mcpHit.positionx)*57.29577951308>
// Double_t Pi = TMath::Pi(); // 180/Pi
//c2->cd(2)->SetGridx(); c1->cd(2)->SetGridy();
//t1->Draw("atan2(save_py,save_px)*57.29577951308:atan2(mcpHit.positiony,mcpHit.positionx)*57.29577951308>>bspot_hist3(64,-180,180,64,-180,180)","mcpHit.ID==0");
///t1->Draw("atan2(save_py,save_px)*57.29577951308");
//t1->Draw("det_y[0]:det_x[0]>>bspot_hist(64,-40,40,64,-40,40)");
t1->Draw("90-atan2(save_pz,sqrt(save_px^2 + save_py^2))*57.29577951308>>ang_hist(64,0,5)","(save_detID==900)");
//t1->Draw("90-atan2(save_pz,sqrt(save_px^2 + save_py^2))*57.29577951308");
//htemp->SetTitle("Correlation angle for L1 (8.7 kV, 15 keV); Final angle [deg.]; Inital angle [deg.]");
ang_hist->GetXaxis()->SetRangeUser(-5., 5.);
ang_hist->Draw("F");
ang_hist->SetFillStyle(1001);
ang_hist->SetFillColor(805);
ang_hist->SetTitleSize(0.025);
ang_hist->SetTitle("Muon angular distribution after L1");
ang_hist->GetXaxis()->SetNdivisions(206);
ang_hist->GetXaxis()->SetTickLength(0.018);
ang_hist->GetXaxis()->SetLabelSize(0.04);
ang_hist->GetXaxis()->SetTitleSize(0.045);
ang_hist->GetYaxis()->SetTitleOffset(1.0);
ang_hist->GetXaxis()->SetTitle("Angle (deg.)");
TAxis* yax = ang_hist->GetYaxis();
yax->SetNdivisions(206); // N2*100 + N1 (N2 = secondary, N1 = primary) //yax->SetNdivisions(410);
yax->SetTickLength(0.018);
yax->SetLabelSize(0.04);
yax->SetTitleSize(0.045);
yax->SetTitleOffset(1.3);
yax->SetTitle("Counts (arb. units)");
ang_hist->Draw();
TText *pt = new TText(3.2, 200., "Plane at -300 mm");
pt->SetTextSize(0.03);
pt->Draw();
//TPaveText *pt = new TPaveText(0.6,0.4,0.89, 0.45,"trNDC");
//pt->SetTextSize(0.03);
//pt->SetFillColor(0); //pt->SetFillColor(390);
//pt->SetBorderSize(0);
//pt->SetTextAlign(12);
//pte = pt->AddText("Plane at z = -300 mm");
//pt->Draw();
//c2->SaveAs("data/sr1_ang_dist_300.eps");
}
*/
/// Insert simple text directly from command line
// TText text(3, 300, "Plane at -380 mm");
// text.SetTextSize(0.03);
// text.Draw();
/// Optional changes of statistics
// TPaveStats* sb2=(TPaveStats *)(ang_hist->GetListOfFunctions()->FindObject("stats"));
// sb2->SetTextSize(0.025);
// sb2->SetFillColor(390);
/// An easy way to plot functions
// (new TF1("fun1","(1-x)*sqrt(1-x*x)",-1,1))->Draw();
// (new TF2("fun2","(175/80)**2*(1-y)*(1-x**2)+(1+y)*(1-x)**2",-1,1,-1,1))->Draw("lego")
// From: www-pnp.physics.ox.ac.uk/~west/root/plotting_with_style.html#demo_background
/// For publishing (insert these lines in rootlogon.C):
// gStyle->SetLineWidth(2.);
// gStyle->SetTextSize(1.1);
// gStyle->SetLabelSize(0.06,"xy");
// gStyle->SetTitleSize(0.06,"xy");
// gStyle->SetTitleOffset(1.2,"x");
// gStyle->SetTitleOffset(1.0,"y");
// gStyle->SetPadTopMargin(0.1);
// gStyle->SetPadRightMargin(0.1);
// gStyle->SetPadBottomMargin(0.16);
// gStyle->SetPadLeftMargin(0.12);

View File

@ -0,0 +1,204 @@
% Test of Spin Rotator transmittance as a function of Lens L1 voltage
% Simulation performed with 1e4 events (9908), B = 360 G, E = 21 kV/m
% To get count number use, e.g.: less sr_bspot_*.eps | grep bspot_histEntries
d0 = [ ... % Parallel beam = > alpha = 0
% L1 (kV) Counts
0.0 8684
1.0 8702
2.0 8755
3.0 8780
4.0 8847
5.0 8927
6.0 8983
7.0 8985
8.0 8982
9.0 8979
9.5 8976
10.0 8964
10.5 8938
11.0 8869
11.3 8758
12.0 8395
13.0 7522
14.0 6345
15.0 5305
];
da = [... % alpha = 1 deg., alpha = 2 deg., third column SR OFF, alpha = 1 deg.
0.0 5777 3688 8794
1.0 5687 3781 8791 % 9005 for alpha = 0
2.0 5780 3790 8804
3.0 5892 3782 8825
4.0 5919 3846 8853
5.0 5986 3881 8898
6.0 6200 3925 8944 % 8991 for alpha = 0
7.0 6453 4192 8959
8.0 6724 4340 8975
9.0 7058 4542 8981
10.0 7337 4889 8981
11.0 7452 5291 8964 % 8972 for alpha = 0
12.0 7322 5663 8881
13.0 6896 5835 8593
14.0 6057 5497 7975
15.0 5082 4827 6911 % 7034 for alpha = 0
];
L1_V0 = d0(:,1); counts0 = d0(:,2); % alpha = 0 deg.
L1_V1 = da(:,1); counts1 = da(:,2); % alpha = 1 deg.
L1_V2 = da(:,1); counts2 = da(:,3); % alpha = 2 deg.
L1_V3 = da(:,1); counts3 = da(:,4); % SR OFF! alpha = 1 deg.
counts0 = counts0/100; counts1 = counts1/100;
counts2 = counts2/100; counts3 = counts3/100;
hp = plot(L1_V0, counts0,'bo-', L1_V1, counts1,'mo-', L1_V2, counts2,'ro-', L1_V3, counts3,'ko-');
set(hp, 'MarkerFaceColor','w','MarkerSize',8)
legend('Ang. spread = 0 deg.','Ang. spread = 1 deg.','Ang. spread = 2 deg.',' SR off, Ang. = 0 deg.',4)
axis([0 15 0 100])
grid on
xlabel('Lens L1 voltage (kV)','FontSize',14)
ylabel('Spin Rotator transmission (%)','FontSize',14)
text(2, 15, [{'E = 21 kV, B = 360 G'},{'10 cm symm. capacitor'},{'E_0 = 20 keV'}],'FontSize',14)
set(gca,'FontSize',14)
% Simulations as a function of L1 voltage for E0 = 15 keV and 20 keV,
% using alpha = 1.4 deg. from previous G3 simulations.
de = [...%E0 = 15, E0 = 20 keV, alpha = 1.4 deg. fixed. Last col. SR OFF at 15 keV.
0.0 4990 5065 7635
1.0 4974 5063 7665
2.0 5056 5048 7722
3.0 5023 5122 7840
4.0 5229 5190 8009
5.0 5457 5269 8253
6.0 5774 5415 8470
7.0 6174 5607 8639
8.0 6716 5784 8714
9.0 6964 6107 8642
10.0 6733 6462 8198
11.0 5628 6790 7043
12.0 4510 6923 5233
13.0 3347 6745 3542
14.0 2431 6077 2175
15.0 1568 5355 1268
];
L1_V = de(:,1); % L1 Voltage values (alpha = 1.4 deg.)
counts1 = de(:,2); counts4 = de(:,4); % E0 = 15 keV, SR ON/OFF
counts2 = de(:,3); % E0 = 20 keV, SR ON
% For SR OFF at 20 keV and alpha = 1 deg. see the variable counts3 above
counts1 = counts1/100; counts2 = counts2/100; counts4 = counts4/100;
figure(2)
hp = plot(L1_V, counts1,'bv-', L1_V, counts2,'mv-', L1_V, counts4,'ro-', L1_V3, counts3,'ko-');
set(hp, 'MarkerFaceColor','w','MarkerSize',8)
legend('E_0 = 15 keV','E_0 = 20 keV','SR off (15 keV)','SR off (20 keV)',4)
axis([0 15 0 100])
grid on
% E_0 = 20 keV, E = 21 kV, B = 360 G
% E_0 = 15 keV, E = 18.1865 kV, B = 311.7691 G
xlabel('Lens L1 voltage (kV)','FontSize',14)
ylabel('Spin Rotator transmission (%)','FontSize',14)
text(1, 15, [{'E_0 = 20 keV, E = 21 kV, B = 360 G'},...
{'E_0 = 15 keV, E = 16.3 kV, B = 312 G'},...
{'10 cm symm. capacitor'},{'Ang. spread = 1.4 deg.'}],'FontSize',14)
set(gca,'FontSize',14)
% Simulations as a function of L1 voltage for E0 = 15 keV and 20 keV,
% using alpha = 1.4 deg. and CONSTANT E and B fields.
dc = [...%E0 = 15: a) EB const; b) only E const. (19.3 kV). c) E0 = 20 keV, EB const,
% d) E0 = 15 keV using E and B MAPS with improved E field map (E3D_cap_symm_edge.map instead of E3D_cap_symm.map)
% e) E0 = 15 keV using E and B MAPS with improved E field map (E3D_edge_rod.map)
% f) E0 = 15 keV using E and B MAPS with improved E field map (E3D_edge_3rods.map) <= BEST E-FIELD MAP!
% a b c d e f
0.0 8065 7192 8082 5772 5669 7250
1.0 8102 7244 8197 5847 5612 7278
2.0 8190 7272 8243 5847 5646 7293
3.0 8257 7365 8190 5915 5825 7374
4.0 8379 7540 8301 6082 5906 7495
5.0 8527 7753 8445 6357 6219 7709
6.0 8659 8016 8541 6673 6515 7965
7.0 8762 8299 8669 7114 6956 8290
8.0 8783 8503 8874 7578 7411 8527
9.0 8747 8497 8792 7738 7653 8577
10.0 8525 8134 8920 7392 7243 8319
11.0 7790 7194 8945 6466 6291 7553
12.0 6301 5714 8889 5215 5057 6225
13.0 4443 4090 8762 4109 3650 4646
14.0 2901 2641 8326 2874 2377 3127
15.0 1674 1607 7605 1834 1485 1982
];
L1_V = dc(:,1); % L1 Voltage values (alpha = 1.4 deg.)
counts1 = dc(:,2); counts2 = dc(:,3); % E0 = 15 keV, EB const, E const only
counts3 = dc(:,4); % E0 = 20 keV, EB const
counts4 = dc(:,5); % E0 = 15 keV, using E and B maps with improved E field map (E3D_cap_symm_edge.map)
counts7 = dc(:,6); % E0 = 15 keV, using E and B maps with improved E field map (E3D_edge_rod.map)
counts8 = dc(:,7); % E0 = 15 keV, using E and B maps with improved E field map (E3D_edge_3rods.map) <- BEST!
% For SR OFF at 20 keV and alpha = 1 deg. see the variable counts3 above
counts1 = counts1/100; counts2 = counts2/100; counts3 = counts3/100;
counts4 = counts4/100; counts5 = de(:,2)/100; counts6 = de(:,4)/100;
counts7 = counts7/100; counts8 = counts8/100;
figure(3)
hp3 = plot(L1_V, counts1,'bv-', L1_V, counts2,'mv-', L1_V, counts4,'yv-', ...
L1_V, counts5,'gv-', L1_V, counts6,'ro-', L1_V3, counts3,'kd-');
set(hp3, 'MarkerFaceColor','w','MarkerSize',8)
legend('Const. E, B (15 keV)','Const. E (15 keV)','Map1 E, B (15 keV)','Map0 E, B (15 keV)','SR off (15 keV)','Const. E, B (20 keV)',3)
axis([0 15 0 100])
grid on
% E_0 = 20 keV, E = 21 kV, B = 360 G
% E_0 = 15 keV, E = 18.1865 kV, B = 311.7691 G
xlabel('Lens L1 voltage (kV)','FontSize',14)
ylabel('Spin Rotator transmission (%)','FontSize',14)
title('Spin Rot. transmission - Constant field vs. Field maps at 15 keV','FontSize',16)
text(1, 15, [{'E_0 = 20 keV, E = 21 kV, B = 360 G'},...
{'E_0 = 15 keV, E = 16.6 kV, B = 312 G'},...
{'12 cm symm. capacitor'},{'Ang. spread = 1.4 deg.'}],'FontSize',14)
set(gca,'FontSize',14)
figure(4)
hp4 = plot(L1_V, counts1,'bv-', L1_V, counts2, 'mv-', L1_V, counts8,'kv-', ...
L1_V, counts7,'rv-', L1_V, counts4,'yv-', L1_V, counts5,'gv-');
set(hp4, 'MarkerFaceColor','w','MarkerSize',8)
legend('Const. E, B fields','Const. E field, B map','Map3 E "3 rods"','Map2 E "1 rod"','Map1 E "12 cm plates"','Map0 E "10 cm plates"',3)
axis([0 15 0 100])
grid on
xlabel('Lens L1 voltage (kV)','FontSize',14)
ylabel('Spin Rotator transmission (%)','FontSize',14)
title('Spin Rot. transmission - E-field const. vs. maps at 15 keV','FontSize',16)
text(6.8, 12, [{'E_0 = 15 keV, E = 15.8 kV, B = 312 G'},...
{'12 cm symm. capacitor'},{'Ang. spread = 1.4 deg.'}],'FontSize',14)
set(gca,'FontSize',14)
return
% SR TOT transm = SR_transm * L1 transm. (SR OFF) => SR_transm. = SR TOT transm / L1 transm. (SR OFF)
hold on
hp1 = plot(L1_V, counts2./counts4*100,'go-');
set(hp1, 'MarkerFaceColor','w','MarkerSize',8)
hp2 = plot(L1_V, da(:,2)./counts4,'yo-');
set(hp2, 'MarkerFaceColor','w','MarkerSize',8)
text(1,82,'L1 transm.','FontSize',12)
text(1,68,'SR transm.','FontSize',12)
text(1,53,'Tot. transm.','FontSize',12)

View File

@ -0,0 +1,44 @@
% Transmission of Spin Rotator as a function of angular dispersion of incoming muons.
% Settings B = 360 G, E = 21 kV.
d = [...
0.0 89.0
0.2 88.8
0.4 86.8
0.7 81.0
1.0 74.1
1.5 62.6
2.0 51.7
2.5 45.6
3.0 42.0
3.5 37.71
4.0 34.03
];
d1 = [...
0.0 92.99
0.2 92.58
0.4 91.80
0.7 93.08
1.0 92.85
1.5 87.82
2.0 75.97
2.5 62.93
3.0 49.73
3.5 40.12
4.0 34.66
];
ang_sigma = d(:,1); sr_trans = d(:,2);
ang_sigm1 = d1(:,1); sr_trans1 = d1(:,2);
hp = plot(ang_sigma, sr_trans,'ro-');
hold on
hp1= plot(ang_sigm1, sr_trans1,'bo-');
set(hp, 'MarkerFaceColor','w','MarkerSize',8)
set(hp1,'MarkerFaceColor','w','MarkerSize',8)
legend('SR ON','SR OFF',3)
axis([0 4 0 100])
grid on
xlabel('Muon beam angular dispersion \sigma (deg.)','FontSize',14)
ylabel('Spin Rotator transmission (%)','FontSize',14)
text(2.5, 85, [{'E = 21 kV, B = 360 G'},{'10 mm symm. capacitor'},{'p rejection: total'}],'FontSize',14)
set(gca,'FontSize',14)

View File

@ -0,0 +1,59 @@
# This is a macro file for visualizing G4 events.
# It can either be included in another macro or called with /control/exec vis.mac
# Create an OpenGL driver (i.e. a scene handler and viewer)
# Some useful choices: VRML2FILE, OGLSX, OGLIX, DAWNFILE, etc.
/vis/open VRML2FILE
# To calculate volumes and masses uncomment the next two lines
#*/vis/open ATree
#*/vis/ASCIITree/verbose 4
# Create a new empty scene and attach it to handler
/vis/scene/create
# Add world volume, trajectories and hits to the scene
/vis/scene/add/volume
/vis/scene/add/trajectories
/vis/scene/add/hits
/vis/sceneHandler/attach
# Configure the viewer (optional)
/vis/viewer/set/viewpointThetaPhi 235 -45
/vis/viewer/set/lightsThetaPhi 120 60
#/vis/viewer/set/hiddenEdge true
#/vis/viewer/set/style surface
#/vis/viewer/zoom 0.5
# Style: s - surface, w - wireframe
# Note: "surface style" and "hiddenEdge true" remove transparency!
# Other viewpoints (25 55) (235 -45) (125 35)
# Store trajectory information for visualisation (set to 0 if too many tracks cause core dump)
/tracking/storeTrajectory 1
#At the end of each event (default behaviour)
#/vis/scene/endOfEventAction refresh
#At the end of run of X events - Data from X events will be superimposed
/vis/scene/endOfEventAction accumulate
#At the end of Y runs - Data from Y runs will be superimposed
#/vis/scene/endOfRunAction accumulate
# Coloured trajectories for an easier particle identification:
# PDG IDs and colours: e- 11 red, e+ -11 blue, nu_e 12 yellow,
# mu+ -13 magenta, anti_nu_mu -14 green, gamma 22 grey
#
#/vis/modeling/trajectories/create/drawByCharge
#/vis/modeling/trajectories/drawByCharge-0/set 1 cyan
/vis/modeling/trajectories/create/drawByParticleID
/vis/modeling/trajectories/drawByParticleID-0/set gamma grey
/vis/modeling/trajectories/drawByParticleID-0/setRGBA mu+ 1 0 1 1
/vis/modeling/trajectories/drawByParticleID-0/setRGBA e+ 0 0 0.8 0.5
/vis/modeling/trajectories/drawByParticleID-0/setRGBA nu_e 0.7 0.7 0 1
/vis/modeling/trajectories/drawByParticleID-0/setRGBA anti_nu_mu 0.3 1.0 0 0.5
# Verbosity of hits
#/hits/verbose 2
# Output just the detector geometry
/vis/viewer/flush

132
geant4/spin_rot/sr1.cc Normal file
View File

@ -0,0 +1,132 @@
#include "sr1DetectorConstruction.hh"
#include "sr1PhysicsList.hh"
#include "sr1PrimaryGeneratorAction.hh"
#include "sr1RunAction.hh"
#include "sr1EventAction.hh"
#include "sr1SteppingAction.hh"
#include "sr1SteppingVerbose.hh"
#include "G4RunManager.hh"
#include "G4UImanager.hh"
#include "G4UIterminal.hh"
#include "G4UItcsh.hh"
#include "Randomize.hh"
#include <X11/Xlib.h>
#ifdef G4VIS_USE
//#include "sr1VisManager.hh"
#include "G4VisExecutive.hh" // TS Trajectory drawing by ID or charge
#include "G4TrajectoryDrawByCharge.hh"
#endif
#include "sr1RootOutput.hh"
#include "sr1Parameters.hh"
#include "sr1ErrorMessage.hh"
int main(int argc,char** argv) {
XInitThreads();
// choose the Random engine
// CLHEP::HepRandom::setTheEngine(new CLHEP::RanecuEngine); // the /sr1/run/randomOption 2 does not work with RanecuEngine
CLHEP::HepRandom::setTheEngine(new CLHEP::HepJamesRandom);
//my Verbose output class
G4VSteppingVerbose::SetInstance(new sr1SteppingVerbose);
// Run manager
G4RunManager * runManager = new G4RunManager;
// Create class "myParameters", which is a collection of many different parameters
G4String steeringFileName=argv[1];
sr1Parameters* myParameters = new sr1Parameters(steeringFileName);
// sr1Parameters* myParameters = new sr1Parameters();
// Create class "sr1ErrorMessage"
sr1ErrorMessage* myErrorMessage = new sr1ErrorMessage();
// Create Root class for storing the output of the Geant simulation
sr1RootOutput* myRootOutput = new sr1RootOutput();
// UserInitialization classes (mandatory)
sr1DetectorConstruction* sr1detector = new sr1DetectorConstruction;
// if(argc>2) { sr1detector->SetInputParameterFileName(argv[2]); }
// else
if (argc>1) {
G4int myRunNr=atoi(argv[1]); // Get the run number from the name of the
// parameter file, if it starts with a number.
if (myRunNr>0) {runManager->SetRunIDCounter(myRunNr);}
sr1detector->SetInputParameterFileName(argv[1]);
}
runManager->SetUserInitialization(sr1detector);
runManager->SetUserInitialization(new sr1PhysicsList);
#ifdef G4VIS_USE
// Visualization, if you choose to have it!
G4VisManager* visManager = new G4VisExecutive; // sr1VisManager; TS Trajectory drawing by ID or charge
visManager->Initialize();
#endif
// UserAction classes
runManager->SetUserAction(new sr1PrimaryGeneratorAction(sr1detector));
runManager->SetUserAction(new sr1RunAction);
runManager->SetUserAction(new sr1EventAction);
runManager->SetUserAction(new sr1SteppingAction);
//Initialize G4 kernel
runManager->Initialize();
//get the pointer to the User Interface manager
G4UImanager * UI = G4UImanager::GetUIpointer();
if(argc==1)
// Define (G)UI terminal for interactive mode
{
// G4UIterminal is a (dumb) terminal.
G4UIsession * session = 0;
#ifdef G4UI_USE_TCSH
session = new G4UIterminal(new G4UItcsh);
#else
session = new G4UIterminal();
#endif
UI->ApplyCommand("/control/execute vis.mac");
session->SessionStart();
delete session;
}
else
// Batch mode
{
G4String command = "/control/execute ";
G4String fileName = argv[1];
UI->ApplyCommand(command+fileName);
if (argc>2) {
G4String SecondArgument = argv[2];
if (SecondArgument=="idle") {
G4UIsession * session = 0;
#ifdef G4UI_USE_TCSH
session = new G4UIterminal(new G4UItcsh);
#else
session = new G4UIterminal();
#endif
session->SessionStart();
delete session;
}
}
}
#ifdef G4VIS_USE
delete visManager;
#endif
delete myRootOutput;
delete myErrorMessage;
delete myParameters;
delete runManager;
return 0;
}

View 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 "sr1Parameters.hh"
#include "sr1ErrorMessage.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. !
sr1ErrorMessage::GetInstance()->sr1Error(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(sr1Parameters::nrOfEventsToBeGenerated)/(nrOfSteps);
G4double fieldStep = (finalField-initialField)/(nrOfSteps-1);
// G4cout<<"sr1Parameters::nrOfEventsToBeGenerated="<<sr1Parameters::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;
}
}

View 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));
}
}

View 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 "sr1RootOutput.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;
}
}
sr1RootOutput::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();
sr1RootOutput::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));
}
}

View 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;
}

View 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;
}

View 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;
}

1032
geant4/spin_rot/src/meyer.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,187 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "sr1EventAction.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 "sr1MagneticField.hh"
#include "sr1TabulatedField3D.hh"
#include "sr1TabulatedField2D.hh"
#include "sr1RootOutput.hh"
#include "sr1ErrorMessage.hh"
#include "sr1SteppingAction.hh"
#include "F04GlobalField.hh"
//#include "F04ElementField.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool sr1EventAction::setRandomNrSeedAccordingEventNr=0;
G4bool sr1EventAction::setRandomNrSeedFromFile=0;
G4int sr1EventAction::nHowOftenToPrintEvent=10000;
//vector<int> * sr1EventAction::RandomNrInitialisers=NULL;
//long sr1EventAction::myEventNr=0;
sr1EventAction::sr1EventAction() {
pointer=this;
fieldValueStart=0;
pointerToSeedVector = new vector<int>;
timeDependentField=false;
lastFieldValue=-10000*tesla;
pointerToMusrUniformField=NULL;
pointerToTabulatedField3D=NULL;
pointerToTabulatedField2D=NULL;
latestEventNr=-1;
}
sr1EventAction* sr1EventAction::pointer=0;
sr1EventAction* sr1EventAction::GetInstance() {
return pointer;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1EventAction::~sr1EventAction()
{
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void sr1EventAction::BeginOfEventAction(const G4Event* evt) {
// test error
// sr1ErrorMessage::GetInstance()->sr1Error(SERIOUS,"test error",true);
//
// G4cout<<"sr1EventAction::BeginOfEventAction: KAMIL"<<G4endl;
sr1SteppingAction::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;}
sr1RootOutput* myRootOutput = sr1RootOutput::GetRootInstance();
myRootOutput->SetFieldValue(actualFieldValue);
// if (sr1DetectorMessenger::setRandomNrSeedAccordingEventNr) {
if (setRandomNrSeedFromFile) {
// G4cout<<"RandomNrInitialisers.size()="<<RandomNrInitialisers->size()<<G4endl;
if (thisEventNr < (long) pointerToSeedVector->size()) {
G4cout <<"sr1EventAction.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 sr1EventAction::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> * sr1EventAction::pointerToSeedVector=NULL;
vector<int> * sr1EventAction::GetPointerToSeedVector() {
return pointerToSeedVector;
}
void sr1EventAction::SetTimeDependentField(G4bool setFieldToBeTimeDependend, G4double initialField,
G4double finalField, G4int nrOfSteps) {
timeDependentField = setFieldToBeTimeDependend;
fieldValueStart = initialField;
fieldValueEnd = finalField;
fieldNrOfSteps = nrOfSteps;
fieldStep = (finalField-initialField)/(nrOfSteps-1);
G4cout<<"---&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&---"<<G4endl;
}

View File

@ -0,0 +1,341 @@
#include "sr1Axial2DElField.hh"
#include "G4UnitsTable.hh"
//#include "sr1Parameters.hh"
sr1Axial2DElField::sr1Axial2DElField(const char* filename, G4double fieldValue, G4double lenUnit, G4double fieldNormalisation, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter) : F04ElementField(positionOfTheCenter, logVolume),
ffieldValue(fieldValue)
//sr1Axial2DElField::sr1Axial2DElField(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;
}
///sr1Axial2DElField::~sr1Axial2DElField() /// Made virtual!
///{
/// delete [] &rField ;
/// delete [] &zField ;
///}
void sr1Axial2DElField::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 sr1Axial2DElField::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 sr1Axial2DElField::GetNominalFieldValue() {
return ffieldValue;
}
void sr1Axial2DElField::SetNominalFieldValue(G4double newFieldValue) {
// Rescale the EM field to account for the new applied field value
ffieldValue=newFieldValue;
G4cout<<"sr1Axial2DElField.cc: ffieldValue changed to = "<< ffieldValue/kilovolt<<" kV."<<G4endl;
}
void sr1Axial2DElField::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 sr1Axial2DElField::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];
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,210 @@
#include "sr1DetectorMessenger.hh"
#include "sr1DetectorConstruction.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 "sr1EventAction.hh" // cks needed for the initialisation of the random nr. generator by event nr.
//#include <fstream>
//#include <vector>
#include "globals.hh"
//#include "sr1Parameters.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1DetectorMessenger::sr1DetectorMessenger(sr1DetectorConstruction* myDet)
:myDetector(myDet)
{
sr1Dir = new G4UIdirectory("/sr1/");
sr1Dir->SetGuidance("UI commands specific to this example.");
CommandCmd = new G4UIcmdWithAString("/sr1/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("/sr1/run/");
runDir->SetGuidance("sr1 run control");
RunIDSetCmd = new G4UIcmdWithAnInteger("/sr1/run/runID",this);
RunIDSetCmd->SetGuidance("Set the run number");
RunIDSetCmd->SetParameterName("something",false);
RunIDSetCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
RandomOptionCmd = new G4UIcmdWithAnInteger("/sr1/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("/sr1/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("/sr1/det/");
detDir->SetGuidance("detector control.");
// WhichProcessesCmd = new G4UIcmdWithAString("/sr1/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("/sr1/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("/sr1/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("/sr1/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("/sr1/det/setGaussianField",this);
// GFieldCmd = new G4UIcmdWith3VectorAndUnit("/sr1/det/setGaussianField",this);
GFieldCmd = new G4UIcmdWith3Vector("/sr1/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("/sr1/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......
sr1DetectorMessenger::~sr1DetectorMessenger()
{
// delete WhichProcessesCmd;
delete UpdateCmd;
delete detDir;
delete sr1Dir;
delete CommandCmd;
// delete FieldCmd;
delete UFieldCmd;
delete GFieldCmd;
/// delete UEFieldCmd;
delete RunIDSetCmd;
delete RandomOptionCmd;
delete HowOftenToPrintEventCmd;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void sr1DetectorMessenger::SetNewValue(G4UIcommand* command,G4String newValue) {
// if( command == WhichProcessesCmd )
// { sr1Parameters* myParameters = sr1Parameters::GetInstance();
// sr1Parameters -> SetMyProcesses(newValue); }
// sr1Parameters* myParameters = sr1Parameters::GetInstance();
// myParameters -> strcnpy(sr1Parameters::myProcesses,newValue,99);
// sr1Parameters::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;
sr1EventAction::setRandomNrSeedAccordingEventNr=1;
// sr1EventAction::setMyEventNr(70);
}
else if (RandomOption == 3) {
G4cout << "*******************************************" << G4endl;
G4cout << "*** Random Seed set from external file ***" << G4endl;
G4cout << "*******************************************" << G4endl;
sr1EventAction::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 = sr1EventAction::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
// sr1EventAction::RandomNrInitialisers->push_back(num);
}
indata.close();
G4cout << "End-of-file reached.." << seedVector->size()<<G4endl;
// sr1EventAction::RandomNrInitialisers=seedVector;
}
}
if ( command == HowOftenToPrintEventCmd )
{
G4int n = HowOftenToPrintEventCmd->GetNewIntValue(newValue);
sr1EventAction::nHowOftenToPrintEvent=n;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

View File

@ -0,0 +1,62 @@
#include "sr1ErrorMessage.hh"
sr1ErrorMessage::sr1ErrorMessage():nErrors(1)
{
pointerToErrors=this;
severityWord[INFO]="INFO";
severityWord[WARNING]="WARNING";
severityWord[SERIOUS]="SERIOUS";
severityWord[FATAL]="FATAL";
}
sr1ErrorMessage::~sr1ErrorMessage() {}
sr1ErrorMessage* sr1ErrorMessage::pointerToErrors=NULL;
sr1ErrorMessage* sr1ErrorMessage::GetInstance() {
return pointerToErrors;
}
void sr1ErrorMessage::sr1Error(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 sr1ErrorMessage::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;
}

View File

@ -0,0 +1,182 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "sr1EventAction.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 "sr1MagneticField.hh"
#include "sr1TabulatedField3D.hh"
#include "sr1TabulatedField2D.hh"
#include "sr1RootOutput.hh"
#include "sr1ErrorMessage.hh"
#include "sr1SteppingAction.hh" ///
#include "F04GlobalField.hh" /// Are these two really needed ??
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool sr1EventAction::setRandomNrSeedAccordingEventNr=0;
G4bool sr1EventAction::setRandomNrSeedFromFile=0;
G4int sr1EventAction::nHowOftenToPrintEvent=10000;
//vector<int> * sr1EventAction::RandomNrInitialisers=NULL;
//long sr1EventAction::myEventNr=0;
sr1EventAction::sr1EventAction() {
pointer=this;
fieldValueStart=0;
pointerToSeedVector = new vector<int>;
timeDependentField=false;
lastFieldValue=-10000*tesla;
pointerToMusrUniformField=NULL;
pointerToTabulatedField3D=NULL;
pointerToTabulatedField2D=NULL;
latestEventNr=-1;
}
sr1EventAction* sr1EventAction::pointer=0;
sr1EventAction* sr1EventAction::GetInstance() {
return pointer;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1EventAction::~sr1EventAction()
{
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void sr1EventAction::BeginOfEventAction(const G4Event* evt) {
// test error
// sr1ErrorMessage::GetInstance()->sr1Error(SERIOUS,"test error",true);
//
sr1SteppingAction::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;}
sr1RootOutput* myRootOutput = sr1RootOutput::GetRootInstance();
myRootOutput->SetFieldValue(actualFieldValue);
// if (sr1DetectorMessenger::setRandomNrSeedAccordingEventNr) {
if (setRandomNrSeedFromFile) {
// G4cout<<"RandomNrInitialisers.size()="<<RandomNrInitialisers->size()<<G4endl;
if (thisEventNr < (long) pointerToSeedVector->size()) {
G4cout <<"sr1EventAction.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 sr1EventAction::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> * sr1EventAction::pointerToSeedVector=NULL;
vector<int> * sr1EventAction::GetPointerToSeedVector() {
return pointerToSeedVector;
}
void sr1EventAction::SetTimeDependentField(G4bool setFieldToBeTimeDependend, G4double initialField,
G4double finalField, G4int nrOfSteps) {
timeDependentField = setFieldToBeTimeDependend;
fieldValueStart = initialField;
fieldValueEnd = finalField;
fieldNrOfSteps = nrOfSteps;
fieldStep = (finalField-initialField)/(nrOfSteps-1);
G4cout<<"---&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&---"<<G4endl;
}

View File

@ -0,0 +1,28 @@
#include "sr1GaussianField.hh"
sr1GaussianField::sr1GaussianField(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 sr1GaussianField::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 sr1GaussianField::GetFieldSetValue() {
return ffieldValue;
}

View File

@ -0,0 +1,70 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "sr1MagneticField.hh"
#include "G4FieldManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1MagneticField::sr1MagneticField()
: G4UniformMagField(G4ThreeVector())
{
GetGlobalFieldManager()->SetDetectorField(this);
GetGlobalFieldManager()->CreateChordFinder(this);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1MagneticField::sr1MagneticField(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 sr1MagneticField::SetFieldValue(G4double fieldValue)
{
G4UniformMagField::SetFieldValue(G4ThreeVector(0,0,fieldValue));
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// Set the value of the Global Field
//
void sr1MagneticField::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......
sr1MagneticField::~sr1MagneticField()
{
// GetGlobalFieldManager()->SetDetectorField(0);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4TransportationManager.hh"
G4FieldManager* sr1MagneticField::GetGlobalFieldManager()
{
return G4TransportationManager::GetTransportationManager()->GetFieldManager();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

View File

@ -0,0 +1,106 @@
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
// Muonium Formation according to yield.cc function (through GetYields method).
// Id : sr1MuFormation.cc, v 1.4
// Author: Taofiq PARAISO, T. Shiroka
// Date : 2007-12
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#include "sr1MuFormation.hh"
using namespace std;
sr1MuFormation::sr1MuFormation(const G4String& name, G4ProcessType aType)
: G4VDiscreteProcess(name, aType){}
sr1MuFormation::~sr1MuFormation(){}
G4VParticleChange* sr1MuFormation::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 sr1MuFormation::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 sr1MuFormation::GetMeanFreePath(const G4Track&,
G4double,
G4ForceCondition* condition)
{
*condition = Forced;
return DBL_MAX;
}
void sr1MuFormation::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 sr1MuFormation::PrepareSecondary(const G4Track& track)
{
if(p_name=="mu+")
{
aSecondary = new G4Track(DP,track.GetGlobalTime(),track.GetPosition());
}
}

View File

@ -0,0 +1,81 @@
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
// Muonium "Scattering"
// Id : sr1MuScatter.cc, v 1.4
// Author: Taofiq PARAISO, T. Shiroka
// Date : 2007-12
// Notes : Simplified model for Mu scattering. Spin effects have been excluded.
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#include "sr1MuScatter.hh"
using namespace std;
sr1MuScatter::sr1MuScatter(const G4String& name,
G4ProcessType aType)
: G4VDiscreteProcess(name, aType){}
sr1MuScatter:: ~sr1MuScatter(){}
/*! - 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* sr1MuScatter::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 sr1MuScatter::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 sr1MuScatter::GetMeanFreePath(const G4Track&,
G4double,
G4ForceCondition* condition)
{
*condition = Forced;
return DBL_MAX;
}
void sr1MuScatter::PrepareSecondary(const G4Track& track)
{
aSecondary = new G4Track(DP,track.GetDynamicParticle()->GetPreAssignedDecayProperTime(),track.GetPosition());
}

View 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: sr1Muonium.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 "sr1Muonium.hh"
#include "G4ParticleTable.hh"
#include "MuDecayChannel.hh"
#include "G4DecayTable.hh"
// ######################################################################
// ### MUONIUM ###
// ######################################################################
sr1Muonium* sr1Muonium::theInstance = 0;
sr1Muonium* sr1Muonium::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<sr1Muonium*>(anInstance);
return theInstance;
}
sr1Muonium* sr1Muonium::MuoniumDefinition()
{
return Definition();
}
sr1Muonium* sr1Muonium::Muonium()
{
return Definition();
}

View File

@ -0,0 +1,71 @@
#include "sr1Parameters.hh"
///sr1Parameters::sr1Parameters()
/// :typeOfProcesses("standard")
///{
/// pointerToParameters=this;
///}
sr1Parameters::sr1Parameters(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 sr1DetectorConstruction.cc class).
FILE *fSteeringFile=fopen(steeringFileName.c_str(),"r");
if (fSteeringFile==NULL) {
G4cout<<"sr1Parameters::sr1Parameters: steeringFileName=\""<<steeringFileName
<<"\" not opened for some reason."<<G4endl;
}
G4cout<<"sr1Parameters::sr1Parameters: 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);
sr1Parameters::nrOfEventsToBeGenerated = nev;
}
// Now find out about some other private parameters that also need to be initialised at an early stage
if (strcmp(tmpString0,"/sr1/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){ sr1Parameters::boolG4GeneralParticleSource = true; }
}
}
}
fclose(fSteeringFile);
}
sr1Parameters::~sr1Parameters() {}
sr1Parameters* sr1Parameters::pointerToParameters=NULL;
sr1Parameters* sr1Parameters::GetInstance() {
return pointerToParameters;
}
G4bool sr1Parameters::storeOnlyEventsWithHits =true;
G4double sr1Parameters::signalSeparationTime=100*nanosecond;
G4bool sr1Parameters::storeOnlyTheFirstTimeHit=false;
G4bool sr1Parameters::includeMuoniumProcesses =true;
G4bool sr1Parameters::field_DecayWithSpin=false; //Added by TS to confrom with the new StepAction ...
G4bool sr1Parameters::boolG4GeneralParticleSource=false; ///! This is not strictly necessary! TS
G4int sr1Parameters::nrOfEventsToBeGenerated=0;

View File

@ -0,0 +1,416 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "globals.hh"
#include "G4ios.hh"
#include "sr1PhysicsList.hh"
#include "G4VPhysicsConstructor.hh"
#include "G4ProcessManager.hh"
#include "G4ParticleTypes.hh"
#include "G4MuonDecayChannel.hh"
#include "G4DecayTable.hh"
//#include "sr1MuonDecayChannel.hh"
//#include "sr1Decay.hh"
//cks Added to have Geant default muon decay with spin
#include "G4MuonDecayChannelWithSpin.hh"
//#include "G4AtRestSpinPrecession.hh"
//TS Muonium "particle"
#include "sr1Muonium.hh"
#include "MuDecayChannel.hh"
#include "MuDecayChannelWithSpin.hh"
#include "sr1Parameters.hh"
// Constructor and Destructor
sr1PhysicsList::sr1PhysicsList():G4VUserPhysicsList()
{
defaultCutValue = 0.1*mm; // 1.0*cm;
SetVerboseLevel(0);
}
sr1PhysicsList::~sr1PhysicsList()
{}
// Construction of the different particles (calls different construction methods)
void sr1PhysicsList::ConstructParticle()
{
ConstructBosons();
ConstructLeptons();
ConstructBaryons();
}
// Bosons
void sr1PhysicsList::ConstructBosons()
{
// pseudo-particles
G4Geantino::GeantinoDefinition();
G4ChargedGeantino::ChargedGeantinoDefinition();
// gamma
G4Gamma::GammaDefinition();
}
// Leptons
void sr1PhysicsList::ConstructLeptons()
{
// e+/-
G4Electron::ElectronDefinition();
G4Positron::PositronDefinition();
// mu+/-
G4MuonPlus::MuonPlusDefinition();
G4MuonMinus::MuonMinusDefinition();
// Muonium - TS
sr1Muonium::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));
sr1Muonium::MuoniumDefinition() -> SetDecayTable(MuoniumDecayTable);
//MuoniumDecayTable ->DumpInfo(); // Info on muonium decay channels
}
// Mesons (only some light mesons)
void sr1PhysicsList::ConstructMesons()
{
G4PionPlus::PionPlusDefinition();
G4PionMinus::PionMinusDefinition();
G4PionZero::PionZeroDefinition();
}
// Baryons
void sr1PhysicsList::ConstructBaryons()
{
G4Proton::ProtonDefinition();
G4AntiProton::AntiProtonDefinition();
G4Neutron::NeutronDefinition();
G4AntiNeutron::AntiNeutronDefinition();
}
// Physical processes - general
void sr1PhysicsList::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 "sr1AtRestSpinRotation.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 "sr1MuFormation.hh" // includes the yield function Y = Y(E).
// For a simple Muonium "scattering" when Mu hits solid materials
#include "sr1MuScatter.hh"
// Construction methods for the different processes
void sr1PhysicsList::ConstructEM()
{
G4String myTypeOfProcesses = sr1Parameters::GetInstance()->GetMyTypeOfProcesses();
G4cout<<" uuuuuuuuu myTypeOfProcesses="<<myTypeOfProcesses<<G4endl;
G4bool inclMuProcesses = sr1Parameters::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 sr1MuFormation();
pmanager->AddProcess(aMuoniumFormation);
pmanager->SetProcessOrdering(aMuoniumFormation,idxPostStep,2);
//pmanager->AddProcess(new sr1MuFormation, -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 sr1AtRestSpinRotation, 1, -1, -1);
// sr1Decay* theDecayProcess = new sr1Decay();
// 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();
//sr1DecayWithSpin* theDecayProcess = new sr1DecayWithSpin();
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 sr1MuScatter, -1, 1, 1); <--- ERROR ?!?
//pmanager->AddProcess(new sr1MuScatter, -1, -1, 1); //<--- ERROR ?!?
// Muonium "scattering"
G4VProcess* aMuScatt = new sr1MuScatter();
pmanager->AddProcess(aMuScatt);
pmanager->SetProcessOrdering(aMuScatt, idxPostStep, 1);
// Muonium decay process
G4Decay* theDecayProcess = new G4Decay();
//sr1DecayWithSpin* theDecayProcess = new sr1DecayWithSpin();
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 sr1PhysicsList::ConstructGeneral()
{
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4Region.hh"
#include "G4RegionStore.hh"
#include "G4ProductionCuts.hh"
void sr1PhysicsList::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 << "sr1PhysicsList.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......

View File

@ -0,0 +1,319 @@
#include "sr1PrimaryGeneratorAction.hh"
#include "sr1DetectorConstruction.hh"
#include "sr1PrimaryGeneratorMessenger.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 "sr1RootOutput.hh" //cks for storing some info in the Root output file
#include "sr1ErrorMessage.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
sr1PrimaryGeneratorAction::sr1PrimaryGeneratorAction(
sr1DetectorConstruction* sr1DC)
:sr1Detector(sr1DC), 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 sr1ParticleGun(n_particle);
particleGun = new G4ParticleGun(n_particle);
//create a messenger for this class
gunMessenger = new sr1PrimaryGeneratorMessenger(this);
// default particle kinematic
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
G4ParticleDefinition* particle= particleTable->FindParticle("mu+");
particleGun->SetParticleDefinition(particle);
mu_mass = particle->GetPDGMass();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
sr1PrimaryGeneratorAction::~sr1PrimaryGeneratorAction()
{
delete particleGun;
delete gunMessenger;
if (takeMuonsFromTurtleFile) {fclose(fTurtleFile);}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void sr1PrimaryGeneratorAction::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,"sr1PrimaryGeneratorAction::GeneratePrimaries: Too strict restriction on the generated radius.");
// sr1ErrorMessage::GetInstance()->sr1Error(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,"sr1PrimaryGeneratorAction::GeneratePrimaries: Too strict restriction on the generated z-coordinate.");
// sr1ErrorMessage::GetInstance()->sr1Error(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<<"sr1PrimaryGeneratorAction::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<<"sr1PrimaryGeneratorAction::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<<"sr1PrimaryGeneratorAction::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<<"sr1PrimaryGeneratorAction.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->SetParticleEnergy(particleEnergy);
particleGun->SetParticleMomentumDirection(G4ThreeVector(px,py,pz));
particleGun->SetParticlePolarization(G4ThreeVector(xpolaris,ypolaris,zpolaris));
particleGun->GeneratePrimaryVertex(anEvent);
// G4cout<<"sr1PrimaryGeneratorAction: 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<<"sr1PrimaryGeneratorAction: 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:
sr1RootOutput* myRootOutput = sr1RootOutput::GetRootInstance();
myRootOutput->SetInitialMuonParameters(x,y,z,px,py,pz,xpolaris,ypolaris,zpolaris);
}
///////////////////////////////////////////////////////////////////////
//
//
void sr1PrimaryGeneratorAction::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 sr1PrimaryGeneratorAction::SetMuonDecayTimeLimits(G4ThreeVector decayTimeLimits) {
muonDecayTimeMin = decayTimeLimits[0];
muonDecayTimeMax = decayTimeLimits[1];
muonMeanLife = decayTimeLimits[2];
// store the muon decay time parameters to the Root output
sr1RootOutput* myRootOutput = sr1RootOutput::GetRootInstance();
myRootOutput->StoreGeantParameter(2,muonDecayTimeMin/microsecond);
myRootOutput->StoreGeantParameter(3,muonDecayTimeMax/microsecond);
myRootOutput->StoreGeantParameter(4,muonMeanLife/microsecond);
}
void sr1PrimaryGeneratorAction::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;}
}

View File

@ -0,0 +1,136 @@
#include "sr1PrimaryGeneratorMessenger.hh"
#include "sr1PrimaryGeneratorAction.hh"
#include "G4UIcmdWithAString.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "G4UIcmdWithADouble.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UIcmdWith3Vector.hh"
#include "G4UIcmdWith3VectorAndUnit.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
sr1PrimaryGeneratorMessenger::sr1PrimaryGeneratorMessenger(sr1PrimaryGeneratorAction* sr1Gun)
:sr1Action(sr1Gun)
{
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....
sr1PrimaryGeneratorMessenger::~sr1PrimaryGeneratorMessenger()
{
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 sr1PrimaryGeneratorMessenger::SetNewValue(G4UIcommand *command, G4String newValue)
{
if( command == setvertexCmd)
{ sr1Action->Setvertex(setvertexCmd->GetNew3VectorValue(newValue));}
else if( command == setvertexSigmaCmd)
{ sr1Action->SetvertexSigma(setvertexSigmaCmd->GetNew3VectorValue(newValue));}
else if( command == setvertexBoundaryCmd)
{ sr1Action->SetvertexBoundary(setvertexBoundaryCmd->GetNew3VectorValue(newValue));}
else if( command == setEnergyCmd)
{ sr1Action->SetEnergy(setEnergyCmd->GetNewDoubleValue(newValue));}
else if( command == setMomentumCmd)
{ sr1Action->SetMomentum(setMomentumCmd->GetNewDoubleValue(newValue));}
else if( command == setMomentumSmearingCmd)
{ sr1Action->SetMomentumSmearing(setMomentumSmearingCmd->GetNewDoubleValue(newValue));}
else if( command == setMomentumBoundaryCmd)
{ sr1Action->SetMomentumBoundary(setMomentumBoundaryCmd->GetNew3VectorValue(newValue));}
else if( command == setTiltAngleCmd)
{ sr1Action->SetTilt(setTiltAngleCmd->GetNew3VectorValue(newValue));}
else if( command == setSigmaTiltAngleCmd)
{ sr1Action->SetSigmaTilt(setSigmaTiltAngleCmd->GetNew3VectorValue(newValue));}
else if( command == setPitchCmd)
{ sr1Action->SetPitch(setPitchCmd->GetNewDoubleValue(newValue));}
else if( command == setMuonPolarizCmd)
{ sr1Action->SetInitialMuonPolariz(setMuonPolarizCmd->GetNew3VectorValue(newValue));}
else if( command == setMuonDecayTimeCmd)
{ sr1Action->SetMuonDecayTimeLimits(setMuonDecayTimeCmd->GetNew3VectorValue(newValue)); }
else if ( command == setTurtleCmd)
{ sr1Action->SetTurtleInput(newValue); }
}

View File

@ -0,0 +1,358 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "sr1RootOutput.hh"
#include "G4RunManager.hh"
#include "G4Run.hh"
//#include "globals.hh"
#include "sr1ErrorMessage.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1RootOutput::sr1RootOutput() {
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......
sr1RootOutput::~sr1RootOutput() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1RootOutput* sr1RootOutput::pointerToRoot=0;
sr1RootOutput* sr1RootOutput::GetRootInstance() {
return pointerToRoot;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool sr1RootOutput::store_runID = true;
G4bool sr1RootOutput::store_eventID = true;
G4bool sr1RootOutput::store_BFieldAtDecay = true;
G4bool sr1RootOutput::store_muIniPosX = true;
G4bool sr1RootOutput::store_muIniPosY = true;
G4bool sr1RootOutput::store_muIniPosZ = true;
G4bool sr1RootOutput::store_muIniMomX = true;
G4bool sr1RootOutput::store_muIniMomY = true;
G4bool sr1RootOutput::store_muIniMomZ = true;
G4bool sr1RootOutput::store_muIniPolX = true;
G4bool sr1RootOutput::store_muIniPolY = true;
G4bool sr1RootOutput::store_muIniPolZ = true;
G4bool sr1RootOutput::store_muDecayDetID= true;
G4bool sr1RootOutput::store_muDecayPosX = true;
G4bool sr1RootOutput::store_muDecayPosY = true;
G4bool sr1RootOutput::store_muDecayPosZ = true;
G4bool sr1RootOutput::store_muDecayTime = true;
G4bool sr1RootOutput::store_muDecayPolX = true;
G4bool sr1RootOutput::store_muDecayPolY = true;
G4bool sr1RootOutput::store_muDecayPolZ = true;
G4bool sr1RootOutput::store_muTargetTime = true;
G4bool sr1RootOutput::store_muTargetPosX = true;
G4bool sr1RootOutput::store_muTargetPosY = true;
G4bool sr1RootOutput::store_muTargetPosZ = true;
G4bool sr1RootOutput::store_muTargetPolX = true;
G4bool sr1RootOutput::store_muTargetPolY = true;
G4bool sr1RootOutput::store_muTargetPolZ = true;
G4bool sr1RootOutput::store_posIniMomX = true;
G4bool sr1RootOutput::store_posIniMomY = true;
G4bool sr1RootOutput::store_posIniMomZ = true;
G4bool sr1RootOutput::store_globalTime = true;
G4bool sr1RootOutput::store_fieldValue = true;
G4bool sr1RootOutput::store_det_ID = true;
G4bool sr1RootOutput::store_det_edep = true;
G4bool sr1RootOutput::store_det_edep_el = true;
G4bool sr1RootOutput::store_det_edep_pos = true;
G4bool sr1RootOutput::store_det_edep_gam = true;
G4bool sr1RootOutput::store_det_edep_mup = true;
G4bool sr1RootOutput::store_det_nsteps = true;
G4bool sr1RootOutput::store_det_length = true;
G4bool sr1RootOutput::store_det_start = true;
G4bool sr1RootOutput::store_det_end = true;
G4bool sr1RootOutput::store_det_x = true;
G4bool sr1RootOutput::store_det_y = true;
G4bool sr1RootOutput::store_det_z = true;
G4bool sr1RootOutput::store_fieldNomVal = true;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void sr1RootOutput::BeginOfRunAction() {
G4cout << "sr1RootOutput::BeginOfRunAction() Defining Root tree and branches ..."<<G4endl;
G4int tmpRunNr=(G4RunManager::GetRunManager())->GetCurrentRun()->GetRunID();
char RootOutputFileName[200];
sprintf(RootOutputFileName, "data/sr1_%i.root", tmpRunNr);
// G4cout<<"RootOutputFileName="<<RootOutputFileName<<"----"<<G4endl;
// rootFile=new TFile("sr1.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_muTargetPosX) {rootTree->Branch("muTargetPosX",&muTargetPosX_t,"muTargetPosX/D");}
if (store_muTargetPosY) {rootTree->Branch("muTargetPosY",&muTargetPosY_t,"muTargetPosY/D");}
if (store_muTargetPosZ) {rootTree->Branch("muTargetPosZ",&muTargetPosZ_t,"muTargetPosZ/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_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 << "sr1RootOutput::BeginOfRunAction() Root tree and branches were defined.\n"<<G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void sr1RootOutput::EndOfRunAction() {
G4cout << "\nsr1RootOutput::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<<"sr1RootOutput::EndOfRunAction() - Root tree written out.\n"<<G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void sr1RootOutput::FillEvent() {
// G4cout << "hhhhh: sr1RootOutput::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 <<"sr1RootOutput.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 sr1RootOutput::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;
muTargetPosX_t=-1000; muTargetPosY_t=-1000; muTargetPosZ_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 sr1RootOutput::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,"sr1RootOutput::SetVolumeIDMapping: Sensitive volume %s already assigned.",logivol.c_str());
sr1ErrorMessage::GetInstance()->sr1Error(FATAL,message,false);
}
else{
SensDetectorMapping[logivol]=volumeID;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int sr1RootOutput::ConvertVolumeToID(std::string logivol) {
G4int volumeID = SensDetectorMapping[logivol];
if (volumeID==0) {
char message[100];
sprintf(message,"sr1RootOutput::ConvertVolumeToID: No ID number assigned to sensitive volume %s .",logivol.c_str());
sr1ErrorMessage::GetInstance()->sr1Error(SERIOUS,"message",true);
}
return volumeID;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void sr1RootOutput::SetSaveDetectorInfo (G4int ID, G4int particleID, G4double x, G4double y, G4double z,
G4double px, G4double py, G4double pz) {
if (save_n>=save_nMax) {
char message[200];
sprintf(message,"sr1RootOutput.cc::SetSaveDetectorInfo(): more \"save\" hits then allowed: save_nMax=%i",save_nMax);
sr1ErrorMessage::GetInstance()->sr1Error(SERIOUS,message,true);
}
else {
save_detID[save_n]=ID;
save_particleID[save_n]=particleID;
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 sr1RootOutput::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,
"sr1RootOutput.cc::SetFieldNomVal(): more electromagnetic fields then allowed: maxNFieldnNominalValues=%i",
maxNFieldnNominalValues);
sr1ErrorMessage::GetInstance()->sr1Error(SERIOUS,message,true);
}
}

View File

@ -0,0 +1,85 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// Make G4Timer appear first!
#include "G4Timer.hh"
#include "sr1RunAction.hh"
#include "sr1EventAction.hh"
#include "G4Run.hh"
#include "sr1ErrorMessage.hh"
#include "F04GlobalField.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1RunAction::sr1RunAction() {
timer = new G4Timer;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1RunAction::~sr1RunAction() {
delete timer;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void sr1RunAction::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 sr1EventAction class, as it will
// be needed for the time dependent magnetic field;
sr1EventAction* pointerToEventAction = sr1EventAction::GetInstance();
pointerToEventAction->SetNumberOfEventsInThisRun(aRun->GetNumberOfEventToBeProcessed());
//
sr1RootOutput::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();
sr1RootOutput::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 sr1RunAction::EndOfRunAction(const G4Run* aRun) {
sr1RootOutput::GetRootInstance()->EndOfRunAction();
sr1ErrorMessage::GetInstance()->PrintErrorSummary();
timer->Stop();
G4cout << "sr1RunAction::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......

View File

@ -0,0 +1,156 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "sr1ScintHit.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<sr1ScintHit> sr1ScintHitAllocator;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1ScintHit::sr1ScintHit() {
}
G4int sr1ScintHit::ScintMultihit=0;
G4int sr1ScintHit::runIDoldScint=-1;
G4int sr1ScintHit::eventIDoldScint=-1;
G4int sr1ScintHit::NIS=0;
G4int sr1ScintHit::ScintChamberNbold=-1;
G4int sr1ScintHit::verboseLevel=0;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1ScintHit::~sr1ScintHit() {
//save the Tree header. The file will be automatically closed
//when going out of the function scope
// rootTree->Write();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1ScintHit::sr1ScintHit(const sr1ScintHit& right)
: G4VHit()
{
particleName = right.particleName;
trackID = right.trackID;
edep = right.edep;
pre_pos = right.pre_pos;
pol = right.pol;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
const sr1ScintHit& sr1ScintHit::operator=(const sr1ScintHit& 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 sr1ScintHit::operator==(const sr1ScintHit& right) const
{
return (this==&right) ? 1 : 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void sr1ScintHit::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 sr1ScintHit::Print()
{
if (verboseLevel>2) G4cout<<"VERBOSE 3: Kamil: sr1ScintHit::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......

View File

@ -0,0 +1,383 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//cksdel #include "sr1RunAction.hh"
#include "sr1ScintSD.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 "sr1Parameters.hh"
#include "sr1ErrorMessage.hh"
#include <vector>
//bool myREMOVEfunction (int i,int j) { return (i<j); }
//bool timeOrdering (sr1ScintHit hit1, sr1ScintHit 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......
sr1ScintSD::sr1ScintSD(G4String name)
:G4VSensitiveDetector(name)
{
G4String HCname;
collectionName.insert(HCname="scintCollection");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1ScintSD::~sr1ScintSD(){ }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void sr1ScintSD::Initialize(G4HCofThisEvent* HCE) {
if (verboseLevel>1) G4cout<<"VERBOSE 2: sr1ScintSD::Initialize\n";
// Positron_momentum_already_stored=0;
// Comment the following lines to disable output of initial variables
// sr1RootOutput* myRootOutput = sr1RootOutput::GetRootInstance();
// myRootOutput->ClearAllRootVariables();
scintCollection = new sr1ScintHitsCollection
(SensitiveDetectorName,collectionName[0]);
static G4int HCID = -1;
if(HCID<0) {
HCID = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[0]);
if (verboseLevel>1) G4cout<<"VERBOSE 2: sr1ScintSD::HCID was <0\n, now HCID="<<HCID<<"\n";
}
HCE->AddHitsCollection( HCID, scintCollection );
myStoreOnlyEventsWithHits = sr1Parameters::storeOnlyEventsWithHits;
mySignalSeparationTime = sr1Parameters::signalSeparationTime;
myStoreOnlyTheFirstTimeHit= sr1Parameters::storeOnlyTheFirstTimeHit;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool sr1ScintSD::ProcessHits(G4Step* aStep,G4TouchableHistory*)
{
if (verboseLevel>1) G4cout<<"VERBOSE 2: sr1ScintSD::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.
// sr1RootOutput* myRootOutput = sr1RootOutput::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;
sr1ScintHit* newHit = new sr1ScintHit();
// 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 sr1ScintSD::EndOfEvent(G4HCofThisEvent*) {
if (verboseLevel>1) {
G4cout<<"VERBOSE 2: sr1ScintSD::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;
sr1RootOutput* myRootOutput = sr1RootOutput::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) {
sr1ScintHit* firstHit = (*scintCollection)[0];
myRootOutput->SetGlobTime(firstHit->GetGlobalTime());
const G4int det_IDmax = sr1RootOutput::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=sr1RootOutput::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++) {
sr1ScintHit* 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
sr1ScintHit* 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,"sr1ScintSD.cc::EndOfEvent(): untreated particle \"%s\" deposited energy.",aParticleName.c_str());
sr1ErrorMessage::GetInstance()->sr1Error(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,"sr1ScintSD.cc::EndOfEvent(): number of signals exceeds maximal allowed value.");
sr1ErrorMessage::GetInstance()->sr1Error(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,"sr1ScintSD.cc::EndOfEvent(): UNTREATED PARTICLE \"%s\" deposited energy.",aParticleName.c_str());
sr1ErrorMessage::GetInstance()->sr1Error(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 sr1RootOutput 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......

View File

@ -0,0 +1,99 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "sr1ShieldHit.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<sr1ShieldHit> sr1ShieldHitAllocator;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1ShieldHit::sr1ShieldHit() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1ShieldHit::~sr1ShieldHit() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
sr1ShieldHit::sr1ShieldHit(const sr1ShieldHit& 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 sr1ShieldHit& sr1ShieldHit::operator=(const sr1ShieldHit& 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 sr1ShieldHit::operator==(const sr1ShieldHit& right) const
{
return (this==&right) ? 1 : 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void sr1ShieldHit::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 sr1ShieldHit::Print()
{
G4EventManager* fEventManager = G4EventManager::GetEventManager();
fEventManager->AbortCurrentEvent();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

Some files were not shown because too many files have changed in this diff Show More