490 lines
24 KiB
C++
490 lines
24 KiB
C++
//
|
|
// SiPMDetectorConstruction.cpp
|
|
// sipm
|
|
//
|
|
// Created by Baranyai David on 2018. 08. 22..
|
|
//
|
|
// 2020.02.07 - SiPM size fixed
|
|
// - Scintillator is now a box
|
|
|
|
#include "SiPMDetectorConstruction.hh"
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
SiPMDetectorConstruction::SiPMDetectorConstruction() : G4VUserDetectorConstruction()
|
|
{
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
SiPMDetectorConstruction::~SiPMDetectorConstruction()
|
|
{
|
|
}
|
|
|
|
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
|
|
|
G4VPhysicalVolume* SiPMDetectorConstruction::Construct()
|
|
{
|
|
// Get nist material manager
|
|
G4NistManager* nist = G4NistManager::Instance();
|
|
|
|
//Get the parameters instance
|
|
SiPMParameters& parameters = SiPMParameters::GetInstance();
|
|
|
|
// Option to switch on/off checking of volumes overlaps
|
|
G4bool checkOverlaps = true;
|
|
|
|
//---Object size calculations-----------------------------------------------------------------------------------
|
|
//Calculate everything with real lengths
|
|
double lengthMultiplier = parameters.GetLengthMultiplier();
|
|
|
|
G4ThreeVector sipm_size = parameters.GetSiPMSize();
|
|
sipm_size.setX(sipm_size.getX() * lengthMultiplier);
|
|
sipm_size.setY(sipm_size.getY() * lengthMultiplier);
|
|
sipm_size.setZ(sipm_size.getZ() * lengthMultiplier);
|
|
|
|
G4ThreeVector scintillator_size = parameters.GetScintillatorSize();
|
|
scintillator_size.setX(scintillator_size.getX() * lengthMultiplier);
|
|
scintillator_size.setY(scintillator_size.getY() * lengthMultiplier);
|
|
scintillator_size.setZ(scintillator_size.getZ() * lengthMultiplier);
|
|
|
|
//Scintillator radius | only used if the shape of the scintillator is set to tube
|
|
G4double scint_radius = parameters.GetScintillatorRadius() * lengthMultiplier;
|
|
|
|
G4double coatingThickness = parameters.CoatingThickness() * lengthMultiplier;
|
|
|
|
//Scintillator size with wolfram
|
|
G4ThreeVector coated_scintillator_size = scintillator_size; //scintillator size already calculated with the length mulitiplier
|
|
coated_scintillator_size.setX(coated_scintillator_size.getX() + (coatingThickness * 2));
|
|
coated_scintillator_size.setY(coated_scintillator_size.getY() + (coatingThickness * 2));
|
|
coated_scintillator_size.setZ(coated_scintillator_size.getZ() + (coatingThickness * 2)); //both sides
|
|
|
|
//World size
|
|
int sipm_size_multiplier = 0;
|
|
if(parameters.FirstSiPMEnabled() || parameters.SecondSiPMEnabled()) sipm_size_multiplier = 1; //if at least one sipm is enabled, then increase the world size by sipm size * 1
|
|
else if (parameters.FirstSiPMEnabled() && parameters.SecondSiPMEnabled()) sipm_size_multiplier = 2; //if both sipm is enabled, then increase the world size by sipm size * 2
|
|
|
|
G4double world_sizeZ = 0;
|
|
if (coatingThickness > sipm_size.getZ()) //if wolfram thicker than sipm, then increase the worldZ by the wolfram thickness
|
|
{
|
|
world_sizeZ = coated_scintillator_size.getZ();
|
|
}
|
|
else
|
|
{
|
|
world_sizeZ = sipm_size_multiplier * sipm_size.getZ() + scintillator_size.getZ();
|
|
}
|
|
|
|
G4double world_sizeX = parameters.GetXDivison() * coated_scintillator_size.getX();
|
|
G4double world_sizeY = parameters.GetYDivison() * coated_scintillator_size.getY();
|
|
|
|
//Container sizes
|
|
G4double container_sizeX = coated_scintillator_size.getX();
|
|
G4double container_sizeY = coated_scintillator_size.getY();
|
|
G4double container_sizeZ = world_sizeZ;
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
//---Object position calculations-----------------------------------------------------------------------------------
|
|
G4ThreeVector pos_sipm0 = G4ThreeVector();
|
|
G4ThreeVector pos_sipm1 = G4ThreeVector();
|
|
G4ThreeVector posScint = G4ThreeVector();
|
|
G4ThreeVector posScintCoating = G4ThreeVector();
|
|
double z_pos_helper = 0;
|
|
|
|
//World position
|
|
G4ThreeVector posWorld = G4ThreeVector(); //at (0, 0, 0)
|
|
|
|
//SiPM0 position
|
|
if (parameters.FirstSiPMEnabled())
|
|
{
|
|
if (coatingThickness > sipm_size.getZ())
|
|
{
|
|
z_pos_helper = coatingThickness - (sipm_size.getZ() / 2);
|
|
}
|
|
else
|
|
{
|
|
z_pos_helper = sipm_size.getZ() / 2;
|
|
}
|
|
z_pos_helper = z_pos_helper - (container_sizeZ / 2);
|
|
pos_sipm0 = G4ThreeVector(0, 0, z_pos_helper); //center on X and Y
|
|
}
|
|
|
|
//SiPM1 position
|
|
if (parameters.SecondSiPMEnabled())
|
|
{
|
|
if (coatingThickness > sipm_size.getZ())
|
|
{
|
|
z_pos_helper = coatingThickness + scintillator_size.getZ() + (sipm_size.getZ() / 2);
|
|
}
|
|
else
|
|
{
|
|
z_pos_helper = sipm_size.getZ() + scintillator_size.getZ() + sipm_size.getZ() / 2;
|
|
}
|
|
z_pos_helper = z_pos_helper - (container_sizeZ / 2);
|
|
pos_sipm1 = G4ThreeVector(0, 0, z_pos_helper); //center on X and Y
|
|
}
|
|
|
|
//Coating position
|
|
if (parameters.FirstSiPMEnabled())
|
|
{
|
|
if (coatingThickness > sipm_size.getZ())
|
|
{
|
|
z_pos_helper = coated_scintillator_size.getZ() / 2;
|
|
}
|
|
else
|
|
{
|
|
z_pos_helper = sipm_size.getZ() - coatingThickness + (coated_scintillator_size.getZ() / 2);
|
|
}
|
|
z_pos_helper = z_pos_helper - (container_sizeZ / 2);
|
|
posScintCoating = G4ThreeVector(0, 0, z_pos_helper); //center on X and Y
|
|
}
|
|
else
|
|
{
|
|
z_pos_helper = coated_scintillator_size.getZ() / 2;
|
|
z_pos_helper = z_pos_helper - (container_sizeZ / 2);
|
|
posScintCoating = G4ThreeVector(0, 0, z_pos_helper); //center on X and Y
|
|
}
|
|
|
|
//Scintillator position
|
|
if (parameters.FirstSiPMEnabled())
|
|
{
|
|
if (coatingThickness > sipm_size.getZ())
|
|
{
|
|
z_pos_helper = coatingThickness + (scintillator_size.getZ() / 2);
|
|
}
|
|
else
|
|
{
|
|
z_pos_helper = sipm_size.getZ() + (scintillator_size.getZ() / 2);
|
|
}
|
|
z_pos_helper = z_pos_helper - (container_sizeZ / 2);
|
|
posScint = G4ThreeVector(0, 0, z_pos_helper); //center on X and Y
|
|
}
|
|
else
|
|
{
|
|
z_pos_helper = coatingThickness + (scintillator_size.getZ() / 2);
|
|
z_pos_helper = z_pos_helper - (container_sizeZ / 2);
|
|
<<<<<<< HEAD
|
|
//posScint = G4ThreeVector(0, 0, z_pos_helper); //center on X and Y
|
|
=======
|
|
posScint = G4ThreeVector(0, 0, z_pos_helper); //center on X and Y
|
|
>>>>>>> 247f4aad085b756a9fdbb30ec68ccec1ad1b97b7
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
//---Material definitions-------------------------------------------------------------------------------------------
|
|
G4double a, z, density;
|
|
G4int nelements;
|
|
|
|
// Air
|
|
G4Element* N = new G4Element("Nitrogen", "N", z = 7, a = 14.01 * g / mole);
|
|
G4Element* O = new G4Element("Oxygen", "O", z = 8, a = 16.00 * g / mole);
|
|
G4Material* air = new G4Material("Air", density = 1.29 * mg / cm3, nelements = 2);
|
|
air->AddElement(N, 70. * perCent);
|
|
air->AddElement(O, 30. * perCent);
|
|
|
|
//Water
|
|
G4Element* H = new G4Element("Hydrogen", "H", z = 1, a = 1.01 * g / mole);
|
|
G4Material* water = new G4Material("Water", density = 1.0 * g / cm3, nelements = 2);
|
|
water->AddElement(H, 2);
|
|
water->AddElement(O, 1);
|
|
|
|
G4Material* wolfram = nist->FindOrBuildMaterial("G4_W");
|
|
|
|
//Object materials
|
|
G4Material* world_mat = air; //nist->FindOrBuildMaterial("G4_AIR");
|
|
G4Material* scint_mat = water; //nist->FindOrBuildMaterial("G4_Si");
|
|
G4Material* scint_coating = wolfram; //nist->FindOrBuildMaterial("G4_W");
|
|
G4Material* sipm0_mat = air; //nist->FindOrBuildMaterial("G4_Si");
|
|
G4Material* sipm1_mat = air; //nist->FindOrBuildMaterial("G4_Si");
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
//---World definitions----------------------------------------------------------------------------------------------
|
|
G4Box* solidWorld = new G4Box( "World", //its name
|
|
<<<<<<< HEAD
|
|
world_sizeX,
|
|
world_sizeY,
|
|
world_sizeZ); //its size
|
|
//Prevent overlapping so the world size is doubled
|
|
=======
|
|
0.5 * world_sizeX,
|
|
0.5 * world_sizeY,
|
|
0.5 * world_sizeZ); //its size
|
|
>>>>>>> 247f4aad085b756a9fdbb30ec68ccec1ad1b97b7
|
|
|
|
G4LogicalVolume* logicWorld = new G4LogicalVolume( solidWorld, //its solid
|
|
world_mat, //its material
|
|
"World"); //its name
|
|
|
|
G4VPhysicalVolume* physWorld = new G4PVPlacement( 0, //no rotation
|
|
posWorld, //at (0,0,0)
|
|
logicWorld, //its logical volume
|
|
"World", //its name
|
|
0, //its mother volume
|
|
false, //no boolean operation
|
|
0, //copy lxenumber
|
|
checkOverlaps); //overlaps checking
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
//---Container definitions------------------------------------------------------------------------------------------
|
|
//Place a container which contains everything (sipms, scintillator, coating) for G4PVPlacement
|
|
G4Box *solidContainer = new G4Box( "Container", //name
|
|
container_sizeX * 0.5,
|
|
container_sizeY * 0.5,
|
|
container_sizeZ * 0.5); //size
|
|
|
|
G4LogicalVolume *logicContainer = new G4LogicalVolume( solidContainer, //its solid
|
|
world_mat, //its material
|
|
"Container"); //its name
|
|
|
|
G4Colour containerColour( 1.0, 1.0, 0.0);
|
|
G4VisAttributes* containerVisAtt = new G4VisAttributes( containerColour );
|
|
logicContainer -> SetVisAttributes(containerVisAtt);
|
|
logicContainer -> SetVisAttributes(G4VisAttributes::GetInvisible());
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
//---Scintillator coating definitions-------------------------------------------------------------------------------
|
|
G4Box* solidScintCoating = new G4Box( "ScintillatorCoating", //its name
|
|
0.5 * coated_scintillator_size.getX(),
|
|
0.5 * coated_scintillator_size.getY(),
|
|
0.5 * coated_scintillator_size.getZ()); //its size
|
|
|
|
|
|
//---Scintillator definitions---------------------------------------------------------------------------------------
|
|
|
|
G4Box* solidScint = new G4Box( "Scintillator", //its name
|
|
0.5 * scintillator_size.getX(),
|
|
0.5 * scintillator_size.getY(),
|
|
0.5 * scintillator_size.getZ()); //its size
|
|
|
|
G4LogicalVolume* logicScint = new G4LogicalVolume( solidScint, //its solid
|
|
<<<<<<< HEAD
|
|
scint_mat, //its material
|
|
=======
|
|
scint_mat, //its material
|
|
>>>>>>> 247f4aad085b756a9fdbb30ec68ccec1ad1b97b7
|
|
"Scintillator"); //its name
|
|
|
|
G4VSolid* solidCoating = new G4SubtractionSolid("ScintillatorCoating",
|
|
solidScintCoating,
|
|
<<<<<<< HEAD
|
|
solidScint/*,
|
|
0,
|
|
G4ThreeVector(0, 0, 0)*/);
|
|
=======
|
|
solidScint,
|
|
0,
|
|
G4ThreeVector(0, 0, 0));
|
|
>>>>>>> 247f4aad085b756a9fdbb30ec68ccec1ad1b97b7
|
|
|
|
G4LogicalVolume* logicScintCoating = new G4LogicalVolume( solidCoating, //its solid
|
|
scint_coating, //its material
|
|
"ScintillatorCoating"); //its name
|
|
|
|
G4VPhysicalVolume* physScint = new G4PVPlacement( 0, //no rotation
|
|
posScint, //at position
|
|
logicScint, //its logical volume
|
|
"Scintillator", //its name
|
|
<<<<<<< HEAD
|
|
logicContainer, //its mother volume
|
|
=======
|
|
logicContainer, //its mother volume
|
|
>>>>>>> 247f4aad085b756a9fdbb30ec68ccec1ad1b97b7
|
|
false, //no boolean operation
|
|
0, //copy lxenumber
|
|
checkOverlaps); //overlaps checking
|
|
|
|
G4VPhysicalVolume* physScintCoating = new G4PVPlacement(0, //no rotation
|
|
posScintCoating, //at position
|
|
logicScintCoating, //its logical volume
|
|
"ScintillatorCoating", //its name
|
|
logicContainer, //its mother volume
|
|
false, //no boolean operation
|
|
0, //copy lxenumber
|
|
checkOverlaps); //overlaps checking
|
|
|
|
|
|
G4Colour scintColour(1.0, 0, 0.0);
|
|
G4VisAttributes* scintVisAtt = new G4VisAttributes(scintColour);
|
|
logicScint->SetVisAttributes(scintVisAtt);
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
//---SiPM0 definitions----------------------------------------------------------------------------------------------
|
|
G4Colour sipmColour(0.0, 1.0, 0.0);
|
|
G4Box* solidSipm0;
|
|
G4LogicalVolume* logicSipm0;
|
|
G4VPhysicalVolume* physSipm0;
|
|
G4VisAttributes* sipmVisAtt;
|
|
|
|
if (parameters.FirstSiPMEnabled())
|
|
{
|
|
solidSipm0 = new G4Box( "Sipm0", //its name
|
|
0.5 * sipm_size.getX(),
|
|
0.5 * sipm_size.getY(),
|
|
0.5 * sipm_size.getZ()); //its size
|
|
|
|
logicSipm0 = new G4LogicalVolume( solidSipm0, //its solid
|
|
sipm0_mat, //its material
|
|
"Sipm0"); //its name
|
|
|
|
physSipm0 = new G4PVPlacement( 0, //no rotation
|
|
pos_sipm0, //at position
|
|
logicSipm0, //its logical volume
|
|
"Sipm0", //its name
|
|
logicContainer, //its mother volume
|
|
false, //no boolean operation
|
|
0, //copy lxenumber
|
|
checkOverlaps); //overlaps checking
|
|
sipmVisAtt = new G4VisAttributes(sipmColour);
|
|
logicSipm0->SetVisAttributes(sipmVisAtt);
|
|
}
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
//---SiPM1 definitions----------------------------------------------------------------------------------------------
|
|
// sipm1 shape -> same as sipm0
|
|
G4Box* solidSipm1;
|
|
G4LogicalVolume* logicSipm1;
|
|
G4VPhysicalVolume* physSipm1;
|
|
|
|
if (parameters.SecondSiPMEnabled())
|
|
{
|
|
solidSipm1 = new G4Box( "Sipm1", //its name
|
|
0.5 * sipm_size.getX(),
|
|
0.5 * sipm_size.getY(),
|
|
0.5 * sipm_size.getZ()); //its size
|
|
|
|
logicSipm1 = new G4LogicalVolume( solidSipm1, //its solid
|
|
sipm1_mat, //its material
|
|
"Sipm1"); //its name
|
|
|
|
physSipm1 = new G4PVPlacement( 0, //no rotation
|
|
pos_sipm1, //at position
|
|
logicSipm1, //its logical volume
|
|
"Sipm1", //its name
|
|
logicContainer, //its mother volume
|
|
false, //no boolean operation
|
|
0, //copy lxenumber
|
|
checkOverlaps); //overlaps checking
|
|
|
|
logicSipm1->SetVisAttributes(sipmVisAtt);
|
|
}
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
//---General values-------------------------------------------------------------------------------------------------
|
|
const G4int n = 2;
|
|
G4double pp[n] = {2.0 * eV, 3.0 * eV}; //distribution of optical photons produced in eV
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
//---General Material Settings--------------------------------------------------------------------------------------
|
|
//material of scintillator
|
|
G4double rind_scintillator[n] = {1.59, 1.57}; //refraction index
|
|
G4double absl[n] = {35.*m, 35.*m}; //absorption length
|
|
G4double slow[n] = {1, 1};
|
|
G4double fast[n] = {1, 1};
|
|
|
|
G4MaterialPropertiesTable *scint_material_mpt = new G4MaterialPropertiesTable();
|
|
|
|
scint_material_mpt -> AddProperty("RINDEX", pp, rind_scintillator, n);
|
|
scint_material_mpt -> AddProperty("ABSLENGTH", pp, absl, n);
|
|
scint_material_mpt -> AddProperty("SLOWCOMPONENT", pp, slow, n);
|
|
scint_material_mpt -> AddProperty("FASTCOMPONENT", pp, fast, n);
|
|
<<<<<<< HEAD
|
|
scint_material_mpt -> AddConstProperty("SCINTILLATIONYIELD", 1000./MeV); //50 volt
|
|
=======
|
|
scint_material_mpt -> AddConstProperty("SCINTILLATIONYIELD", 50000./MeV); //50 volt
|
|
>>>>>>> 247f4aad085b756a9fdbb30ec68ccec1ad1b97b7
|
|
scint_material_mpt -> AddConstProperty("RESOLUTIONSCALE", 1.0);
|
|
scint_material_mpt -> AddConstProperty("FASTTIMECONSTANT", 0.01*ns);
|
|
scint_material_mpt -> AddConstProperty("SLOWTIMECONSTANT", 1.*ns);
|
|
scint_material_mpt -> AddConstProperty("YIELDRATIO", 0.1);
|
|
|
|
scint_mat -> SetMaterialPropertiesTable(scint_material_mpt);
|
|
|
|
//Surface of scintillator to wolfram
|
|
G4OpticalSurface *OpScintillatorSurface = new G4OpticalSurface("Scintillator Surface to Wolfram",glisur, polished, dielectric_metal);
|
|
|
|
G4LogicalBorderSurface *ScintillatorSurface = new G4LogicalBorderSurface("Scintillator Surface", physScint, physScintCoating, OpScintillatorSurface);
|
|
|
|
<<<<<<< HEAD
|
|
G4double reflectivityCoating[n] = {0.99, 0.99};
|
|
=======
|
|
G4double reflectivityCoating[n] = {0.9, 0.9};
|
|
>>>>>>> 247f4aad085b756a9fdbb30ec68ccec1ad1b97b7
|
|
G4double efficiencyCoating[n] = {0, 0};
|
|
|
|
G4MaterialPropertiesTable *ScintillatorToWolframMaterialPropertyTable = new G4MaterialPropertiesTable();
|
|
ScintillatorToWolframMaterialPropertyTable -> AddProperty("REFLECTIVITY", pp, reflectivityCoating, n);
|
|
ScintillatorToWolframMaterialPropertyTable -> AddProperty("EFFICIENCY", pp, efficiencyCoating, n);
|
|
|
|
OpScintillatorSurface -> SetMaterialPropertiesTable(ScintillatorToWolframMaterialPropertyTable);
|
|
|
|
|
|
//Surface from scintillator to sipm0 and sipm1
|
|
G4OpticalSurface *SurfacefromScintillatorToSipm = new G4OpticalSurface("SurfacefromScintillatorToSipm", glisur, polished, dielectric_metal);
|
|
|
|
G4LogicalBorderSurface* SurfacefromScintillatorToSipm0_logical;
|
|
G4LogicalBorderSurface* SurfacefromScintillatorToSipm1_logical;
|
|
|
|
if (parameters.FirstSiPMEnabled())
|
|
{
|
|
SurfacefromScintillatorToSipm0_logical = new G4LogicalBorderSurface("SurfacefromScintillatorToSipm0", physScint, physSipm0, SurfacefromScintillatorToSipm);
|
|
}
|
|
|
|
if (parameters.SecondSiPMEnabled())
|
|
{
|
|
SurfacefromScintillatorToSipm1_logical = new G4LogicalBorderSurface("SurfacefromScintillatorToSipm1", physScint, physSipm1, SurfacefromScintillatorToSipm);
|
|
}
|
|
|
|
G4double reflectivity[n] = {1, 1}; //ha nem 1,1 akkor nem éri el a sipm-et az aki eléri a scint végét.
|
|
|
|
G4MaterialPropertiesTable *ScintillatorMaterialPropertyTable = new G4MaterialPropertiesTable();
|
|
ScintillatorMaterialPropertyTable -> AddProperty("REFLECTIVITY", pp, reflectivity, n);
|
|
|
|
SurfacefromScintillatorToSipm -> SetMaterialPropertiesTable(ScintillatorMaterialPropertyTable);
|
|
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
|
|
//---Container placement--------------------------------------------------------------------------------------------
|
|
//Using G4PVPlacement instead of replica or others
|
|
|
|
int x = parameters.GetXDivison();
|
|
int y = parameters.GetYDivison();
|
|
int copyNumber = 0;
|
|
G4VPhysicalVolume *physContainer[x][y];
|
|
char s1[30];
|
|
|
|
for(int i = 0; i < x; i++)
|
|
{
|
|
for(int j = 0; j < y; j++)
|
|
{
|
|
snprintf(s1, 30, "Container_x%d_y%d", i, j);
|
|
logicContainer -> SetName(s1);
|
|
<<<<<<< HEAD
|
|
physContainer[i][j] = new G4PVPlacement( 0,
|
|
G4ThreeVector(i * container_sizeX + (container_sizeX / 2) - (world_sizeX / 2), j * container_sizeY + (container_sizeY / 2) - (world_sizeY / 2), container_sizeZ / 2),
|
|
logicContainer,
|
|
s1, //its name
|
|
logicWorld,
|
|
false,
|
|
copyNumber, //copy number
|
|
checkOverlaps);
|
|
copyNumber++;
|
|
=======
|
|
physContainer[x][y] = new G4PVPlacement(0,
|
|
G4ThreeVector(i * (container_sizeX / 2), j * (container_sizeY / 2), container_sizeZ / 2),
|
|
logicContainer,
|
|
s1, //its name
|
|
logicWorld,
|
|
false,
|
|
helper, //copy number
|
|
checkOverlaps);
|
|
helper++;
|
|
>>>>>>> 247f4aad085b756a9fdbb30ec68ccec1ad1b97b7
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------------------------------------------
|
|
return physWorld;
|
|
}
|