construction wrapper seems to work

This commit is contained in:
Jan Kieseler
2023-09-07 23:31:46 +02:00
parent 3521cfd79e
commit 0adb64f763
6 changed files with 237 additions and 109 deletions
+62
View File
@@ -0,0 +1,62 @@
#include "ConstructionWrapper.hh"
Layer::Layer(){
thickness = 0;
material = "";
nx = 1;
ny = 1;
isActive = false;
physicalVolume = nullptr;
}
void Layer::setThickness(double thickness){
this->thickness = thickness;
}
void Layer::setMaterial(std::string material){
this->material = material;
}
void Layer::setNx(int nx){
this->nx = nx;
}
void Layer::setNy(int ny){
this->ny = ny;
}
void Layer::setIsActive(bool isActive){
this->isActive = isActive;
}
void Layer::assignPhysicalVolume(G4VPhysicalVolume* physicalVolume){
this->physicalVolume = physicalVolume;
}
ConstructionWrapper::ConstructionWrapper(double xy_width){
xywidth = xy_width;
}
void ConstructionWrapper::addLayer(double thickness, std::string material, bool isActive, int nx, int ny){
Layer layer;
layer.setThickness(thickness);
layer.setMaterial(material);
layer.setIsActive(isActive);
if(!isActive){
nx = 1;
ny = 1;
}
layer.setNx(nx);
layer.setNy(ny);
layer.sens_xwidth = xywidth/(float)nx;
layer.sens_ywidth = xywidth/(float)ny;
layers.push_back(layer);
}
const std::vector<Layer> & ConstructionWrapper::getLayers() const{
return layers;
}
std::vector<Layer> & ConstructionWrapper::getLayers(){
return layers;
}
+98 -102
View File
@@ -49,10 +49,48 @@
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4PVParameterised.hh"
#include "G4VPVParameterisation.hh"
namespace B4
{
//helper
class LayerParametrisation: public G4VPVParameterisation{
public:
LayerParametrisation(Layer layer, G4double position = 0): G4VPVParameterisation(), layer(layer), position(position){
}
~LayerParametrisation() = default;
void ComputeTransformation(const G4int copyNo, G4VPhysicalVolume* physVol) const{
G4double x = 0;
G4double y = 0;
G4double z = 0;
if(layer.nx > 1){
x = (copyNo % layer.nx) * layer.sens_xwidth*cm;
}
if(layer.ny > 1){
y = (copyNo / layer.nx) * layer.sens_ywidth*cm;
}
G4ThreeVector origin(x, y, z);
origin -= G4ThreeVector(layer.sens_xwidth * ((float)layer.nx-1) / 2.*cm, layer.sens_ywidth * ((float)layer.ny-1) / 2.*cm, 0);
origin += G4ThreeVector(0., 0., position);
physVol->SetTranslation(origin);
}
void ComputeDimensions(G4Box& box, const G4int copyNo, const G4VPhysicalVolume* physVol) const{
box.SetXHalfLength(layer.sens_xwidth/2*cm);
box.SetYHalfLength(layer.sens_ywidth/2*cm);
box.SetZHalfLength(layer.thickness/2*cm);
}
private:
Layer layer;
G4double position;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4ThreadLocal
@@ -75,18 +113,11 @@ void DetectorConstruction::DefineMaterials()
{
// Lead material defined using NIST Manager
auto nistManager = G4NistManager::Instance();
nistManager->FindOrBuildMaterial("G4_Pb");
// Liquid argon material
G4double a; // mass of a mole;
G4double z; // z=mean number of protons;
G4double density;
new G4Material("liquidArgon", z=18., a= 39.95*g/mole, density= 1.390*g/cm3);
// The argon by NIST Manager is a gas with a different density
// Vacuum
new G4Material("Galactic", z=1., a=1.01*g/mole,density= universe_mean_density,
kStateGas, 2.73*kelvin, 3.e-18*pascal);
nistManager->FindOrBuildMaterial("G4_AIR");
auto cwLayers = cw.getLayers();
for(auto layer : cwLayers){
nistManager->FindOrBuildMaterial(layer.material);
}
// Print materials
G4cout << *(G4Material::GetMaterialTable()) << G4endl;
@@ -97,28 +128,21 @@ void DetectorConstruction::DefineMaterials()
G4VPhysicalVolume* DetectorConstruction::DefineVolumes()
{
// Geometry parameters
G4int nofLayers = 10;
G4double absoThickness = 10.*mm;
G4double gapThickness = 5.*mm;
G4double calorSizeXY = 10.*cm;
auto & cwLayers = cw.getLayers();
G4int nofLayers = cwLayers.size();
G4double caloLength = 0;
for(auto layer : cwLayers){
caloLength += layer.thickness * cm;
}
G4double calorSizeXY = cw.getXYWidth() * cm;
auto layerThickness = absoThickness + gapThickness;
auto calorThickness = nofLayers * layerThickness;
auto worldSizeXY = 1.2 * calorSizeXY;
auto worldSizeZ = 1.2 * calorThickness;
auto worldSizeZ = 1.2 * caloLength;
// Get materials
auto defaultMaterial = G4Material::GetMaterial("Galactic");
auto absorberMaterial = G4Material::GetMaterial("G4_Pb");
auto gapMaterial = G4Material::GetMaterial("liquidArgon");
if ( ! defaultMaterial || ! absorberMaterial || ! gapMaterial ) {
G4ExceptionDescription msg;
msg << "Cannot retrieve materials already defined.";
G4Exception("DetectorConstruction::DefineVolumes()",
"MyCode0001", FatalException, msg);
}
auto defaultMaterial = G4Material::GetMaterial("G4_AIR");
//
// World
//
@@ -146,7 +170,7 @@ G4VPhysicalVolume* DetectorConstruction::DefineVolumes()
//
auto calorimeterS
= new G4Box("Calorimeter", // its name
calorSizeXY/2, calorSizeXY/2, calorThickness/2); // its size
calorSizeXY/2, calorSizeXY/2, caloLength/2); // its size
auto calorLV
= new G4LogicalVolume(
@@ -155,7 +179,7 @@ G4VPhysicalVolume* DetectorConstruction::DefineVolumes()
"Calorimeter"); // its name
new G4PVPlacement(nullptr, // no rotation
G4ThreeVector(), // at (0,0,0)
G4ThreeVector(0,0,0), // at (0,0,0)
calorLV, // its logical volume
"Calorimeter", // its name
worldLV, // its mother volume
@@ -164,82 +188,52 @@ G4VPhysicalVolume* DetectorConstruction::DefineVolumes()
fCheckOverlaps); // checking overlaps
//
// Layer
// construct layers here; this is where the layers are added to the calorimeter
// they will be flagged active or inactive based on the isActive flag later in
// the ActionInitialization by passing the ConstructioWrapper to the EventAction class.
//
auto layerS
= new G4Box("Layer", // its name
calorSizeXY/2, calorSizeXY/2, layerThickness/2); // its size
auto layerLV
= new G4LogicalVolume(
layerS, // its solid
defaultMaterial, // its material
"Layer"); // its name
G4double position = -caloLength/2;
int layerNumber = 0;
for(auto& layer : cwLayers){
layer.name = "Layer_"+std::to_string(layerNumber);
layerNumber++;
new G4PVReplica(
"Layer", // its name
layerLV, // its logical volume
calorLV, // its mother
kZAxis, // axis of replication
nofLayers, // number of replica
layerThickness); // witdth of replica
position += layer.thickness / 2 *cm;
auto layerS
= new G4Box(layer.name, // its name
calorSizeXY/2, calorSizeXY/2, layer.thickness/2 *cm); // its size
//
// Absorber
//
auto absorberS
= new G4Box("Abso", // its name
calorSizeXY/2, calorSizeXY/2, absoThickness/2); // its size
auto layerLV
= new G4LogicalVolume(
layerS, // its solid
defaultMaterial, //G4Material::GetMaterial(layer.material), // its material
layer.name); // its name
auto absorberLV
= new G4LogicalVolume(
absorberS, // its solid
absorberMaterial, // its material
"Abso"); // its name
fAbsorberPV = new G4PVPlacement(nullptr, // no rotation
G4ThreeVector(0., 0., -gapThickness / 2), // its position
absorberLV, // its logical volume
"Abso", // its name
layerLV, // its mother volume
false, // no boolean operation
0, // copy number
fCheckOverlaps); // checking overlaps
//
// Gap
//
auto gapS
= new G4Box("Gap", // its name
calorSizeXY/2, calorSizeXY/2, gapThickness/2); // its size
auto gapLV
= new G4LogicalVolume(
gapS, // its solid
gapMaterial, // its material
"Gap"); // its name
fGapPV = new G4PVPlacement(nullptr, // no rotation
G4ThreeVector(0., 0., absoThickness / 2), // its position
gapLV, // its logical volume
"Gap", // its name
layerLV, // its mother volume
false, // no boolean operation
0, // copy number
fCheckOverlaps); // checking overlaps
//
// print parameters
//
G4cout
<< G4endl
<< "------------------------------------------------------------" << G4endl
<< "---> The calorimeter is " << nofLayers << " layers of: [ "
<< absoThickness/mm << "mm of " << absorberMaterial->GetName()
<< " + "
<< gapThickness/mm << "mm of " << gapMaterial->GetName() << " ] " << G4endl
<< "------------------------------------------------------------" << G4endl;
auto sensorLV = new G4LogicalVolume(
new G4Box("sensor", layer.sens_xwidth/2*cm, layer.sens_ywidth/2*cm, layer.thickness/2*cm),
G4Material::GetMaterial(layer.material),
"sensor");
//needs RepeatPlacement for xy granularity
//use G4PVParameterised to create a grid of sensitive detectors
auto ppv = new G4PVParameterised(layer.name,
sensorLV,
layerLV, kUndefined,
layer.nx*layer.ny, new LayerParametrisation(layer,0.));
auto pv = new G4PVPlacement(nullptr, // no rotation
G4ThreeVector(0,0,position), // at (0,0,0)
layerLV, // its logical volume
layer.name, // its name
calorLV, // its mother volume
false, // no boolean operation
0, // copy number
fCheckOverlaps); // checking overlaps
layer.assignPhysicalVolume(pv);
position += layer.thickness / 2 *cm; //assign the physical volume to the layer
}
//
// Visualization attributes
//
@@ -255,6 +249,8 @@ G4VPhysicalVolume* DetectorConstruction::DefineVolumes()
return worldPV;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void DetectorConstruction::ConstructSDandField()