Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • a.bercuci/cbmroot_geometry
  • d.ramirez/cbmroot_geometry
  • m.shiroya/cbmroot_geometry
  • ajit.kumar/cbmroot_geometry
  • n.herrmann/cbmroot_geometry
  • a.weber/cbmroot_geometry
  • a.agarwal_AT_vecc.gov.in/cbmroot_geometry
  • l.chlad/cbmroot_geometry
  • a.toia/cbmroot_geometry
  • ma.beyer/cbmroot_geometry
  • a_meye37_AT_uni-muenster.de/cbmroot_geometry
  • praisig/cbmroot_geometry
  • aksharma/cbmroot_geometry
  • hofmanond_AT_fjfi.cvut.cz/cbmroot_geometry
  • r.karabowicz/cbmroot_geometry
  • i.deppner/cbmroot_geometry
  • s.lebedev/cbmroot_geometry
  • osingh/cbmroot_geometry
  • CbmSoft/cbmroot_geometry
  • p.-a.loizeau/cbmroot_geometry
  • f.uhlig/cbmroot_geometry
  • d.emschermann/cbmroot_geometry
  • e.clerkin/cbmroot_geometry
  • rishat.sultanov_AT_cern.ch/cbmroot_geometry
  • se.gorbunov/cbmroot_geometry
  • s.roy/cbmroot_geometry
  • p.chudoba/cbmroot_geometry
  • o.golosov/cbmroot_geometry
  • apuntke/cbmroot_geometry
  • v.singhal/cbmroot_geometry
30 results
Show changes
Commits on Source (52)
Showing
with 2621 additions and 33 deletions
# Ending a path in a `/` will specify the code owners for every file
# nested in that directory, on any level
/ @f.uhlig @p.-a.loizeau @d.emschermann
/ @f.uhlig @p.-a.loizeau @e.clerkin
# Repository technical side
/ci_scripts/ @f.uhlig @p.-a.loizeau @e.clerkin
## Detectors
# TRD
/trd/ @a.bercuci @p.kaehler
/macro/trd/ @a.bercuci @p.kaehler
# PSD
/psd/ @karpushkin_AT_inr.ru
# PSD/FSD
/psd/ @dvorar10_AT_fjfi.cvut.cz @e.clerkin @i.selyuzhenkov
/macro/psd/ @dvorar10_AT_fjfi.cvut.cz @e.clerkin @i.selyuzhenkov
/fsd/ @dvorar10_AT_fjfi.cvut.cz
/macro/fsd/ @dvorar10_AT_fjfi.cvut.cz
# MUCH
/much/ @v.singhal
/macro/much/ @v.singhal
# TOF
/tof/ @n.herrmann @i.deppner
/macro/tof/ @n.herrmann @i.deppner
# RICH
/rich/ @s.lebedev
/rich/ @s.lebedev @ma.beyer @s.neuhaus
/macro/rich/ @s.lebedev @ma.beyer @s.neuhaus
# STS
/sts/ @v.friese @a.toia
/sts/ @v.friese @a.toia @m.shiroya
/macro/sts/ @v.friese @a.toia @m.shiroya
# MVD
/mvd/ @c.muentz @m.deveaux
/macro/mvd/ @c.muentz @m.deveaux
# passive geometries
/magnet/ @e.clerkin
/passive/ @e.clerkin
/macro/passive/ @e.clerkin
/pipe/ @e.clerkin
/macro/pipe/ @e.clerkin
#setups
# setups
/setup/ @e.clerkin
# mCBM
/mcbm/ @c.sturm
FSD geometry v25e created with create_fsdgeo_firstRealistic.C
Position for maximum deflection angle, e.g. E_kin_beam = 5A GeV and 100% magnetic field strength
Number of SMALL modules per quadrant: 5 x 3
Number of MEDIUM modules per quadrant: 4 x 3
Number of LARGE modules per quadrant: 2 x 2
FSD thickness: 5 cm
FSD front plane center coordinates: (31.6478, 0, 1000) cm
FSD rotation around y axis: 0.0329867 rad
Hole in the wall has a radii of 10 cm
Parameters of module fsdmodule:
Size: 4 cm x 4 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 8 cm x 8 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 16 cm x 16 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
FSD size is 192 cm x 160 cm x 5 cm
FSD contains 372 modules in total,
small sized modules: 156
medium sized modules: 144
large sized modules: 72
FSD volume center coordinates: (31.7302, 0, 1002.5) cm
File added
FSD geometry v25h created with create_fsdgeo_firstRealistic.C
Position for Au beam at 12A GeV/c and 100% magnetic field strength
Number of SMALL modules per quadrant: 5 x 3
Number of MEDIUM modules per quadrant: 4 x 3
Number of LARGE modules per quadrant: 2 x 2
FSD thickness: 5 cm
FSD front plane center coordinates: (15.1229, 0, 1000) cm
FSD rotation around y axis: 0.0171042 rad
Hole in the wall has a radii of 10 cm
Parameters of module fsdmodule:
Size: 4 cm x 4 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 8 cm x 8 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 16 cm x 16 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
FSD size is 192 cm x 160 cm x 5 cm
FSD contains 372 modules in total,
small sized modules: 156
medium sized modules: 144
large sized modules: 72
FSD volume center coordinates: (15.1657, 0, 1002.5) cm
File added
FSD geometry v25i created with create_fsdgeo_firstRealistic.C
Position for Au beam at 11 AGeV/c (10 AGeV) and 100% magnetic field strength
Number of SMALL modules per quadrant: 5 x 3
Number of MEDIUM modules per quadrant: 4 x 3
Number of LARGE modules per quadrant: 2 x 2
FSD thickness: 5 cm
FSD front plane center coordinates: (16.3936, 0, 1000) cm
FSD rotation around y axis: 0.018326 rad
Hole in the wall has a radii of 10 cm
Parameters of module fsdmodule:
Size: 4 cm x 4 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 8 cm x 8 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
Parameters of module fsdmodule:
Size: 16 cm x 16 cm
Thickness: 5 cm
Channel Depth (ratio of thickness): 0.75
Channel Width: 0.2 cm
Channel distance from the edge of scintillator: 0.5 cm
Channel radius at corners: 1 cm
FSD size is 192 cm x 160 cm x 5 cm
FSD contains 372 modules in total,
small sized modules: 156
medium sized modules: 144
large sized modules: 72
FSD volume center coordinates: (16.4394, 0, 1002.5) cm
File added
/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
/* Copyright (C) 2023-2025 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
SPDX-License-Identifier: GPL-3.0-only
Authors: Volker Friese, Lukas Chlad [committer] */
Authors: Radim Dvorak, Volker Friese, Lukas Chlad [committer] */
/** @file create_fsdgeo_firstRealistic.C
** @author Lukas Chlad <l.chlad@gsi.de>
......@@ -8,8 +8,8 @@
** @version 1.0
**
** This macro creates a FSD geometry in ROOT format to be used as input
** for the transport simulation. The labeling of versions is ment
** to correspond with beampipe versions v21[e-h]. Letter 'z' is reserved
** for the transport simulation. The labeling of versions is ment
** to correspond with beampipe versions v24[e-h]. Letter 'z' is reserved
** for parking position.
**
** It allows to create module stacks of varying sizes.
......@@ -32,7 +32,7 @@ std::pair<Bool_t, std::pair<Double_t,Double_t> > calc_x_trans_and_y_rot(Double_t
// ====== Main function =====
// ============================================================================
void create_fsdgeo_firstRealistic(TString geoTag = "v23i")
void create_fsdgeo_firstRealistic(TString geoTag = "v25i")
{
// ----- Steering variables ---------------------------------------------
Double_t fsdX; // x position (cm) of FSD in cave (front plane center)
......@@ -49,22 +49,25 @@ void create_fsdgeo_firstRealistic(TString geoTag = "v23i")
fsdX = calcPosxRoty.second.first;
fsdRotY = calcPosxRoty.second.second;
if (geoTag == "v23e") {
if (geoTag == "v25e") {
comment = "Position for maximum deflection angle, e.g. E_kin_beam = 5A GeV and 100% magnetic field strength";
}
else if (geoTag == "v23f") {
else if (geoTag == "v25f") {
comment = "Position for NO deflection angle";
}
else if (geoTag == "v23g") {
comment = "Position for Au beam at 3.3A GeV/c and 50% magnetic field strength";
else if (geoTag == "v25g") {
comment = "to be add later";
}
else if (geoTag == "v23h") {
else if (geoTag == "v25h") {
comment = "Position for Au beam at 12A GeV/c and 100% magnetic field strength";
}
else if (geoTag == "v23i") {
else if (geoTag == "v25i") {
comment = "Position for Au beam at 11 AGeV/c (10 AGeV) and 100% magnetic field strength";
}
else if (geoTag == "v23z") {
else if (geoTag == "v25i") {
comment = "Position for Au beam at 11 AGeV/c (10 AGeV) and 100% magnetic field strength";
}
else if (geoTag == "v25z") {
fsdX = -90;
fsdY = -70;
fsdZ = 1756;
......@@ -212,7 +215,7 @@ void create_fsdgeo_firstRealistic(TString geoTag = "v23i")
const Double_t plasticSizeZ = 0.5*wallThickness; // half-thickness
const TString plasticUnitName = "unit_Plastic";
TGeoVolume* plasticUnit = new TGeoVolumeAssembly(plasticUnitName);
std::cout << "Module array in one quadrant is "
<< std::ceil(holeRadius/smallCellSize) << "x" << std::ceil(holeRadius/smallCellSize) << " small module size is taken by hole in FSD,"
<< nSmallCells_X << "x" << nSmallCells_Y << " small modules, "
......@@ -500,7 +503,7 @@ TGeoVolume* ConstructGeneralModule(const char* name, Double_t sizeXY, Double_t c
shiftFiberDownRight->RegisterYourself();
TGeoTranslation *shiftFiberDownLeft = new TGeoTranslation(Form("shiftFiberDownLeft%s",suffix.Data()) ,-0.5*sizeXY+edgeMargin+bendRadius,-0.5*sizeXY+edgeMargin+bendRadius,0.5*cellThickness*(1.-fiberDepth));
shiftFiberDownLeft->RegisterYourself();
//fiber parts
TGeoBBox *fiberBoxHorizontal = new TGeoBBox(Form("fiberBoxHorizontal%s",suffix.Data()), 0.5*sizeXY-edgeMargin-bendRadius, 0.5*fiberWidth, 0.5*fiberDepth*cellThickness);
......@@ -563,7 +566,7 @@ TGeoVolume* ConstructGeneralModule(const char* name, Double_t sizeXY, Double_t c
std::pair<Bool_t, std::pair<Double_t,Double_t> > calc_x_trans_and_y_rot(Double_t zpos, TString geoTag)
{
const TString strPsdTube = "psd_tube"; // node of beampipe containing this string is what we need
TString strPipeFile = "${VMCWORKDIR}/geometry/pipe/pipe_v21" + geoTag(3,geoTag.Length()) + ".geo.root";
TString strPipeFile = "${VMCWORKDIR}/geometry/pipe/pipe_v24" + geoTag(3,geoTag.Length()) + ".geo.root";
if(gSystem->ExpandPathName(strPipeFile)){
std::cout << __func__ << ": Error while expanding path to beampipe file!!" << std::endl;
return std::make_pair(kFALSE,std::make_pair(0.,0.));
......@@ -632,7 +635,7 @@ std::pair<Bool_t, std::pair<Double_t,Double_t> > calc_x_trans_and_y_rot(Double_t
// | .
// | / . /<-.
// | / . / `. angle of rotation around y axis
// | / . / ;
// | / . / ;
// ^ value of x_lt / x /-------- "this is 0 but in principle can be different"
// | / . / tan(phi_y) = (x_FSD - x_lt "-x_glob") / (z_FSD - z_lt - z_glob)
// | / . / from here we get:
......
This diff is collapsed.
/* Copyright (C) 2020-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Florian Uhlig, David Emschermann [committer] */
// 2024-12-12 - v24a - DE - first version for PAnda STrAws in mCBM, 4 modules
// 2024-11-25 - v01a - RK - first version
// details concering the copynr of layers, modules and straw assemblies
// 1 0 4 0 1 0 6 4 sample copy number of a straw
// | | / | / \---- number of straw in module (1-128, 3 decimal digits, 7 bits -127)
// | | \-------- number of module in layer (1-36, 2 decimal digits, 6 bits - 63)
// | \------------ number of layer in MuST (1-12, 2 decimal digits, 4 bits - 15)
// \-------------- leading 1 to allow for 0s in layer number
// clang-format off
#include <iostream>
#include "TGeoBBox.h"
#include "TGeoManager.h"
#include "TGeoVolume.h"
void dump_info_file();
using namespace std;
// Name of output file with geometry
const TString tagVersion = "v24a";
// const TString geoVersion = "must_" + tagVersion;
const TString geoVersion = "must_" + tagVersion + "_mcbm";
const TString FileNameSim = geoVersion + ".geo.root?reproducible"; // Reproducible flag removes changing timestamps etc...
const TString FileNameGeo = geoVersion + "_geo.root";
const TString FileNameInfo = geoVersion + ".geo.info";
// Double_t fTranslationZ = 0.; // cm - Z Translation of the whole Geometry
Double_t fTranslation[3] = { 50., 0., 340. + 1.5 }; // cm - Translation of the whole Geometry
// DE-1layer const Int_t nLayer = 1; // number of layers
// DE-1layer Double_t StereoAngle[nLayer] = { 0. }; // X,U,V,X stereo angle of straws
// DE-1layer const Int_t mustlayout[nLayer][nModule] = { { 1 } };
// mCBM 2025
const Int_t nLayer = 4; // number of layers
const Int_t nModule = 1; // number of modules
const Int_t nModuleType = 4; // number of modules types
const Double_t zLayerPitch = 4.0; // distance of module front to module front in z
Double_t StereoAngle[nLayer] = { 0., -5., 5., 0.}; // X,U,V,X stereo angle of straws - mCBM 2025
// Double_t StereoAngle[nLayer] = { 0., 0., 0., 0.}; // X,U,V,X stereo angle of straws
// Double_t StereoAngle[nLayer] = { 0., 5., -5., 0.}; // X,U,V,X stereo angle of straws
const Int_t mustlayout[nLayer][nModule] = { { 1 }, { 1 }, { 1 }, { 1 } };
// mCBM ------------
// DE4 // CBM FAIR
// DE4 const Int_t nLayer = 12; // number of layers
// DE4 const Int_t nModule = 36; // number of modules
// DE4
// DE4 const Int_t mustlayout[nLayer][nModule] =
// DE4 // station 1
// DE4 { { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 // station 2
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 // station 3
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE4 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 } };
// DE5 // conical beampipe support in S2 and S3 modules
// DE5 const Int_t mustlayout[nLayer][nModule] =
// DE5 // station 1
// DE5 { { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 // station 2
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 // station 3
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1 },
// DE5 { 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 7, 8, 2, 1, 1, 1, 1, 1, 1, 1 } };
// some global variables
TGeoManager* gGeoMan = NULL; // Pointer to TGeoManager instance
TGeoVolume* gModules[nModuleType]; // Global storage for module types
// Forward declarations
void create_materials_from_media_file();
TGeoVolume* create_must_module_type(Int_t moduleType, Int_t modulecopynr);
void Create_MUST_Geometry_v24a()
{
// Load FairRunSim to ensure the correct unit system
FairRunSim* sim = new FairRunSim();
// Load needed material definition from media.geo file
create_materials_from_media_file();
// Get the GeoManager for later usage
gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
gGeoMan->SetVisLevel(10);
// Create the top volume
// TGeoBBox* topbox = new TGeoBBox("", 1000., 1000., 2000.);
TGeoBBox* topbox = new TGeoBBox("", 100., 1000., 2000.);
TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air"));
gGeoMan->SetTopVolume(top);
TGeoVolume* must = new TGeoVolumeAssembly(geoVersion);
top->AddNode(must, 1);
for (Int_t iLayer=1; iLayer <= nLayer; iLayer++)
{
// add layer keeping volume
TString layername = Form("layer%02d", iLayer);
TGeoVolume* layer = new TGeoVolumeAssembly(layername);
Int_t layercopynr = 100 + iLayer;
// cout << "layercopynr " << layercopynr << endl;
must->AddNode(layer, layercopynr);
for (Int_t iModule=1; iModule <= nModule; iModule++)
{
Int_t modulecopynr = layercopynr * 100 + iModule;
// cout << "modulecopynr " << modulecopynr << endl;
gModules[iModule] = create_must_module_type(iModule, modulecopynr);
TGeoRotation* module_rotation = new TGeoRotation();
module_rotation->RotateZ(StereoAngle[iLayer-1]);
TGeoCombiTrans* module_placement = new TGeoCombiTrans(0., 0., (iLayer-1) * zLayerPitch, module_rotation);
layer->AddNode(gModules[iModule], modulecopynr, module_placement);
}
}
gGeoMan->CloseGeometry();
gGeoMan->CheckOverlaps(0.001);
gGeoMan->PrintOverlaps();
gGeoMan->Test();
must->Export(FileNameSim); // an alternative way of writing the must volume
TFile* outfile = new TFile(FileNameSim, "UPDATE");
TGeoTranslation* must_placement =
new TGeoTranslation("must_trans", fTranslation[0], fTranslation[1], fTranslation[2]);
must_placement->Write();
outfile->Close();
outfile = new TFile(FileNameGeo, "RECREATE");
gGeoMan->Write(); // use this is you want GeoManager format in the output
outfile->Close();
dump_info_file();
top->Draw("ogl");
}
void create_materials_from_media_file()
{
// Use the FairRoot geometry interface to load the media which are already defined
FairGeoLoader* geoLoad = new FairGeoLoader("TGeo", "FairGeoLoader");
FairGeoInterface* geoFace = geoLoad->getGeoInterface();
TString geoPath = gSystem->Getenv("VMCWORKDIR");
TString medFile = geoPath + "/geometry/media.geo";
geoFace->setMediaFile(medFile);
geoFace->readMedia();
// Read the required media and create them in the GeoManager
FairGeoMedia* geoMedia = geoFace->getMedia();
FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
//Media
FairGeoMedium *mcarbon = geoMedia->getMedium("TRDcarbon");
if (mcarbon == NULL) Fatal("Main", "FairMedium TRDcarbon not found");
geoBuild->createMedium(mcarbon);
FairGeoMedium *mkapton = geoMedia->getMedium("MUCHkapton");
if (mkapton == NULL) Fatal("Main", "FairMedium MUCHkapton not found");
geoBuild->createMedium(mkapton);
FairGeoMedium *mMUCHargon_co2 = geoMedia->getMedium("MUCHGEMmixture");
if (mMUCHargon_co2 == NULL) Fatal("Main", "FairMedium mMUCHargon_co2 not found");
geoBuild->createMedium(mMUCHargon_co2);
//---------------------------------------------------------------------------------
// FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium");
// if (mAluminium == NULL) Fatal("Main", "FairMedium aluminium not found");
// geoBuild->createMedium(mAluminium);
//
// FairGeoMedium* mMylar = geoMedia->getMedium("mylar");
// if (mMylar == NULL) Fatal("Main", "FairMedium mylar not found");
// geoBuild->createMedium(mMylar);
//
// FairGeoMedium* mIron = geoMedia->getMedium("iron"); // TODO should be tungsten?
// if (mIron == NULL) Fatal("Main", "FairMedium iron not found");
// geoBuild->createMedium(mIron);
//
// FairGeoMedium* mAir = geoMedia->getMedium("air");
// if (mAir == NULL) Fatal("Main", "FairMedium air not found");
// geoBuild->createMedium(mAir);
}
TGeoVolume* create_must_module_type(Int_t moduleType, Int_t modulecopynr)
{
TString modulename = Form("module%02d", moduleType);
TGeoVolume* module = new TGeoVolumeAssembly(modulename);
//------------------------------------------------------------------
TGeoMedium* carbon = gGeoMan->GetMedium("TRDcarbon"); // Carbon
TGeoMedium* kapton = gGeoMan->GetMedium("MUCHkapton"); // Kapton
TGeoMedium* argon_co2 = gGeoMan->GetMedium("MUCHGEMmixture"); // active medium (Ar + CO2)
//------------------------------------------------------------------
// not used TGeoMedium* medAl = gGeoMan->GetMedium("aluminium");
// not used if (medAl == NULL) Fatal("Main", "Medium vacuum not found");
// not used
// not used TGeoMedium* medMylar = gGeoMan->GetMedium("mylar");
// not used if (medMylar == NULL) Fatal("Main", "Medium mylar not found");
// not used
// not used TGeoMedium* medIron = gGeoMan->GetMedium("iron");
// not used if (medIron == NULL) Fatal("Main", "Medium iron not found");
// not used
// not used TGeoMedium* medAir = gGeoMan->GetMedium("air");
// not used if (medAir == NULL) Fatal("Main", "Medium air not found");
// Straw tube dimensions
Double_t strawLength = 230.0; // cm
Double_t strawRadius = 0.245; // cm
Double_t wallThickness = 0.0065; // cm
// Module and straw layout parameters
Int_t nStrawsPerColumnLong = 64; // DE
Int_t nStrawsPerModuleS3 = 32; // DE
Double_t spacingY = 0.550; // cm // DE
Double_t spacingX = 0.525; // cm // DE
Double_t offsetX = spacingX / 2.0;
//Double_t size_module_long = std::ceil(spacingX * nStrawsPerColumnLong); // DE
Double_t xwidth_module_long = 34.0; // cm // DE
// (34 / 2. - 31.75 * 0.525 + 15.75 * 0.525) * 2 = 17.2
Double_t xwidth_module_S3 = 17.2; // cm // DE
Double_t moduleXSize = xwidth_module_S3;
Double_t moduleYSize = strawLength;
Double_t moduleZSize = 3.;
Double_t frameThick = 0.05;
Double_t moduleXPos = 0., moduleYPos = 0., moduleZPos = moduleZSize/2.;
// Carbon SideFrame
TGeoBBox* must_vert_frame = new TGeoBBox("must_vert_frame", frameThick/2., moduleYSize/2., moduleZSize/2.); // vertical
TGeoVolume* must_vert_frame_vol = new TGeoVolume("framevert", must_vert_frame, carbon);
must_vert_frame_vol->SetLineColor(kBlue);
TGeoTranslation* frameTransPosX = new TGeoTranslation(moduleXPos + (moduleXSize/2. - frameThick/2.), moduleYPos, moduleZPos);
module->AddNode(must_vert_frame_vol, 1, frameTransPosX);
TGeoTranslation* frameTransNegX = new TGeoTranslation(moduleXPos - (moduleXSize/2. - frameThick/2.), moduleYPos, moduleZPos);
module->AddNode(must_vert_frame_vol, 2, frameTransNegX);
TGeoVolumeAssembly* strawAssembly = new TGeoVolumeAssembly("strawAssembly");
TGeoRotation* strawRotat = new TGeoRotation("strawRotat", 0.0, 90.0, 0.0);
// Common straw geometry
TGeoTube* strawGas = new TGeoTube("StrawGas", 0, strawRadius - wallThickness, strawLength / 2.);
TGeoVolume* volStrawGas = new TGeoVolume("strawgasactive", strawGas, argon_co2);
volStrawGas->SetLineColor(kGreen);
volStrawGas->SetTransparency(40);
strawAssembly->AddNode(volStrawGas,1);
TGeoTube* strawWall = new TGeoTube("StrawWall", strawRadius - wallThickness, strawRadius, strawLength / 2.);
TGeoVolume* volStrawWall = new TGeoVolume("strawwallpassive", strawWall, kapton);
volStrawWall->SetLineColor(kRed);
//volStrawWall->SetTransparency(40);
strawAssembly->AddNode(volStrawWall,1);
// not used double strawRad = 0.25, straw_Length = moduleYSize;
// not used double stGasRad = 0.24, stGas_Length = straw_Length;
// not used double wireRad = 0.01, wire_Length = straw_Length;
// not used
// not used auto wireShape = new TGeoTube("wireShape", 0., wireRad, wire_Length/2.);
// not used TGeoVolume* wireVol = new TGeoVolume("MustWire", wireShape, medIron);
// not used wireVol->SetLineColor(kRed);
// not used strawAssembly->AddNode(wireVol,1);
// not used
// not used auto stGasShape = new TGeoTube("stGasShape", wireRad, stGasRad, stGas_Length/2.);
// not used TGeoVolume* stGasVol = new TGeoVolume("MustStGas", stGasShape, medAir);
// not used stGasVol->SetTransparency();
// not used stGasVol->SetLineColor(kYellow);
// not used strawAssembly->AddNode(stGasVol,1);
// not used
// not used auto strawShape = new TGeoTube("strawShape", stGasRad, strawRad, straw_Length/2.);
// not used TGeoVolume* strawVol = new TGeoVolume("MustStraw", strawShape, medMylar);
// not used strawVol->SetLineColor(kGreen);
// not used strawAssembly->AddNode(strawVol,1);
Int_t strawcopynr = 0;
Int_t nStraws = 2 * nStrawsPerModuleS3;
for ( int istraw = 0; istraw < nStraws; istraw++ )
{
Double_t xoffset = 15.75;
Double_t yoffset = -spacingY/2.;
if (istraw%2==1)
{
xoffset = 15.25;
yoffset = spacingY/2.;
}
TGeoTranslation* strawTrans = new TGeoTranslation((istraw/2 - xoffset) * spacingX, 0., yoffset + moduleZPos);
TGeoCombiTrans* strawCombi = new TGeoCombiTrans(*strawTrans, *strawRotat);
strawcopynr = modulecopynr * 1000 + istraw + 1;
// cout << "strawcopynr " << strawcopynr << endl;
module->AddNode(strawAssembly, strawcopynr, strawCombi);
// TGeoTranslation* strawTrans = new TGeoTranslation((istraw/2 - 15.75) * spacingX, 0., -spacingY/2.);
// TGeoTranslation* strawTrans = new TGeoTranslation((istraw/2 - 15.25) * spacingX, 0., spacingY/2.);
}
// for ( int istraw = 0 ; istraw < nStrawsPerModuleS3 ; istraw++ )
// {
// TGeoTranslation* strawTrans = new TGeoTranslation((istraw - 15.75) * spacingX, 0., -spacingY/2.);
// TGeoCombiTrans* strawCombi = new TGeoCombiTrans(*strawTrans, *strawRotat);
//
// strawcopynr = modulecopynr * 1000 + istraw + 1;
// // cout << "strawcopynr " << strawcopynr << endl;
// module->AddNode(strawAssembly, strawcopynr, strawCombi);
// }
//
// for ( int istraw = 0 ; istraw < nStrawsPerModuleS3 ; istraw++ ) {
// TGeoTranslation* strawTrans = new TGeoTranslation((istraw - 15.25) * spacingX, 0., spacingY/2.);
// TGeoCombiTrans* strawCombi = new TGeoCombiTrans(*strawTrans, *strawRotat);
//
// strawcopynr = modulecopynr * 1000 + istraw + 1 + 32;
// // cout << "strawcopynr " << strawcopynr << endl;
// module->AddNode(strawAssembly, strawcopynr, strawCombi);
// }
return module;
}
void dump_info_file()
{
TDatime datetime; // used to get timestamp
printf("writing summary information file: %s\n", FileNameInfo.Data());
FILE* ifile;
ifile = fopen(FileNameInfo.Data(), "w");
if (ifile == NULL) {
printf("error opening %s\n", FileNameInfo.Data());
exit(1);
}
fprintf(ifile, "#\n## %s information file\n#\n\n", geoVersion.Data());
fprintf(ifile, "# created %d\n\n", datetime.GetDate());
fprintf(ifile, "# MUST geometry consisting fo %d layers\n", nLayer);
for (Int_t iLayer=1; iLayer <= nLayer; iLayer++)
{
fprintf(ifile, "Layer %d: number of modules: %d module type %d StereoAngle %f.1 degrees\n", iLayer, nModule, nModuleType, StereoAngle[iLayer]);
}
fprintf(ifile, "Front module x-offset %f.1 cm\n", fTranslation[0]);
fprintf(ifile, "Front module y-offset %f.1 cm\n", fTranslation[1]);
fprintf(ifile, "Front module z-offset %f.1 cm\n", fTranslation[2]);
fprintf(ifile, "\n");
fclose(ifile);
}
/* Copyright (C) 2020-2024 Institut fuer Kernphysik, Goethe-Universitaet Frankfurt
SPDX-License-Identifier: GPL-3.0-only
Authors: Phillip Klaus [committer], Eoin Clerkin */
/*
* ROOT Macro to create the geometry of the Micro Vertex Detector
* of the CBM experiment at FAIR. It is used within the CbmRoot
* framework to simulate the detector response.
*
* The main output of this script is a .root file containing the
* the volumes of the detector. The media those volumes are
* filled with / made of are referenced in this script only by name
* and defined in a separate ASCII file named media.geo.
*
* For some components, their medium is a surrogate with equivalent
* material budget to simplify the design and speed-up simulation or
* because we depend on educated estimates regarding their material
* composition for the time being.
*/
/*
* Parameters defining the MVD
*/
static const int numStations = 2;
// all units are in cm
// Float_t quadrantBeamOffset[4] = {0.54, 0.54, 0.82, 1.04};
Float_t carrierClampOverlap = 0.0;
// Float_t heatsinkWidth[4] = {23.1, 31.1, 34.34, 37.7};
Float_t heatsinkHeight = 37.7;
// Heatsink actual thickness: 1.0cm
// The additional contributionof 0.7cm is a surrogate
// for FEBs incl. FR-4, copper, connectors:
Float_t heatsinkThickness = 1.0 + 0.7;
Float_t topPlateThickness = 1.0;
Float_t fpcWidth = 1.9;
Float_t fpcThickness = 0.0009;
Float_t glueThickness = 0.0008;
/* MIMOSIS dimensions
https://indico.gsi.de/contributionDisplay.py?contribId=8&sessionId=6&confId=4759
30.97 x 16.55 mm2 (of which the lower 3mm inactive) */
Float_t sensorDimensionsActive[3] = {3.097, 1.355, 0.005};
Float_t sensorDimensionsPassive[3] = {3.097, 0.300, 0.005};
// Formula for the carrier dimensions height ([1]):
// nrows * sensorDimensionsActive[1] + (nrows - 1) * sensorActiveOverlap +
// sensorDimensionsPassive[1] + fpcWidth + 0.1 eg. for nrows=2:
// 2*1.355-(2-1)*0.05+0.3+1.9+0.1
/* MIMOSIS-based tr (tracking) variant (general purpose tracking variant) */
/* Commented out for TwoStation Generation
Float_t stationPosition[4] = {4.0, 8.0, 12.0, 16.0};
int sensorRows[4] = {4, 4, 7, 7};
int sensorCols[4] = {2, 2, 4, 4};
Float_t heatsinkWidth[4] = {31.1, 31.1, 37.7, 37.7};
Float_t quadrantBeamOffset[4] = {0.54, 0.54, 1.04, 1.04};
Float_t carrierDimensions[4][3] = {{7.19, 7.57, 0.038},
{7.19, 7.57, 0.038},
{13.39, 11.485, 0.038},
{13.39, 11.485, 0.038}};
int carrierMaterials[4] = {1, 1, 1, 1}; // 0 = diamond, 1 = TPG
*/
Float_t stationPosition[2] = {4.0, 16.0};
int sensorRows[2] = {4, 7};
int sensorCols[2] = {2, 4};
Float_t heatsinkWidth[2] = {31.1, 37.7};
Float_t quadrantBeamOffset[2] = {0.54, 1.04};
Float_t carrierDimensions[2][3] = {{7.19, 7.57, 0.038},
{13.39, 11.485, 0.038}};
int carrierMaterials[2] = {1, 1}; // 0 = diamond, 1 = TPG
/* MIMOSIS-based vx (vertexing) variant (dedicated vertexing variant) */
/*
Float_t stationPosition[4] = {1.0, 6.0, 11.0, 16.0};
int sensorRows[4] = {2, 4, 7, 7};
int sensorCols[4] = {1, 2, 4, 4};
Float_t heatsinkWidth[4] = {23.1, 31.1, 37.7, 37.7};
Float_t quadrantBeamOffset[4] = {0.54, 0.54, 1.04, 1.04};
Float_t carrierDimensions[4][3] = {{4.10, 4.96, 0.015},
{7.19, 7.57, 0.038},
{13.39, 11.485, 0.038},
{13.39, 11.485, 0.038}};
int carrierMaterials[4] = {0, 1, 1, 1}; // 0 = diamond, 1 = TPG
*/
Float_t sensorActiveOverlap = 0.05;
Float_t sensorPitch = sensorDimensionsActive[1] - sensorActiveOverlap;
Float_t sensorSpacing = 0.0; // realistically: 0.01 (100um)
// if an artificially exploded view is desired, adjust this parameter:
Float_t explosion =
1.0; // set to 1. for no explosion, and 3. for a heavy explosion
/*
* Procedural code assemblying the MVD
*/
void Create_MVD() {
TGeoVolume *top;
TGeoVolume *stations[numStations];
TGeoVolume *quadrant;
TCanvas *c3D = new TCanvas("c3D", "MVD Layout", 1600, 1200);
TGeoManager *manager = new TGeoManager("Chamber Layout", "Chamber Layout");
TGeoMaterial *mat = new TGeoMaterial("vacuum", 0., 0., 0.);
TGeoMaterial *matAl = new TGeoMaterial("aluminium", 0., 0., 0.);
TGeoMaterial *matSilicon = new TGeoMaterial("silicon", 0, 0, 0);
TGeoMaterial *matGlue = new TGeoMaterial("MVD_glue", 0, 0, 0);
TGeoMaterial *matTPG = new TGeoMaterial("MVD_tpg", 0, 0, 0);
TGeoMaterial *matDiamond = new TGeoMaterial("MVD_cvd_diamond", 0, 0, 0);
TGeoMaterial *matFPC = new TGeoMaterial("MVD_fpc", 0, 0, 0);
TGeoMedium *vac = new TGeoMedium("vacuumMed", 0, mat);
TGeoMedium *Al = new TGeoMedium("AlMed", 2, matAl);
TGeoMedium *silicon = new TGeoMedium("siliconMed", 2, matSilicon);
TGeoMedium *glue = new TGeoMedium("glueMed", 2, matGlue);
TGeoMedium *tpg = new TGeoMedium("tpgMed", 2, matTPG);
TGeoMedium *diamond = new TGeoMedium("diamondMed", 2, matDiamond);
TGeoMedium *FPC = new TGeoMedium("FPCMed", 2, matFPC);
top = manager->MakeBox("Top", vac, 300., 300., 300.);
manager->SetTopVolume(top);
TGeoVolume *mvd = new TGeoVolumeAssembly("TwoStation");
TGeoVolume *sensorActive = manager->MakeBox(
"sensorActive", silicon, sensorDimensionsActive[0] / 2,
sensorDimensionsActive[1] / 2, sensorDimensionsActive[2] / 2);
TGeoVolume *sensorPassive = manager->MakeBox(
"sensorPassive", silicon, sensorDimensionsPassive[0] / 2,
sensorDimensionsPassive[1] / 2, sensorDimensionsPassive[2] / 2);
TGeoVolume *sensorGlue = manager->MakeBox(
"sensorGlue", glue, sensorDimensionsActive[0] / 2,
(sensorDimensionsActive[1] + sensorDimensionsPassive[1]) / 2,
glueThickness / 2);
sensorActive->SetTransparency(0);
sensorActive->SetLineColor(kAzure + 3);
sensorPassive->SetTransparency(0);
sensorPassive->SetLineColor(kCyan + 1);
sensorGlue->SetTransparency(0);
sensorGlue->SetLineColor(kCyan - 10);
Float_t fpcGlueDimensions[2] = {sensorDimensionsActive[0],
sensorPitch - sensorActiveOverlap};
TGeoVolume *fpcGlue =
manager->MakeBox("fpcGlue", glue, fpcGlueDimensions[0] / 2,
fpcGlueDimensions[1] / 2, glueThickness / 2);
fpcGlue->SetTransparency(0);
fpcGlue->SetLineColor(kCyan - 10);
TGeoTranslation T;
TGeoRotation R;
TGeoCombiTrans *M;
char station_name[30], quadrant_name[30], carrier_name[30], heatsink_name[30],
heatsinkpart_name[30], cable_name[30];
int heatsinkpartno = 0, cablepartno = 0;
// --- Sensor Assembly
TGeoVolume *sensor = new TGeoVolumeAssembly("sensor");
// Glue
Float_t x_offset = -sensorDimensionsActive[0] / 2;
Float_t y_offset =
-(sensorDimensionsActive[1] + sensorDimensionsPassive[1]) / 2;
Float_t z_offset = glueThickness / 2;
T.SetTranslation(x_offset, y_offset, -z_offset);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
sensor->AddNode(sensorGlue, 1, M);
// Active
x_offset = -sensorDimensionsActive[0] / 2;
y_offset = -sensorDimensionsActive[1] / 2;
z_offset = sensorDimensionsActive[2] / 2 + glueThickness;
T.SetTranslation(x_offset, y_offset, -z_offset);
M = new TGeoCombiTrans(T, R);
sensor->AddNode(sensorActive, 1, M);
// Passive
y_offset = -sensorDimensionsPassive[1] / 2 - sensorDimensionsActive[1];
T.SetTranslation(x_offset, y_offset, -z_offset);
M = new TGeoCombiTrans(T, R);
sensor->AddNode(sensorPassive, 1, M);
for (int i = 0; i < numStations; i++) {
// --- Station Assembly
cout << "Station " << i << endl;
sprintf(station_name, "station_S%i", i);
TGeoVolume *station = new TGeoVolumeAssembly(station_name);
// --- Quadrant Assembly
sprintf(quadrant_name, "quadrant_S%i", i);
quadrant = new TGeoVolumeAssembly(quadrant_name);
// --- Heatsink Assembly
sprintf(heatsink_name, "heatsink_S%i", i);
TGeoVolume *heatsink = new TGeoVolumeAssembly(heatsink_name);
// --- Carrier
sprintf(carrier_name, "carrier_S%i", i);
Float_t cd[3] = {carrierDimensions[i][0], carrierDimensions[i][1],
carrierDimensions[i][2]};
TGeoMedium *carrierMedium;
int carrierColor;
switch (carrierMaterials[i]) {
case 0:
carrierMedium = diamond;
carrierColor = kGray;
break;
case 1:
carrierMedium = tpg;
carrierColor = kGray + 3;
break;
default:
printf("Carrier material index not found: %i\n", carrierMaterials[i]);
exit(1);
}
TGeoVolume *carrier =
manager->MakeBox(carrier_name, carrierMedium, cd[0] / 2, cd[1] / 2, cd[2] / 2);
carrier->SetTransparency(0);
carrier->SetLineColor(carrierColor);
T.SetTranslation(-cd[0] / 2, -cd[1] / 2, 0);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(carrier, 1, M);
// --- Heatsink
R.SetAngles(0., 0., 0.);
// first part next to carrier
sprintf(heatsinkpart_name, "heatsinkpart_%i", heatsinkpartno++);
Float_t height_1 = heatsinkWidth[i] / 2 - cd[1] + carrierClampOverlap -
quadrantBeamOffset[i];
Float_t width_1 = heatsinkWidth[i] / 2 + quadrantBeamOffset[i];
Float_t thickness = heatsinkThickness;
TGeoVolume *hs_part1 = manager->MakeBox(heatsinkpart_name, Al, width_1 / 2.,
height_1 / 2., thickness / 2.);
hs_part1->SetTransparency(10);
hs_part1->SetLineColor(kGray);
T.SetTranslation(-width_1 / 2, -height_1 / 2 - cd[1] + carrierClampOverlap,
0);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(hs_part1, 1, M);
// second part next to carrier
sprintf(heatsinkpart_name, "heatsinkpart_%i", heatsinkpartno++);
Float_t height_2 = heatsinkWidth[i] - height_1 - width_1;
Float_t width_2 = heatsinkWidth[i] / 2 - cd[0] + carrierClampOverlap +
quadrantBeamOffset[i];
TGeoVolume *hs_part2 = manager->MakeBox(heatsinkpart_name, Al, width_2 / 2,
height_2 / 2, thickness / 2);
hs_part2->SetTransparency(10);
hs_part2->SetLineColor(kGray);
T.SetTranslation(-width_2 / 2 - cd[0] + carrierClampOverlap, -height_2 / 2,
0);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(hs_part2, 1, M);
// element to fill top and bottom if needed
sprintf(heatsinkpart_name, "heatsinkpart_%i", heatsinkpartno++);
Float_t height = (heatsinkHeight - heatsinkWidth[i]) / 2;
if (height > 0.1) {
TGeoVolume *hs_part3 =
manager->MakeBox(heatsinkpart_name, Al, heatsinkWidth[i] / 2,
height / 2, heatsinkThickness / 2);
hs_part3->SetTransparency(10);
hs_part3->SetLineColor(kGray);
T.SetTranslation(0, height / 2 + heatsinkWidth[i] / 2, 0);
M = new TGeoCombiTrans(T, R);
heatsink->AddNode(hs_part3, 1, M);
T.SetTranslation(0, -(height / 2 + heatsinkWidth[i] / 2), 0);
M = new TGeoCombiTrans(T, R);
heatsink->AddNode(hs_part3, 2, M);
T.SetTranslation(0, 0, 0);
M = new TGeoCombiTrans(T, R);
station->AddNode(heatsink, 1, M);
}
// --- Sensors
cout << " # of sensors per quadrant: " << sensorCols[i] * sensorRows[i]
<< endl;
R.SetAngles(0., 0., 0.);
TGeoVolume *cable;
Float_t cableDimensions[2] = {0.0, 0.0};
for (int k = 0; k < sensorCols[i]; k++) {
if (k % 2 == 0) {
// Make new cable with correct dimensions
sprintf(cable_name, "cable_%i", cablepartno++);
cableDimensions[0] = cd[0] - sensorDimensionsActive[0] * k;
cableDimensions[1] = fpcWidth;
cable = manager->MakeBox(cable_name, FPC, cableDimensions[0] / 2,
cableDimensions[1] / 2, fpcThickness / 2);
cable->SetTransparency(0);
cable->SetLineColor(kSpring - 1);
}
for (int l = 0; l < sensorRows[i]; l++) {
Float_t y_offset = -sensorPitch * l;
Float_t z_offset = cd[2] / 2;
R.SetAngles(0., 0., 0.);
Float_t x_offset = -sensorDimensionsActive[0] * k;
if (l % 2 == 0) // front side
z_offset = -z_offset;
if (l % 2 == 1) // back side
{
R.SetAngles(0., 180., 180.);
x_offset -= sensorDimensionsActive[0];
}
T.SetTranslation(x_offset, y_offset, z_offset);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(sensor, k * sensorRows[i] + l, M);
if (k % 2 == 0) {
// add FPC and glue for the cable
Float_t directional_z_offset = 0.0;
directional_z_offset += glueThickness; // sensor glue
directional_z_offset += sensorDimensionsActive[2]; // sensor
directional_z_offset +=
(fpcThickness + glueThickness) * (k / 2); // fpcAssembly pitch
// fpcGlue
Float_t fpcGlue_x_offset =
-fpcGlueDimensions[0] / 2 - sensorDimensionsActive[0] * k;
Float_t fpcGlue_y_offset = -fpcGlueDimensions[1] / 2 -
sensorPitch * (l + 1) -
sensorDimensionsPassive[1];
Float_t fpcGlue_z_offset = z_offset;
directional_z_offset += glueThickness / 2;
if (l % 2 == 0) // front side
fpcGlue_z_offset -= directional_z_offset;
if (l % 2 == 1) // back side
fpcGlue_z_offset += directional_z_offset;
T.SetTranslation(fpcGlue_x_offset, fpcGlue_y_offset,
fpcGlue_z_offset);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(fpcGlue, 1, M);
if (k != sensorCols[i] - 1) {
T.SetTranslation(fpcGlue_x_offset - fpcGlueDimensions[0],
fpcGlue_y_offset, fpcGlue_z_offset);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(fpcGlue, 1, M);
}
// cable
Float_t fpc_x_offset =
-cableDimensions[0] / 2 - sensorDimensionsActive[0] * k;
Float_t fpc_y_offset = -cableDimensions[1] / 2 -
sensorPitch * (l + 1) -
sensorDimensionsPassive[1];
Float_t fpc_z_offset = z_offset;
directional_z_offset += glueThickness / 2;
directional_z_offset += fpcThickness / 2;
if (l % 2 == 0) // front side
fpc_z_offset -= directional_z_offset;
if (l % 2 == 1) // back side
fpc_z_offset += directional_z_offset;
T.SetTranslation(fpc_x_offset, fpc_y_offset, fpc_z_offset);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
quadrant->AddNode(cable, l + 1, M);
}
}
}
for (int j = 0; j < 4; j++) {
cout << " Quadrant " << j << endl;
Float_t x_sign = (j == 0 || j == 3) ? 1. : -1.;
Float_t y_sign = (j == 0 || j == 1) ? -1. : 1.;
T.SetTranslation(x_sign * quadrantBeamOffset[i],
y_sign * quadrantBeamOffset[i], 0);
R.SetAngles(0., 0., -90. * j);
M = new TGeoCombiTrans(T, R);
station->AddNode(quadrant, j, M);
}
T.SetTranslation(0, 0, explosion * stationPosition[i]);
R.SetAngles(0., 0., 0.);
M = new TGeoCombiTrans(T, R);
mvd->AddNode(station, 1, M);
station->Draw("");
gPad->GetView()->RotateView(90, 180);
char filename[30];
sprintf(filename, "mvd.root.S%i.pdf", i);
c3D->SaveAs(filename);
stations[i] = station;
}
// Add top and bottom mounting plates
double depth =
stationPosition[numStations - 1] - stationPosition[0] + heatsinkThickness;
TGeoVolume *top_bottom_plate = manager->MakeBox(
"top_bottom_plate", Al, heatsinkWidth[numStations - 1] / 2,
topPlateThickness / 2, depth / 2);
top_bottom_plate->SetTransparency(10);
top_bottom_plate->SetLineColor(kGray);
T.SetTranslation(0, +heatsinkHeight / 2 + topPlateThickness / 2,
depth / 2 + stationPosition[0] - heatsinkThickness / 2);
M = new TGeoCombiTrans(T, R);
mvd->AddNode(top_bottom_plate, 1, M);
T.SetTranslation(0, -heatsinkHeight / 2 - topPlateThickness / 2,
depth / 2 + stationPosition[0] - heatsinkThickness / 2);
M = new TGeoCombiTrans(T, R);
mvd->AddNode(top_bottom_plate, 2, M);
// Demonstration target:
// TGeoVolume *target = manager->MakeBox("target", silicon, 0.5, 0.5, 0.05);
// mvd->AddNode(target, 1);
top->AddNode(mvd, 2, new TGeoTranslation(0,0,-40));
// Standard checks, to be executed at least before submitting a new geo
manager->CloseGeometry();
manager->CheckOverlaps(0.001, "s");
top->CheckOverlaps(0.001, "s");
top->FindOverlaps();
quadrant->CheckOverlaps(0.001, "s");
manager->CheckGeometryFull();
// done with standard checks
// Open a file for writing a reporoducible format
TFile *outfile = new TFile("mvd_v25a.geo.root?reproducible", "RECREATE");
top->Write(); // Write top volume
// Also add transformation matrix to place in space:
TGeoTranslation *mvd_trans = new TGeoTranslation("", 0., 0., 0.0);
TGeoRotation *mvd_rot = new TGeoRotation();
TGeoCombiTrans *mvd_combi_trans = new TGeoCombiTrans(*mvd_trans, *mvd_rot);
//mvd_combi_trans->Write("trans");
outfile->Close();
mvd->Draw("ogl");
// station->Draw("ogl");
// quadrant->Draw("ogl");
// quadrant->Draw("");
// quadrant->Raytrace();
// top->Draw("");
// gPad->GetView()->ShowAxis();
// top->Raytrace();
}
## MVD Simulation Geometry
This repository contains files necessary to (re-) create the
CbmRoot simulation geometry of the Micro Vertex Detector (MVD).
Imported files from https://git.cbm.gsi.de/mvd/simulation-geometry
Branches in this repo contain other versions of the MVD simulation geometry
/* Copyright (C) 2013-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Volker Friese, David Emschermann [committer] */
/******************************************************************************
** Creation of beam pipe geometry in ROOT format (TGeo).
**
** @file create_pipegeo_v16.C
** @author Volker Friese <v.friese@gsi.de>
** @date 11.10.2013
**
** The beam pipe is composed of carbon with a thickness of 0.5 mm. It is
** placed directly into the cave as mother volume.
** The pipe consists of a number of parts. Each part has a PCON
** shape. The beam pipe inside the RICH is part of the RICH geometry;
** the beam pipe geometry thus excludes the z range of the RICH in case
** the latter is present in the setup.
*****************************************************************************/
// 2025.02.07 - DE - add NCAL mockup to v20a
// 2020.05.05 - DE - update table dimensions and position measured by Christian Sturm
// 2018.08.23 - DE - shorten the table length from 400 cm to 250 cm
#include "TGeoManager.h"
#include "TGeoPcon.h"
#include "TGeoTube.h"
#include <iomanip>
#include <iostream>
using namespace std;
// ------------- Other global variables -----------------------------------
// ---> TGeoManager (too lazy to write out 'Manager' all the time
TGeoManager* gGeoMan = NULL; // will be set later
// ----------------------------------------------------------------------------
// ============================================================================
// ====== Main function =====
// ============================================================================
void create_platform_v24a()
{
// ----- Define platform parts ----------------------------------------------
/** For v24a (mCBM) **/
TString geoTag = "v24a_mcbm";
// Double_t platform_angle = 25.; // rotation angle around y-axis
// Double_t platform_angle = 19.; // rotation angle around y-axis
Double_t platform_angle = 0.; // rotation angle around y-axis
// Double_t platX_offset = -230.; // offset to the right side along x-axis
Double_t platX_offset = -25.1; // offset along x-axis
Double_t platY_offset = 0.0; // offset along y-axis
Double_t platZ_offset = 13.7; // offset along z-axis
Double_t sizeX = 100.0; // table width // until 15.05.2020: 80.0;
Double_t sizeY = 98.5; // table height // until 15.05.2020: 80.0;
Double_t sizeZ = 215.5; // table length // until 15.05.2020: 250.0;
// Double_t endZ = 450.0; // ends at z = 450.0
// /** For v16b (SIS 300) **/
// TString geoTag = "v16b";
// Double_t sizeX = 725.0; // symmetric in x
// Double_t sizeY = 234.0; // without rails
// Double_t sizeZ = 455.0; // long version
// Double_t endZ = 540.0; // ends at z = 450.0
// Double_t beamY = 570.0; // nominal beam height
Double_t beamY = 200.0; // nominal beam height
Double_t posX = 0;
Double_t posY = -beamY + sizeY / 2.; // rest on the floor at -beamY
Double_t posZ = +sizeZ / 2.;
// --------------------------------------------------------------------------
// ------- Geometry file name (output) ----------------------------------
TString geoFileName = "platform_";
geoFileName = geoFileName + geoTag + ".geo.root";
// --------------------------------------------------------------------------
// ------- Open info file -----------------------------------------------
TString infoFileName = geoFileName;
infoFileName.ReplaceAll("root", "info");
fstream infoFile;
infoFile.open(infoFileName.Data(), fstream::out);
infoFile << "Platform geometry created with create_platform_v24a.C" << std::endl << std::endl;
// --------------------------------------------------------------------------
// ------- Load media from media file -----------------------------------
FairGeoLoader* geoLoad = new FairGeoLoader("TGeo", "FairGeoLoader");
FairGeoInterface* geoFace = geoLoad->getGeoInterface();
TString geoPath = gSystem->Getenv("VMCWORKDIR");
TString medFile = geoPath + "/geometry/media.geo";
geoFace->setMediaFile(medFile);
geoFace->readMedia();
gGeoMan = gGeoManager;
// --------------------------------------------------------------------------
// ----------------- Get and create the required media -----------------
FairGeoMedia* geoMedia = geoFace->getMedia();
FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
// // ---> aluminium
// FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium");
// if ( ! mAluminium ) Fatal("Main", "FairMedium aluminium not found");
// geoBuild->createMedium(mAluminium);
// TGeoMedium* aluminium = gGeoMan->GetMedium("aluminium");
// if ( ! aluminium ) Fatal("Main", "Medium aluminium not found");
FairGeoMedium* mAir = geoMedia->getMedium("air");
if (!mAir) Fatal("Main", "FairMedium air not found");
geoBuild->createMedium(mAir);
TGeoMedium* air = gGeoMan->GetMedium("air");
if (!air) Fatal("Main", "Medium air not found");
// --------------------------------------------------------------------------
// -------------- Create geometry and top volume -------------------------
gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
gGeoMan->SetName("PLATFORMgeom");
TGeoVolume* top = new TGeoVolumeAssembly("top");
gGeoMan->SetTopVolume(top);
TString platformName = "platform_";
platformName += geoTag;
TGeoVolume* platform = new TGeoVolumeAssembly(platformName.Data());
// --------------------------------------------------------------------------
// ----- Create ---------------------------------------------------------
TGeoBBox* platform_base = new TGeoBBox("", sizeX / 2., sizeY / 2., sizeZ / 2.);
TGeoVolume* platform_vol = new TGeoVolume("platform", platform_base, air);
platform_vol->SetLineColor(kBlue);
platform_vol->SetTransparency(70);
TGeoTranslation* platform_trans = new TGeoTranslation("", posX, posY, posZ);
platform->AddNode(platform_vol, 1, platform_trans);
infoFile << "sizeX : " << setprecision(2) << sizeX << " cm " << endl
<< "sizeY : " << setprecision(2) << sizeY << " cm " << endl
<< "sizeZ : " << setprecision(2) << sizeZ << " cm " << endl
<< endl;
infoFile << "posX : " << setprecision(2) << posX << " cm " << endl
<< "posY : " << setprecision(2) << posY << " cm " << endl
<< "posZ : " << setprecision(2) << posZ << " cm " << endl
<< endl;
infoFile << "offsetX : " << setprecision(2) << platX_offset << " cm " << endl
<< "offsetY : " << setprecision(2) << platY_offset << " cm " << endl
<< "offsetZ : " << setprecision(2) << platZ_offset << " cm " << endl
<< endl;
// --------------- Finish -----------------------------------------------
top->AddNode(platform, 1);
// ----- Create ncal -------------------------------------------------
//=======================================================================================
// -------------- Create geometry and top volume -------------------------
TString ncalName = "ncal_v24a";
// gGeoMan->SetTopVolume(top);
// TGeoVolume* ncal = new TGeoVolumeAssembly(ncalName.Data());
// --------------------------------------------------------------------------
// Laenge 50.0 cm
// Durchmesser 14.0 cm
const Bool_t IncludeOuterRing = true; // false; // true, plot out 6 detectors
const Bool_t IncludeInnerCore = true; // false; // true, plot inner detectors
// start and stop angles
Double_t angle1 = 0; // closed
Double_t angle2 = 360; // closed
Double_t gxoff = 0; // global offset in x
Double_t gyoff = 0; // global offset in y
Double_t gzoff = 380; // global offset in z
gxoff -= platX_offset; // global offset in x
gyoff -= platY_offset; // global offset in y
gzoff -= platZ_offset; // global offset in z
// 7 ncal array
Double_t rmax50 = 14.0 / 2.;
Double_t rmin50 = 0.;
Double_t length50 = 50.0;
Double_t nscale = 1.01;
// TGeoVolume* vncal00 = gGeoManager->MakePgon("ncal00", air, 0, 360, 6, 2); // 1 section
TGeoVolume* vncal00 = gGeoManager->MakePgon("ncal00", air, angle1, angle2, 6, 4); // 2 sections
TGeoPgon *pgon = (TGeoPgon*)(vncal00->GetShape());
pgon->DefineSection(0,-length50 /2., rmin50, rmax50); // detector
pgon->DefineSection(1, length50 /2., rmin50, rmax50); // detector
pgon->DefineSection(2, length50 /2. , rmin50, rmax50/2.); // light guide
pgon->DefineSection(3, length50 /2.+10, rmin50, rmax50/2.); // light guide
vncal00->SetLineColor(kGreen);
TGeoTranslation* tra1 = new TGeoTranslation("tra1", gxoff + cos( 30 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin( 30 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 1, tra1);
TGeoTranslation* tra2 = new TGeoTranslation("tra2", gxoff + cos( 90 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin( 90 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 2, tra2);
TGeoTranslation* tra3 = new TGeoTranslation("tra3", gxoff + cos(150 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin(150 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 3, tra3);
TGeoTranslation* tra4 = new TGeoTranslation("tra4", gxoff + cos(210 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin(210 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 4, tra4);
TGeoTranslation* tra5 = new TGeoTranslation("tra5", gxoff + cos(270 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin(270 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 5, tra5);
TGeoTranslation* tra6 = new TGeoTranslation("tra6", gxoff + cos(330 * acos(-1)/180) * 2 * rmax50 * nscale, gyoff + sin(330 * acos(-1)/180) * 2 * rmax50 * nscale, gzoff + length50 / 2.);
if (IncludeOuterRing) platform->AddNode(vncal00, 6, tra6);
TGeoTranslation* tra7 = new TGeoTranslation("tra7", gxoff + 0., gyoff + 0., gzoff + length50 / 2.);
if (IncludeInnerCore) platform->AddNode(vncal00, 7, tra7);
// --------------- Finish -----------------------------------------------
// TGeoTranslation* tra_ncal = new TGeoTranslation("tra_ncal", gxoff, gyoff, gzoff);
// platform->AddNode(ncal, 1, tra_ncal);
cout << endl << endl;
gGeoMan->CloseGeometry();
gGeoMan->CheckOverlaps(0.001);
gGeoMan->PrintOverlaps();
gGeoMan->Test();
platform->Export(geoFileName); // an alternative way of writing the platform volume
TFile* geoFile = new TFile(geoFileName, "UPDATE");
// rotate the platform around y
TGeoRotation* platform_rotation = new TGeoRotation();
platform_rotation->RotateY(platform_angle);
// TGeoCombiTrans* platform_placement = new TGeoCombiTrans( sin( platform_angle/180.*acos(-1) ) * z1[1]/2., 0., 0., platform_rotation);
TGeoCombiTrans* platform_placement =
new TGeoCombiTrans("platform_rot", platX_offset, platY_offset, platZ_offset, platform_rotation);
// TGeoTranslation* platform_placement = new TGeoTranslation("platform_trans", 0., 0., 0.);
platform_placement->Write();
geoFile->Close();
cout << endl;
cout << "Geometry " << top->GetName() << " written to " << geoFileName << endl;
top->Draw("ogl");
infoFile.close();
}
// ============================================================================
// ====== End of main function =====
// ============================================================================
This diff is collapsed.
......@@ -228,7 +228,7 @@ void create_psdgeo()
// ----- Write PSD volume and placement matrix to geometry file ---------
cout << endl;
TString geoFileName = "psd_";
geoFileName = geoFileName + geoTag + ".geo.root";
geoFileName = geoFileName + geoTag + ".geo.root?reproducible";
psd->Export(geoFileName);
TFile* geoFile = new TFile(geoFileName, "UPDATE");
psdTrans->Write();
......@@ -242,7 +242,7 @@ void create_psdgeo()
// ----- Write entire TGeoManager to file -------------------------------
TString geoManFileName = "psd_";
geoManFileName = geoManFileName + geoTag + ".geoman.root";
geoManFileName = geoManFileName + geoTag + ".geoman.root?reproducible";
TFile* geoManFile = new TFile(geoManFileName, "RECREATE");
gGeoManager->Write();
geoManFile->Close();
......
......@@ -292,7 +292,7 @@ void create_psdgeo_46modules()
// ----- Write PSD volume and placement matrix to geometry file ---------
cout << endl;
TString geoFileName = "psd_";
geoFileName = geoFileName + geoTag + ".geo.root";
geoFileName = geoFileName + geoTag + ".geo.root?reproducible";
psd->Export(geoFileName);
TFile* geoFile = new TFile(geoFileName, "UPDATE");
psdTrans->Write();
......@@ -306,7 +306,7 @@ void create_psdgeo_46modules()
// ----- Write entire TGeoManager to file -------------------------------
TString geoManFileName = "psd_";
geoManFileName = geoManFileName + geoTag + ".geoman.root";
geoManFileName = geoManFileName + geoTag + ".geoman.root?reproducible";
TFile* geoManFile = new TFile(geoManFileName, "RECREATE");
gGeoManager->Write();
geoManFile->Close();
......
......@@ -294,7 +294,7 @@ void create_psdgeo_52modules()
// ----- Write PSD volume and placement matrix to geometry file ---------
cout << endl;
TString geoFileName = "psd_";
geoFileName = geoFileName + geoTag + ".geo.root";
geoFileName = geoFileName + geoTag + ".geo.root?reproducible";
psd->Export(geoFileName);
TFile* geoFile = new TFile(geoFileName, "UPDATE");
psdTrans->Write();
......@@ -308,7 +308,7 @@ void create_psdgeo_52modules()
// ----- Write entire TGeoManager to file -------------------------------
TString geoManFileName = "psd_";
geoManFileName = geoManFileName + geoTag + ".geoman.root";
geoManFileName = geoManFileName + geoTag + ".geoman.root?reproducible";
TFile* geoManFile = new TFile(geoManFileName, "RECREATE");
gGeoManager->Write();
geoManFile->Close();
......
......@@ -240,7 +240,7 @@ void create_psdgeo_ideal(TString geoTag = "v22a")
// ----- Write PSD volume and placement matrix to geometry file ---------
cout << endl;
TString geoFileName = "psd_";
geoFileName = geoFileName + geoTag + ".geo.root";
geoFileName = geoFileName + geoTag + ".geo.root?reproducible";
psd->Export(geoFileName);
TFile* geoFile = new TFile(geoFileName, "UPDATE");
psdTrans->Write();
......@@ -254,7 +254,7 @@ void create_psdgeo_ideal(TString geoTag = "v22a")
// ----- Write entire TGeoManager to file -------------------------------
TString geoManFileName = "psd_";
geoManFileName = geoManFileName + geoTag + ".geoman.root";
geoManFileName = geoManFileName + geoTag + ".geoman.root?reproducible";
TFile* geoManFile = new TFile(geoManFileName, "RECREATE");
gGeoManager->Write();
geoManFile->Close();
......
......@@ -37,7 +37,7 @@ TGeoVolume* ConstructShield(const char* name, Double_t sizeXY, Double_t holesize
// ====== Main function =====
// ============================================================================
void create_psdgeo_with_hole(TString geoTag = "v23a")
void create_psdgeo_with_hole(TString geoTag = "v24f")
{
// ----- Steering variables ---------------------------------------------
......@@ -70,9 +70,18 @@ void create_psdgeo_with_hole(TString geoTag = "v23a")
psdZ = 1756;
psdRotY = 0.0;
holeSize = 20.;
comment = "This is the PSD parking position for no magnetic field. Or very large beam enery.";
}
else if (geoTag == "v24f") {
psdX = -2.47;
psdY = 0;
psdZ = 1010;
psdRotY = 0.0;
holeSize = 20.;
comment = "This is the PSD parking position for an out-of-the-way position to be used in hadron and muon setuos.";
}
const Double_t bigModuleSize = 20.; // Module size (cm)
const Int_t nModulesX = 8; // Number of modules in a row (x direction)
const Int_t nModulesY = 6; // Number of modules in a row (x direction)
......@@ -304,7 +313,7 @@ void create_psdgeo_with_hole(TString geoTag = "v23a")
// ----- Write PSD volume and placement matrix to geometry file ---------
cout << endl;
TString geoFileName = "psd_";
geoFileName = geoFileName + geoTag + ".geo.root";
geoFileName = geoFileName + geoTag + ".geo.root?reproducible";
psd->Export(geoFileName);
TFile* geoFile = new TFile(geoFileName, "UPDATE");
psdTrans->Write();
......@@ -318,7 +327,7 @@ void create_psdgeo_with_hole(TString geoTag = "v23a")
// ----- Write entire TGeoManager to file -------------------------------
TString geoManFileName = "psd_";
geoManFileName = geoManFileName + geoTag + ".geoman.root";
geoManFileName = geoManFileName + geoTag + ".geoman.root?reproducible";
TFile* geoManFile = new TFile(geoManFileName, "RECREATE");
gGeoManager->Write();
geoManFile->Close();
......
/* Copyright (C) 2020-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Florian Uhlig, David Emschermann [committer] */
// clang-format off
#include <iostream>
//#include "FairGeoMedium.h"
//#include "FairGeoBuilder.h"
//#include "FairGeoMedia.h"
#include "TGeoManager.h"
#include "TGeoVolume.h"
using namespace std;
// Changelog
// 2024-05-07 - v24a - DE - Based on v21c, shift to new z-position
// 2022-05-23 - v21c - DE - Based on v21b, rotate RICH orthogonal to the z-axis
// 2022-03-08 - v21b - DE - Based on v21a, relocate RICH along the rail onto the 25 degree line by -20 cm
// 2021-09-28 - v21a - SR - Based on v20d, moved RICH according to the TOF v21d
// 2020-05-25 - v20d - AW - Move mRICH by +7.2cm in Z accordingly to the mTOF movement from rev 16441
// 2020-05-20 - v20d - AW - changed positioning to +2.5cm to 25°line (nearer to beam axis) (from Analysis)
// 2020-05-06 - v20b - AW - changed positioning to center on 25° line (without Window)
// 2020-04-02 - v19a - FU - same as v19c but with exported geometry in output file
// 2019-11-28 - v19c - DE - move mRICH +12+7 cm in x direction (same as mTOF v19b) for the Nov 2019 run
// 2017-11-17 - v18d - DE - add aerogel as radiator to the mRICH module
// 2017-11-12 - v18c - DE - push mRICH downstream to z=355 cm for long setup
// 2017-07-19 - v18b - DE - add one level to the geometry hierarchy
// 2017-07-15 - v18b - DE - arrange 4x mRICH detectors in the setup and tilt towards target
void create_rich_v24a_mcbm()
{
gSystem->Load("libGeom");
// Load FairRunSim to ensure the correct unit system
FairRunSim* sim = new FairRunSim();
TString geoFileName = "rich_v24a_mcbm.geo.root?reproducible"; // Reproducible flag removes changing timestamps etc...
TString topNodeName = "rich_v24a_mcbm";
// displace RICH module along the rails on the TOF frame
Double_t XOffset = 0;
Double_t ZOffset = -9-12; // 2024 z-position
Double_t displacement_along_rails = -23.5; // cm for Nickel-58 run
Double_t support_frame_rotation_angle = 0; // 12.5; // degrees
XOffset += +displacement_along_rails *cos( support_frame_rotation_angle * acos(-1)/180 );
ZOffset += -displacement_along_rails *sin( support_frame_rotation_angle * acos(-1)/180 );
// end of displacement along the rails
FairGeoLoader* geoLoad = new FairGeoLoader("TGeo", "FairGeoLoader");
FairGeoInterface* geoFace = geoLoad->getGeoInterface();
TString geoPath = gSystem->Getenv("VMCWORKDIR");
TString medFile = geoPath + "/geometry/media.geo";
geoFace->setMediaFile(medFile);
geoFace->readMedia();
TGeoManager* gGeoMan = gGeoManager;
FairGeoMedia* geoMedia = geoFace->getMedia();
FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
//Media
FairGeoMedium* mAluminium = geoMedia->getMedium("aluminium");
if (mAluminium == NULL) Fatal("Main", "FairMedium aluminium not found");
geoBuild->createMedium(mAluminium);
TGeoMedium* medAl = gGeoMan->GetMedium("aluminium");
if (medAl == NULL) Fatal("Main", "Medium vacuum not found");
FairGeoMedium* mKapton = geoMedia->getMedium("kapton");
if (mKapton == NULL) Fatal("Main", "FairMedium kapton not found");
geoBuild->createMedium(mKapton);
TGeoMedium* medKapton = gGeoMan->GetMedium("kapton");
if (medKapton == NULL) Fatal("Main", "Medium kapton not found");
FairGeoMedium* mAir = geoMedia->getMedium("air");
if (mAir == NULL) Fatal("Main", "FairMedium air not found");
geoBuild->createMedium(mAir);
TGeoMedium* medAir = gGeoMan->GetMedium("air");
if (medAir == NULL) Fatal("Main", "Medium air not found");
FairGeoMedium* mPmtGlas = geoMedia->getMedium("PMTglass");
if (mPmtGlas == NULL) Fatal("Main", "FairMedium vacuum not found");
geoBuild->createMedium(mPmtGlas);
TGeoMedium* medPmtGlas = gGeoMan->GetMedium("PMTglass");
if (medPmtGlas == NULL) Fatal("Main", "Medium vacuum not found");
FairGeoMedium* mNitrogen = geoMedia->getMedium("RICHgas_N2_dis");
if (mNitrogen == NULL) Fatal("Main", "FairMedium RICHgas_N2_dis not found");
geoBuild->createMedium(mNitrogen);
TGeoMedium* medNitrogen = gGeoMan->GetMedium("RICHgas_N2_dis");
if (medNitrogen == NULL) Fatal("Main", "Medium RICHgas_N2_dis not found");
FairGeoMedium* mPMT = geoMedia->getMedium("CsI");
if (mPMT == NULL) Fatal("Main", "FairMedium CsI not found");
geoBuild->createMedium(mPMT);
TGeoMedium* medCsI = gGeoMan->GetMedium("CsI");
if (medCsI == NULL) Fatal("Main", "Medium CsI not found");
FairGeoMedium* mElectronic = geoMedia->getMedium("air");
if (mElectronic == NULL) Fatal("Main", "FairMedium air not found");
geoBuild->createMedium(mElectronic);
TGeoMedium* medElectronic = gGeoMan->GetMedium("air");
if (medElectronic == NULL) Fatal("Main", "Medium air not found");
FairGeoMedium* mAerogel = geoMedia->getMedium("aerogel");
if (mAerogel == NULL) Fatal("Main", "FairMedium aerogel not found");
geoBuild->createMedium(mAerogel);
TGeoMedium* medAerogel = gGeoMan->GetMedium("aerogel");
if (medAerogel == NULL) Fatal("Main", "Medium aerogel not found");
//Dimensions of the RICH prototype [cm]
const Double_t ItemToKapton = 1.85;
// Box
const Double_t boxThickness = 0.3;
const Double_t boxBackThickness = 1.;
const Double_t boxFrontThickness = 0.3;
const Double_t boxXLen = 38.2;
const Double_t boxYLen = 59.7;
const Double_t boxZLen = 25. + boxBackThickness - ItemToKapton;
const Bool_t isRotate90DegZ = false;
// PMT
// PMT specs https://www.hamamatsu.com/resources/pdf/etd/H12700_TPMH1348E.pdf
const Double_t pmtNofPixels = 8;
const Double_t pmtSize = 5.2;
const Double_t pmtSizeHalf = pmtSize / 2.;
const Double_t pmtSensitiveSize = 4.85;
const Double_t pmtPixelSize = 0.6; //pmtSensitiveSize / pmtNofPixels;
const Double_t pmtPixelSizeHalf = pmtPixelSize / 2.;
const Double_t pmtOuterPixelSize = 0.625; //pmtSensitiveSize / pmtNofPixels;
const Double_t pmtOuterPixelSizeHalf = pmtOuterPixelSize / 2.;
const Double_t pmtGap = 0.1;
const Double_t pmtGapHalf = pmtGap / 2.;
const Double_t pmtMatrixGap = 0.1;
const Double_t pmtPixelThickness = 0.1;
const Double_t pmtWindowThickness = 0.00; //0.15
Double_t pmtWindowPixelDistance = 0.0;
if (pmtWindowThickness > 0.0) pmtWindowPixelDistance = 0.0;
const Double_t pmtThickness = pmtPixelThickness + pmtWindowThickness + pmtWindowPixelDistance;
const Double_t pmtZPadding = 3.871;
const Double_t pmtXShift = 2.5;
// Electronics
const Double_t elecLength = 10.;
const Double_t elecWidth = 3. * pmtSize;
const Double_t elecHeight = 2. * pmtSize;
// Aerogel Box
const Double_t aerogelXLen = 20.;
const Double_t aerogelYLen = 20.;
const Double_t aerogelZLen = 3.;
const Double_t aerogelPmtDistance = 10.;
const Double_t aerogelGap = 0.1;
// Imaginary sensitive plane
Bool_t isIncludeSensPlane = false;
const Double_t sensPlaneSize = 200.;
const Double_t sensPlaneBoxDistance = 1.;
//Global positioning
const Double_t boxFrontToTarget = 334.2 + ItemToKapton + boxZLen / 2;
// Create the top volume
TGeoVolume* top = new TGeoVolumeAssembly("top");
gGeoMan->SetTopVolume(top);
// Rich assembly
TGeoVolume* rich = new TGeoVolumeAssembly(topNodeName);
top->AddNode(rich, 1);
// Al box
TGeoRotation* rotBox = new TGeoRotation("rotBox", 0., 0., 0.);
TGeoCombiTrans* trBox = NULL;
if (isRotate90DegZ) {
rotBox->RotateZ(90.);
rotBox->RotateY(0.955); //Tilting of Rich
trBox = new TGeoCombiTrans(0, -pmtXShift - (pmtSize + pmtGap + 1), boxFrontToTarget, rotBox);
}
else {
rotBox->RotateX(0.955); //Tilting of Rich
// Nov 2019 run
rotBox->RotateY(support_frame_rotation_angle);
//trBox = new TGeoCombiTrans(-pmtXShift-(pmtSize + pmtGap + 1)+12.+7., 0, boxFrontToTarget, rotBox);
// Mar2020
trBox = new TGeoCombiTrans(-pmtXShift - (pmtSize + pmtGap + 1) + 6.3 + XOffset + 16. + 5. + 2.5, 0,
boxFrontToTarget + 27. + ZOffset, rotBox);
}
TGeoVolume* boxVol = gGeoMan->MakeBox("box", medAl, boxXLen / 2., boxYLen / 2., boxZLen / 2.);
// rich->AddNode(boxVol, 1, trBox);
rich->AddNode(boxVol, 1);
// Gas
TGeoVolume* gasVol = gGeoMan->MakeBox("Gas", medNitrogen, boxXLen / 2. - boxThickness, boxYLen / 2. - boxThickness,
((boxZLen - boxBackThickness - boxFrontThickness) / 2.));
TGeoTranslation* trGas = new TGeoTranslation(0., 0., (-(boxBackThickness - boxFrontThickness) / 2.));
boxVol->AddNode(gasVol, 1, trGas);
// Front plane from kapton
TGeoVolume* kaptonVol = gGeoMan->MakeBox("kapton", medKapton, boxXLen / 2. - boxThickness,
boxYLen / 2. - boxThickness, boxFrontThickness / 2.);
TGeoTranslation* trKapton = new TGeoTranslation(0., 0., -(boxZLen - boxFrontThickness) / 2.);
boxVol->AddNode(kaptonVol, 1, trKapton);
// Aerogel
TGeoVolume* aerogelVol =
gGeoMan->MakeBox("aerogel", medAerogel, aerogelXLen / 2., aerogelYLen / 2., aerogelZLen / 2.);
Double_t aerogelZ = boxZLen / 2. - boxBackThickness - pmtZPadding - aerogelPmtDistance - aerogelZLen / 2.;
TGeoTranslation* trAerogel1 = new TGeoTranslation(pmtXShift, (aerogelYLen + aerogelGap) / 2., aerogelZ);
TGeoTranslation* trAerogel2 = new TGeoTranslation(pmtXShift, -(aerogelYLen + aerogelGap) / 2., aerogelZ);
gasVol->AddNode(aerogelVol, 1, trAerogel1);
gasVol->AddNode(aerogelVol, 2, trAerogel2);
// PMT
TGeoTranslation* trPmt1 = new TGeoTranslation(pmtSizeHalf + pmtGapHalf, -pmtSize - pmtGap, 0.); // Bottom Right
TGeoTranslation* trPmt2 = new TGeoTranslation(pmtSizeHalf + pmtGapHalf, 0., 0.); // Middle Right
TGeoTranslation* trPmt3 = new TGeoTranslation(pmtSizeHalf + pmtGapHalf, pmtSize + pmtGap, 0.); // Top Right
TGeoTranslation* trPmt4 = new TGeoTranslation(-pmtSizeHalf - pmtGapHalf, -pmtSize - pmtGap, 0.); // Bottom Left
TGeoTranslation* trPmt5 = new TGeoTranslation(-pmtSizeHalf - pmtGapHalf, 0., 0.); // Middle Left
TGeoTranslation* trPmt6 = new TGeoTranslation(-pmtSizeHalf - pmtGapHalf, pmtSize + pmtGap, 0.); // Top Left
TGeoVolume* pmtContVol = new TGeoVolumeAssembly("pmt_cont_vol");
TGeoVolume* pmtVol = new TGeoVolumeAssembly("pmt_vol_0");
TGeoVolume* pmtVol_180 = new TGeoVolumeAssembly("pmt_vol_1");
TGeoVolume* pmtPixelVol =
gGeoMan->MakeBox("pmt_pixel", medCsI, pmtPixelSize / 2., pmtPixelSize / 2., pmtPixelThickness / 2.);
TGeoVolume* pmtPixelVol_outer_outer =
gGeoMan->MakeBox("pmt_pixel", medCsI, pmtOuterPixelSize / 2., pmtOuterPixelSize / 2., pmtPixelThickness / 2.);
TGeoVolume* pmtPixelVol_inner_outer =
gGeoMan->MakeBox("pmt_pixel", medCsI, pmtPixelSize / 2., pmtOuterPixelSize / 2., pmtPixelThickness / 2.);
TGeoVolume* pmtPixelVol_outer_inner =
gGeoMan->MakeBox("pmt_pixel", medCsI, pmtOuterPixelSize / 2., pmtPixelSize / 2., pmtPixelThickness / 2.);
TGeoVolume* pmtWindow = gGeoMan->MakeBox("pmt_Window", medPmtGlas, pmtSizeHalf, pmtSizeHalf, pmtWindowThickness / 2.);
pmtContVol->AddNode(pmtVol_180, 1, trPmt1); // To Power Module // Bottom Right
pmtContVol->AddNode(pmtVol, 2, trPmt2); // Middle // Middle Right
pmtContVol->AddNode(pmtVol, 3, trPmt3); // To Combiner // Top Right
pmtContVol->AddNode(pmtVol_180, 4, trPmt4); // To Power Module // Bottom Left
pmtContVol->AddNode(pmtVol, 5, trPmt5); // Middle // Middle Left
pmtContVol->AddNode(pmtVol, 6, trPmt6); // To Combiner // Top Left
Int_t halfPmtNofPixels = pmtNofPixels / 2;
for (Int_t i = 0; i < pmtNofPixels; i++) {
for (Int_t j = 0; j < pmtNofPixels; j++) {
//check outer Pixels
Double_t x = 0.;
Double_t y = 0.;
bool x_outer = false;
bool y_outer = false;
if (i == 0) {
x = -(halfPmtNofPixels - 1) * pmtPixelSize - pmtOuterPixelSizeHalf;
x_outer = true;
}
else if (i == (pmtNofPixels - 1)) {
x = (halfPmtNofPixels - 1) * pmtPixelSize + pmtOuterPixelSizeHalf;
x_outer = true;
}
else if (i < halfPmtNofPixels) {
x = -((halfPmtNofPixels - 1) - i) * pmtPixelSize - pmtPixelSizeHalf;
x_outer = false;
}
else {
x = (i - halfPmtNofPixels) * pmtPixelSize + pmtPixelSizeHalf;
x_outer = false;
}
if (j == 0) {
y = -(halfPmtNofPixels - 1) * pmtPixelSize - pmtOuterPixelSizeHalf;
y_outer = true;
}
else if (j == (pmtNofPixels - 1)) {
y = (halfPmtNofPixels - 1) * pmtPixelSize + pmtOuterPixelSizeHalf;
y_outer = true;
}
else if (j < halfPmtNofPixels) {
y = -((halfPmtNofPixels - 1) - j) * pmtPixelSize - pmtPixelSizeHalf;
y_outer = false;
}
else {
y = (j - halfPmtNofPixels) * pmtPixelSize + pmtPixelSizeHalf;
y_outer = false;
}
//Double_t x = (i - (halfPmtNofPixels - 1)) * pmtPixelSize - pmtPixelSizeHalf;
//Double_t y = (j - (halfPmtNofPixels - 1)) * pmtPixelSize - pmtPixelSizeHalf;
TGeoTranslation* trij = new TGeoTranslation(x, y, -pmtPixelThickness / 2. + pmtThickness / 2.);
//normal rotated PMT (HV connector at lower side)
uint uid = 18 - ((j % 4) / 2) * 16 - (j % 2) + 2 * i + (1 - (j / 4)) * 100;
//180?? rotated PMT
uint uid_180 = 15 + ((j % 4) / 2) * 16 + (j % 2) - 2 * i + (1 - (j / 4)) * 100;
if (x_outer == true && y_outer == true) {
pmtVol->AddNode(pmtPixelVol_outer_outer, uid, trij);
pmtVol_180->AddNode(pmtPixelVol_outer_outer, uid_180, trij);
}
else if (x_outer == true && y_outer == false) {
pmtVol->AddNode(pmtPixelVol_outer_inner, uid, trij);
pmtVol_180->AddNode(pmtPixelVol_outer_inner, uid_180, trij);
}
else if (x_outer == false && y_outer == true) {
pmtVol->AddNode(pmtPixelVol_inner_outer, uid, trij);
pmtVol_180->AddNode(pmtPixelVol_inner_outer, uid_180, trij);
}
else {
pmtVol->AddNode(pmtPixelVol, uid, trij);
pmtVol_180->AddNode(pmtPixelVol, uid_180, trij);
}
}
}
TGeoTranslation* trWndw = new TGeoTranslation(0., 0., +pmtWindowThickness / 2. - pmtThickness / 2.);
if (pmtWindowThickness > 0.0) {
pmtVol->AddNode(pmtWindow, 1, trWndw);
pmtVol_180->AddNode(pmtWindow, 1, trWndw);
}
//
Double_t pmtContXLen = 2 * (pmtSize + pmtGap);
Double_t pmtContYLen = 3 * (pmtSize + pmtGap);
TGeoTranslation* trPmtCont1 = new TGeoTranslation(-pmtContXLen / 2., pmtContYLen, 0.); //Top Left
TGeoTranslation* trPmtCont2 = new TGeoTranslation(-pmtContXLen / 2., 0., 0.); //Middle Left
TGeoTranslation* trPmtCont3 = new TGeoTranslation(-pmtContXLen / 2., -pmtContYLen, 0.); //Bottom Left
TGeoTranslation* trPmtCont4 = new TGeoTranslation(pmtContXLen / 2., pmtContYLen, 0.); //
TGeoTranslation* trPmtCont5 = new TGeoTranslation(pmtContXLen / 2., 0., 0.); //
TGeoTranslation* trPmtCont6 = new TGeoTranslation(pmtContXLen / 2., -pmtContYLen, 0.); //
TGeoVolume* pmtPlaneVol = new TGeoVolumeAssembly("pmt_plane");
pmtPlaneVol->AddNode(pmtContVol, 00,
trPmtCont1); // Id gives the Address 0x7**0 of the top left DiRICH in a BP (X|Y)
pmtPlaneVol->AddNode(pmtContVol, 03, trPmtCont2);
pmtPlaneVol->AddNode(pmtContVol, 06, trPmtCont3);
pmtPlaneVol->AddNode(pmtContVol, 20, trPmtCont4);
pmtPlaneVol->AddNode(pmtContVol, 23, trPmtCont5);
pmtPlaneVol->AddNode(pmtContVol, 26, trPmtCont6);
TGeoTranslation* trPmtPlane =
new TGeoTranslation(pmtXShift, 0., boxZLen / 2. - boxBackThickness - pmtZPadding + (pmtThickness / 2.));
gasVol->AddNode(pmtPlaneVol, 1, trPmtPlane);
gGeoMan->CheckOverlaps();
gGeoMan->PrintOverlaps();
//Draw
pmtPixelVol->SetLineColor(kYellow + 4);
aerogelVol->SetLineColor(kCyan);
aerogelVol->SetTransparency(70);
gasVol->SetLineColor(kGreen);
gasVol->SetTransparency(60);
kaptonVol->SetLineColor(kBlue);
kaptonVol->SetTransparency(70);
//gGeoMan->SetTopVisible();
//boxVol->SetVisibility(true);
// boxVol->Draw("ogl");
//top->Draw("ogl");
gGeoMan->SetVisLevel(7); //7
rich->Export(geoFileName); // an alternative way of writing the trd volume
TFile* geoFile = new TFile(geoFileName, "UPDATE");
trBox->Write();
cout << endl << "Geometry exported to " << geoFileName << endl;
geoFile->Close();
}