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 (46)
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:
......
/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Abhishek Kumar Sharma, Omveer Singh, Shreya Roy, Florian Uhlig [committer] */
/*** @author Abhishek Kumar Sharma, Omveer Singh <omvir.ch@gmail.com>
** @date 17 May 2020
** For more details see info file*/
// clang-format off
// 2025-01-28 - AKS- v24a - 2 GEMs as per CBM actual position
// 2022-05-23 - DE - v22k - 2 GEMs out of acceptance / RPC downstream of TOF stack at 25 degrees
// 2022-04-29 - DE - v22j - 2 GEMs in acceptance x = -5 cm / RPC downstream of TOF stack
// 2022-03-27 - DE - v22i - 2 GEMs in acceptance x = -3 cm / RPC downstream of TOF stack
// 2022-03-27 - DE - v22h - 2 GEMs out of acceptance / RPC downstream of TOF stack
// 2022-03-26 - DE - v22g - 2 GEMs out of acceptance / RPC upstream of TOF stack out of acceptance
// 2022-03-25 - DE - v22f - 2 GEMs in acceptance / RPC upstream of TOF stack on z-axis
#include "TClonesArray.h"
#include "TDatime.h"
#include "TFile.h"
#include "TGeoBBox.h"
#include "TGeoCompositeShape.h"
#include "TGeoCone.h"
#include "TGeoManager.h"
#include "TGeoMaterial.h"
#include "TGeoMatrix.h"
#include "TGeoMedium.h"
#include "TGeoPgon.h"
#include "TGeoTube.h"
#include "TGeoVolume.h"
#include "TGeoXtru.h"
#include "TList.h"
#include "TMath.h"
#include "TObjArray.h"
#include "TRandom3.h"
#include "TString.h"
#include "TSystem.h"
#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>
TObjArray* fStations = new TObjArray();
CbmMuchStation* muchSt;
CbmMuchLayer* muchLy;
CbmMuchLayerSide* muchLySd;
// Name of output file with geometry
const TString tagVersion = "_v24a";
//const TString subVersion = "_sis100_1m_lmvm";
const TString geoVersion = "much"; // + tagVersion + subVersion;
const TString FileNameSim = geoVersion + tagVersion + "_mcbm.geo.root?reproducible";
const TString FileNameGeo = geoVersion + tagVersion + "_mcbm_geo.root?reproducible";
const TString FileNameInfo = geoVersion + tagVersion + "_mcbm.geo.info";
const TString FileNamePar = geoVersion + tagVersion + "_mcbm.par.root?reproducible";
// Names of the different used materials which are used to build the modules
// The materials are defined in the global media.geo file
const TString KeepingVolumeMedium = "air";
const TString activemedium = "MUCHargon";
const TString spacermedium = "MUCHnoryl";
const TString Al = "aluminium"; //Al for cooling & support purpose
const TString copper = "copper";
const TString g10 = "G10";
const TString RPCm= "RPCgas";
const TString RPCg= "RPCglass";
// Input parameters for MUCH stations
//********************************************
const Int_t fNst = 2; // Number of stations
Double_t TOF_Z_Front_Stand = 244.5; // this is the TOF box front
Int_t fNlayers = 1; // Number of layers
Double_t fLayersZ0[fNst] = {77.2525, 98.5535}; // Layers Positions
//Double_t fLayersZ0[fNst] = {65.7, 88.7, RpcPositionZ}; // Layers Positions
Int_t fDetType[fNst] = {3, 3}; // Detector type
Double_t fSupportLz[fNst] = {1., 1.}; // (cooling + support)
Double_t fDriftDz = 0.0035; //35 micron copper Drift
Double_t fG10Dz = 0.30; // 3 mm G10
Double_t fActiveLzSector[fNst] = {0.3, 0.3}; // Active volume thickness [cm]
Double_t fFrameLzSector[fNst] = {.3, .3}; // Frame thickness [cm]
Double_t fRpcGlassDz[fNst] = {0.0,0.0}; //Rpc Glass thickness [cm]
Double_t fSpacerPhi = 2.0; // Spacer width in Phi [cm]
Double_t fOverlapR = 2.0; // Overlap in R direction [cm]
Double_t fSpacerR1 = 6.0; // Spacer width in R at low Z[cm]
Double_t fSpacerR2 = 7.0; // Spacer width in R at high Z[cm]
//Size of Modules
//GEM
Double_t dx = 40.0;
Double_t dy1 = 3.75;
Double_t dy2 = 20;
Double_t fX[fNst] = {39.50, 39.0}; //Placement of modules in X [cm]
Double_t fY[fNst] = {0.50, 0.00}; //Placement of modules in Y [cm]
//***********************************************************
// some global variables
TGeoManager* gGeoMan = NULL; // Pointer to TGeoManager instance
TGeoVolume* gModules_station[fNst]; // Global storage for module types
// Forward declarations
void create_materials_from_media_file();
TGeoVolume* CreateStations(int ist);
TGeoVolume* CreateLayersGem(int istn, int ily);
//void SegmentLayerSide(CbmMuchStation *station, CbmMuchLayerSide *layerSide);
fstream infoFile;
void create_MUCH_geometry_v24a_mcbm()
{
// Load FairRunSim to ensure the correct unit system
FairRunSim* sim = new FairRunSim();
// ------- Open info file -----------------------------------------------
TString infoFileName = FileNameInfo;
infoFileName.ReplaceAll("root", "info");
infoFile.open(infoFileName.Data(), fstream::out);
infoFile << "MUCH geometry created with create_MUCH_geometry_v24a_real_mcbm.C" << endl << endl;
infoFile << "Build a mMUCH setup for mCBM with 2 GEM." << endl;
infoFile << "10 mm thick Al plates are used for support and cooling in the "
"GEM modules."
<< endl;
infoFile << "Drift and read-out PCBs (copper coated G10 plates) inserted for "
"realistic material budget for both GEM and RPC modules."
<< endl
<< endl;
infoFile << "No of Modules: " << fNst << " ( GEM )" << endl;
infoFile << "Position of Modules Z [cm]: ";
for (int i = 0; i < fNst; i++)
infoFile << fLayersZ0[i] << " ";
infoFile << endl << endl << "Placement of Modules:" << endl;
infoFile << "Module"
<< "\t"
<< "X [cm]"
<< "\t"
<< "Y [cm]"
<< "\t" << endl;
infoFile << "----------------------" << endl;
for (int i = 0; i < fNst; i++)
infoFile << " " << i + 1 << "\t" << fX[i] << "\t" << fY[i] << endl;
infoFile << "----------------------" << endl;
infoFile << endl << "Al Cooling Plate Thickness [cm]: ";
for (int i = 0; i < fNst; i++)
infoFile << fSupportLz[i] << " ";
infoFile << endl << "Active Volume Thickness [cm]: ";
for (int i = 0; i < fNst; i++)
infoFile << fActiveLzSector[i] << " ";
infoFile << endl << endl << endl << " GEM Module:" << endl;
infoFile << "--------------------------" << 2 * dx << "= cm -------------------------------" << endl;
infoFile << "<--------------------------2*dx------------------------------->" << endl;
infoFile << "^ . |" << endl;
infoFile << "| .... |" << endl;
infoFile << "| ........ |" << endl;
infoFile << "| .............. |" << endl;
infoFile << "| .................. |" << endl;
infoFile << "| ..................... |" << endl;
infoFile << "| ........................ |" << endl;
infoFile << "| ........................... |" << endl;
infoFile << "| .............................. |^" << endl;
infoFile << "| ................................. ||" << endl;
infoFile << "| ................................. |2*dy1 = " << 2 * dy1 << " cm" << endl;
infoFile << 2 * dy2 << " cm = "<<"2*dy2................................. ||" << endl;
infoFile << "| .............................. |^" << endl;
infoFile << "| ........................... |" << endl;
infoFile << "| ........................ |" << endl;
infoFile << "| ..................... |" << endl;
infoFile << "| ................. |" << endl;
infoFile << "| ............. |" << endl;
infoFile << "| ......... |" << endl;
infoFile << "| ...... |" << endl;
infoFile << "| ... |" << endl;
infoFile << "^ . |" << endl;
infoFile << endl;
// 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.);
TGeoVolume* top = new TGeoVolume("top", topbox, gGeoMan->GetMedium("air"));
gGeoMan->SetTopVolume(top);
TString topName = geoVersion + tagVersion + "_mcbm";
TGeoVolume* much = new TGeoVolumeAssembly(topName);
top->AddNode(much, 1);
TGeoVolume* sttn = new TGeoVolumeAssembly("station");
much->AddNode(sttn, 1);
for (Int_t istn = 0; istn < fNst; istn++) {
Double_t stGlobalZ0 = fLayersZ0[istn];
muchSt = new CbmMuchStation(istn, stGlobalZ0);
muchSt->SetRmin(0.);
muchSt->SetRmax(0.);
fStations->Add(muchSt);
gModules_station[istn] = CreateStations(istn);
sttn->AddNode(gModules_station[istn], istn);
}
gGeoMan->CloseGeometry();
gGeoMan->CheckOverlaps(0.0001, "s");
gGeoMan->PrintOverlaps();
much->Export(FileNameSim); // an alternative way of writing the much
TFile* outfile = new TFile(FileNameSim, "UPDATE");
TGeoTranslation* much_placement = new TGeoTranslation("much_trans", -6., 0., 0.);
much_placement->Write();
outfile->Close();
outfile = new TFile(FileNameGeo, "RECREATE");
gGeoMan->Write(); // use this if you want GeoManager format in the output
outfile->Close();
/*
// create medialist for this geometry
TString createmedialist = gSystem->Getenv("VMCWORKDIR");
createmedialist += "/macro/geometry/create_medialist.C";
std::cout << "Loading macro " << createmedialist << std::endl;
gROOT->LoadMacro(createmedialist);
gROOT->ProcessLine("create_medialist(\"\", false)");
*/
top->Draw("ogl");
infoFile.close();
TFile* parfile = new TFile(FileNamePar, "RECREATE");
fStations->Write("stations", 1); // for geometry parameters
parfile->Close();
infoFile.close();
// cout << "par file created" << parfile << endl;
}
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 geoFile = geoPath + "/geometry/media.geo";
geoFace->setMediaFile(geoFile);
geoFace->readMedia();
// Read the required media and create them in the GeoManager
FairGeoMedia* geoMedia = geoFace->getMedia();
FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
FairGeoMedium* Air = geoMedia->getMedium(KeepingVolumeMedium);
geoBuild->createMedium(Air);
FairGeoMedium* MUCHargon = geoMedia->getMedium(activemedium);
geoBuild->createMedium(MUCHargon);
FairGeoMedium* MUCHnoryl = geoMedia->getMedium(spacermedium);
geoBuild->createMedium(MUCHnoryl);
FairGeoMedium* MUCHsupport = geoMedia->getMedium(Al);
geoBuild->createMedium(MUCHsupport);
FairGeoMedium* copperplate = geoMedia->getMedium(copper);
geoBuild->createMedium(copperplate);
FairGeoMedium* g10plate = geoMedia->getMedium(g10);
geoBuild->createMedium(g10plate);
FairGeoMedium* RPCmedium = geoMedia->getMedium(RPCm);
geoBuild->createMedium(RPCmedium);
FairGeoMedium* RPCmaterial = geoMedia->getMedium(RPCg);
geoBuild->createMedium(RPCmaterial);
}
TGeoVolume* CreateStations(int ist)
{
TString stationName = Form("muchstation%02i", ist + 1);
TGeoVolumeAssembly* station = new TGeoVolumeAssembly(stationName); //, shStation, air);
TGeoVolume* gLayer[fNlayers + 1];
for (int ii = 0; ii < fNlayers; ii++) { // 2 Layers
// Double_t sideDz = fSupportLz[istn] / 2. + fActiveLzSector[istn] / 2.; // distance between side's and layer's centers
muchLy = new CbmMuchLayer(ist, ii, fLayersZ0[ist], 0.);
muchLy->GetSideB()->SetZ(fLayersZ0[ist] );
muchSt->AddLayer(muchLy);
gLayer[ii] = CreateLayersGem(ist, ii);
station->AddNode(gLayer[ii], ii);
}
return station;
}
TGeoVolume* CreateLayersGem(int istn, int ily)
{
TString layerName = Form("muchstation%02ilayer%i", istn + 1, ily + 1);
TGeoVolumeAssembly* volayer = new TGeoVolumeAssembly(layerName);
Double_t SupportDz = fSupportLz[istn] / 2.;
Double_t driftDz = fActiveLzSector[istn] / 2 + fDriftDz / 2.;
Double_t g10Dz = driftDz + fDriftDz / 2. + fG10Dz / 2.;
//Double_t airDz = 0.2;
Double_t moduleZ = fLayersZ0[istn];
Double_t driftZIn = moduleZ - driftDz;
Double_t driftZOut = moduleZ + driftDz;
Double_t g10ZIn = moduleZ - g10Dz;
Double_t g10ZOut = moduleZ + g10Dz ;
Double_t cool_z;
if(istn == 1) {cool_z = g10ZOut + fG10Dz / 2. + SupportDz;}
else {
cool_z = g10ZIn - fG10Dz / 2. - SupportDz;
}
Double_t dz = fActiveLzSector[istn] / 2.; // Active Volume Thickness
Int_t Nsector = 16.0;
Double_t phi0 = TMath::Pi() / Nsector; // azimuthal half widh of each module
//define the spacer dimensions
Double_t tg = (dy2 - dy1) / 2 / dx;
Double_t dd1 = fSpacerPhi * tg;
Double_t dd2 = fSpacerPhi * sqrt(1 + tg * tg);
Double_t sdy1 = dy1 + dd2 - dd1;
Double_t sdy2 = dy2 + dd2 + dd1;
Double_t sdx1 = dx + fSpacerR1; // frame width added
Double_t sdx2 = dx + fSpacerR2; // frame width added
Double_t sdz = fFrameLzSector[istn] / 2.;
//define Additional material as realistic GEM module
Double_t dz_sD = fDriftDz / 2.; //35 micron copper Drift
Double_t dz_sG = fG10Dz / 2.; // 3mm G10
Double_t sdx = sdx2;
Double_t pos[10];
Int_t iMod = 0;
for (Int_t iSide = 0; iSide < 1; iSide++) {
//muchLySd = muchLy->GetSide(iSide);
// Now start adding the GEM modules
for (Int_t iModule = 0; iModule < 1; iModule++) {
Double_t phi = 0; // add 0.5 to not overlap with y-axis for left-right layer separation
Bool_t isBack = iModule % 2;
Char_t cside = (isBack == 0) ? 'f' : 'b';
// correct the x, y positions
pos[0] = fX[istn];
pos[1] = fY[istn];
// different z positions for odd/even modules
pos[2] = moduleZ;
pos[3] = driftZIn;
pos[4] = driftZOut;
pos[5] = g10ZIn;
pos[6] = g10ZOut;
//pos[7] = airDz;
pos[7] = cool_z;
if (iSide != isBack) continue;
if (iModule != 0) iMod = iModule / 2;
muchLySd = muchLy->GetSide(0);
TGeoMedium* argon = gGeoMan->GetMedium(activemedium); // active medium
TGeoMedium* noryl = gGeoMan->GetMedium(spacermedium); // spacer medium
TGeoMedium* copperplate = gGeoMan->GetMedium(copper); // copper Drift medium
TGeoMedium* g10plate = gGeoMan->GetMedium(g10); // G10 medium
TGeoMedium* coolMat = gGeoMan->GetMedium(Al);
//TGeoMedium* Air = gGeoMan->GetMedium(KeepingVolumeMedium); // Air
// Define and place the shape of the modules
TGeoTrap* shapeGem = new TGeoTrap(dz, 0, 0, dx, dy1, dy2, 0, dx, dy1, dy2, 0);
shapeGem->SetName(Form("shStation%02iLayer%i%cModule%03iActiveGemNoHole", istn, ily, cside, iModule));
//------------------------------------------------------Al Cooling Plate--------------------------------------------------------------------
TGeoVolume* voActive;
TGeoTrap* coolGem;
TGeoVolume* voCool;
TGeoVolume* voAir;
coolGem = new TGeoTrap(SupportDz, 0, phi, sdx2, sdy1, sdy2, 0, sdx2, sdy1, sdy2, 0);
coolGem->SetName(Form("shStation%02iLayer%i%cModule%03icoolGem", istn, ily, cside, iModule));
TString CoolName = Form("muchstation%02ilayer%i%ccoolGem%03iAluminum", istn + 1, ily + 1, cside, iModule + 1);
voCool = new TGeoVolume(CoolName, coolGem, coolMat);
voCool->SetLineColor(kYellow);
//-----------------------------------------------------Air-----------------------------------------------
/*TGeoTrap* shapeAir = new TGeoTrap(airDz, 0, 0, dx, dy1, dy2, 0, dx, dy1, dy2, 0);
shapeAir->SetName(Form("shStation%02iLayer%i%cModule%03iActiveNoHole", istn, ily, cside, iModule));
TString airName = Form("muchstation%02ilayer%i%cactive%03igasArgon", istn + 1, ily + 1, cside, iMod + 1);
voAir = new TGeoVolume(airName, shapeAir, Air);
voAir->SetLineColor(kCyan);*/
//------------------------------------------------------Active Volume-----------------------------------------------------
//GEM
TGeoTrap* shapeActive = new TGeoTrap(dz, 0, 0, dx, dy1, dy2, 0, dx, dy1, dy2, 0);
shapeActive->SetName(Form("shStation%02iLayer%i%cModule%03iActiveNoHole", istn, ily, cside, iModule));
TString activeName = Form("muchstation%02ilayer%i%cactive%03igasArgon", istn + 1, ily + 1, cside, iMod + 1);
voActive = new TGeoVolume(activeName, shapeActive, argon);
voActive->SetLineColor(kGreen);
//---------------------------------------------------------Drift & PCB's---------------------------------------------------------------
TString DriftName[2], G10Name[2], AlName;
TGeoVolume *voDrift[2], *voG10[2];
TGeoTrap *DriftGem[2], *G10Gem[2];
for (int iPos = 0; iPos < 2; iPos++) {
Char_t cpos = (iPos == 0) ? 'i' : 'o';
DriftGem[iPos] = new TGeoTrap(dz_sD, 0, phi, sdx, sdy1, sdy2, 0, sdx, sdy1, sdy2, 0);
G10Gem[iPos] = new TGeoTrap(dz_sG, 0, phi, sdx, sdy1, sdy2, 0, sdx, sdy1, sdy2, 0);
DriftGem[iPos]->SetName(Form("shStation%02iLayer%i%cModule%03i%cDrift", istn, ily, cside, iModule, cpos));
DriftName[iPos] =
Form("muchstation%02ilayer%i%cside%03i%ccopperDrift", istn + 1, ily + 1, cside, iMod + 1, cpos);
G10Gem[iPos]->SetName(Form("shStation%02iLayer%i%cModule%03i%cG10", istn, ily, cside, iModule, cpos));
G10Name[iPos] = Form("muchstation%02ilayer%i%cside%03i%cG10", istn + 1, ily + 1, cside, iMod + 1, cpos);
voDrift[iPos] = new TGeoVolume(DriftName[iPos], DriftGem[iPos], copperplate);
voDrift[iPos]->SetLineColor(kRed);
voG10[iPos] = new TGeoVolume(G10Name[iPos], G10Gem[iPos], g10plate);
voG10[iPos]->SetLineColor(28);
}
//------------------------------------------------------------Frame-----------------------------------------------------------------
// Define the trapezoidal Frame
TGeoTrap* shapeFrame = new TGeoTrap(sdz, 0, 0, sdx, sdy1, sdy2, 0, sdx, sdy1, sdy2, 0);
shapeFrame->SetName(Form("shStation%02iLayer%i%cModule%03iFullFrameGemNoHole", istn, ily, cside, iModule));
TString expression = Form("shStation%02iLayer%i%cModule%03iFullFrameGemNoHole-shStation%"
"02iLayer%i%cModule%03iActiveGemNoHole",
istn, ily, cside, iModule, istn, ily, cside, iModule);
TGeoCompositeShape* shFrame = new TGeoCompositeShape(
Form("shStation%02iLayer%i%cModule%03iFinalFrameNoHole", istn, ily, cside, iModule), expression);
TString frameName = Form("muchstation%02ilayer%i%csupport%03i", istn + 1, ily + 1, cside, iMod + 1);
TGeoVolume* voFrame = new TGeoVolume(frameName, shFrame, noryl); // Frame for GEM
voFrame->SetLineColor(kMagenta);
//----------------------------------------------------Placement----------------------------------------------------------------------
// Calculate the phi angle of the sector where it has to be placed
Double_t angle = 90.0; //- (180. / TMath::Pi() * phi0); // convert angle phi from rad to deg
//Double_t angle1 = 180.0;
TGeoRotation* r2 = new TGeoRotation("r2");
//rotate in the vertical plane (per to z axis) with angle
r2->RotateZ(angle);
// if(istn == 0) {r2->RotateX(angle1);}
// if(istn == 1) {r2->RotateX(180.0);}
TGeoTranslation* trans[10];
TGeoHMatrix* incline_mod[10];
for (int i = 0; i < 6; i++) {
trans[i] = new TGeoTranslation("", pos[0] - 58.0, pos[1], pos[i + 2]); // shift GEMs in x, y, z here
incline_mod[i] = new TGeoHMatrix("");
(*incline_mod[i]) = (*trans[i]) * (*r2);
}
volayer->AddNode(voFrame, iMod, incline_mod[0]); // add spacer
volayer->AddNode(voActive, iMod, incline_mod[0]); // add active volume
volayer->AddNode(voDrift[0], iMod, incline_mod[1]); //Drift In
volayer->AddNode(voDrift[1], iMod, incline_mod[2]); //Drift Out
volayer->AddNode(voG10[0], iMod, incline_mod[3]); //G10 In
volayer->AddNode(voG10[1], iMod, incline_mod[4]); //G10 Out
volayer->AddNode(voCool, iMod, incline_mod[5]); // Al Cooling Plate
//volayer->AddNode(voAir, iMod, incline_mod[6]); //Air
TVector3 Position;
Position.SetXYZ(pos[0], pos[1], pos[2]);
cout << pos[2] << " " << pos[3] << " " << pos[4] << " " << pos[5] << " " << pos[6] << " " << pos[7]
<< endl;
muchLySd->AddModule(new CbmMuchModuleGemRadial(fDetType[istn], istn, ily, 0., iModule, Position, dy1,
dy2, dx, dz, muchSt->GetRmin()));
cout<<"stn: "<<istn<<" module: "<<iModule<<endl;
}
}
return volayer;
}
/* 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 =====
// ============================================================================
/* Copyright (C) 2022 Czech Technical University in Prague,
Faculty of Nuclear Sciences and Physical Engineering
SPDX-License-Identifier: GPL-3.0-only
Authors: Petr Chudoba [committer]*/
#include "TGeoArb8.h"
#include "TGeoCompositeShape.h"
#include "TGeoCone.h"
#include "TGeoManager.h"
#include "TGeoMatrix.h"
#include "TGeoSystemOfUnits.h"
#include "TGeoTube.h"
#include "TPad.h"
#include "TROOT.h"
#include "TSystem.h"
#include "TFile.h"
#include "TVector3.h"
#include "iostream"
#include "stdio.h"
#include "cmath"
using namespace std;
using namespace TGeoUnit;
void create_bpipe_geometry_gen(const char* geoTag = "v24f", double beam_deflection_angle=0)
{
//--- Definition of a simple geometry
gSystem->Load("libGeom");
TString geomMngr = "beampipe_";
geomMngr = geomMngr+geoTag;
TGeoManager* geom = new TGeoManager(geomMngr, "CBM beampipe geometry generator for user adjustable angles");
//--- define some materials
TGeoMixture* matCarbonFiber = new TGeoMixture("BP_carbonfiber", 4, 1.5);
matCarbonFiber->AddElement(12.001, 6.0, 0.8926);
matCarbonFiber->AddElement(1.0079, 1.0, 0.0192);
matCarbonFiber->AddElement(35.453, 17.0, 0.0271);
matCarbonFiber->AddElement(15.999, 8.0, 0.0611);
// TGeoMixture* matStainless = new TGeoMixture("BP_stainless", 10, 8.0);
// matStainless->AddElement(12.0, 6.0, 0.00035);
// matStainless->AddElement(51.94, 24.0, 0.175);
// matStainless->AddElement(54.94, 25.0, 0.01);
// matStainless->AddElement(95.94, 42.0, 0.025);
// matStainless->AddElement(14.0, 7.0, 0.0005);
// matStainless->AddElement(58.6934, 28.0, 0.115);
// matStainless->AddElement(30.97, 15.0, 0.000225);
// matStainless->AddElement(31.97, 16.0, 0.000075);
// matStainless->AddElement(27.98, 14.0, 0.005);
// matStainless->AddElement(55.93, 26.0, 0.67135);
TGeoMaterial* matVacuum = new TGeoMaterial("BP_vacuum", 1.e-16, 1.e-16, 1.e-16);
// TGeoMaterial* matAl = new TGeoMaterial("BP_aluminium", 26.9815386, 13, 2.7, 24.01);
// //--- define some media
TGeoMedium* Vacuum = new TGeoMedium("BP_vacuum", 1, matVacuum);
// TGeoMedium* Al = new TGeoMedium("BP_aluminium", 2, matAl);
TGeoMedium* CF = new TGeoMedium("BP_carbonfiber", 3, matCarbonFiber);
// TGeoMedium* Stainless = new TGeoMedium("BP_stainless", 4, matStainless);
// Conus part dimensions
const Double_t conus_lenght = 1585 * mm;
const Double_t conus_rmin1 = 55 * mm;
const Double_t conus_rmax1 = 56 * mm;
const Double_t conus_rmin2 = 125 * mm;
const Double_t conus_rmax2 = 126 * mm;
const Double_t beam_pipe_length = 14460 * mm;
const Double_t beam_pipe_rmin = 90 * mm;
const Double_t beam_pipe_rmax = 92 * mm;
const Double_t dist_to_bellow = 4418 * mm; // center of mass of upstream flange
const Double_t bending_radius = 4737 * mm; // center of mass of downstream flange
const Double_t flange_thickness = 30 * mm;
const Double_t short_segment = 45 * mm;
const Double_t long_segment = 65 * mm;
const Double_t bellow_rmin = 137.5 * mm;
const Double_t bellow_rmax = 142.5 * mm;
const Double_t cone_deflection_angle = 1.277/radian; // from deg to rad
beam_deflection_angle = beam_deflection_angle/radian; // from deg to rad
Double_t pipe_deflection_radius = bending_radius+(flange_thickness/2)+(beam_pipe_length/2);
Double_t bellow_deflection_angle = beam_deflection_angle-cone_deflection_angle; // in radians
Double_t alpha = atan((bending_radius*sin(bellow_deflection_angle))/(bending_radius*cos(bellow_deflection_angle)-dist_to_bellow)); // in radians
Double_t direction=1.0;
if (alpha!=0){
direction=alpha/abs(alpha);
}
// Center of mass points of bellow flanges
TVector3 p_b0(0,0,flange_thickness/2);
TVector3 p_b6(bending_radius*sin(bellow_deflection_angle),0,bending_radius*cos(bellow_deflection_angle)-dist_to_bellow);
// Vectors defining axis of each part of bellow
TVector3 b0(0,0,flange_thickness); // axis vector of the upstream flange
TVector3 b1(short_segment*sin(alpha/4),0,short_segment*cos(alpha/4)); // axis vector of the first bellow segment
TVector3 b2(long_segment*sin(alpha),0,long_segment*cos(alpha)); // axis vector of the second bellow segment
TVector3 b3; // axis vector of the third (middle) bellow segment - init only
TVector3 b4(long_segment*sin(alpha+bellow_deflection_angle),0,long_segment*cos(alpha+bellow_deflection_angle)); // axis vector of the fourth bellow segment
TVector3 b5(short_segment*sin((alpha/4)+bellow_deflection_angle),0,short_segment*cos((alpha/4)+bellow_deflection_angle)); // axis vector of the fifth bellow segment
TVector3 b6(flange_thickness*sin(bellow_deflection_angle),0,flange_thickness*cos(bellow_deflection_angle)); // axis vector of the downstream flange
b3 = (p_b6-(1./2)*b6-b5-b4)-(p_b0+(1./2)*b0+b1+b2); // axis vector of the third (middle) bellow segment
TVector3 pipe_vec(beam_pipe_length*sin(bellow_deflection_angle),0,beam_pipe_length*cos(bellow_deflection_angle));
Double_t middle_segment = b3.Mag();
// Angles of separate part of bellow
Double_t beta0 = direction*b0.Theta();
Double_t beta1 = direction*b1.Theta();
Double_t beta2 = direction*b2.Theta();
Double_t beta3 = direction*b3.Theta();
Double_t beta4 = direction*b4.Theta();
Double_t beta5 = direction*b5.Theta();
Double_t beta6 = direction*b6.Theta();
// Normal vectors for CTub cut planes for bellow segments
TVector3 n01(-sin((beta0-beta1)),0,-cos((beta0-beta1)));
TVector3 n12(-sin((beta1-beta2)/2),0,cos((beta1-beta2)/2));
TVector3 n21(sin((beta2-beta1)/2),0,-cos((beta2-beta1)/2));
TVector3 n23(-sin((beta2-beta3)/2),0,cos((beta2-beta3)/2));
TVector3 n32(sin((beta3-beta2)/2),0,-cos((beta3-beta2)/2));
TVector3 n34(-sin((beta3-beta4)/2),0,cos((beta3-beta4)/2));
TVector3 n43(sin((beta4-beta3)/2),0,-cos((beta4-beta3)/2));
TVector3 n45(-sin((beta4-beta5)/2),0,cos((beta4-beta5)/2));
TVector3 n54(sin((beta5-beta4)/2),0,-cos((beta5-beta4)/2));
TVector3 n56(-sin((beta5-beta6)),0,cos((beta5-beta6)));
//-----------------------DEFINITION OF TRANSFORMATIONS--------------------------------------------------------------------------------------
TGeoTranslation orig_translation("orig_translation", -0.15707676 * mm, 0, 3230 * mm);
TGeoTranslation orig_translation_cone("orig_translation_cone", -0.15707676 * mm, 0, 1645 * mm);
TGeoRotation orig_rotation("orig_rotation");
orig_rotation.RotateY(cone_deflection_angle*radian);
TGeoHMatrix orig_combi = orig_rotation * orig_translation;
TGeoHMatrix orig_combi_cone = orig_rotation * orig_translation_cone;
TGeoHMatrix* origin_combi = new TGeoHMatrix(orig_combi);
TGeoHMatrix* origin_combi_cone = new TGeoHMatrix(orig_combi_cone);
TGeoRotation* rot_sts_conus_connection = new TGeoRotation("rot_sts_conus_connection");
rot_sts_conus_connection->RotateZ(180);
TGeoCombiTrans* ctr_sts_conus_connection = new TGeoCombiTrans(0, 0, -1600 * mm, rot_sts_conus_connection);
TGeoRotation* rotation_of_sts_tube = new TGeoRotation("rotation_of_sts_tube");
rotation_of_sts_tube->RotateZ(180);
rotation_of_sts_tube->RotateY(-cone_deflection_angle*radian);
TGeoCombiTrans* ctr_sts_tube = new TGeoCombiTrans(0.3707676 * mm, 0, -1631.001 * mm, rotation_of_sts_tube);
TVector3 aux_vec;
aux_vec=(1./2)*b0;
TGeoRotation* rot_b0 = new TGeoRotation("rot_b0");
rot_b0->RotateY(beta0*radian);
TGeoCombiTrans* ctr_b0 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b0);
aux_vec=aux_vec+(1./2)*(b0+b1);
TGeoRotation* rot_b1 = new TGeoRotation("rot_b1");
rot_b1->RotateY(beta1*radian);
TGeoCombiTrans* ctr_b1 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b1);
aux_vec=aux_vec+(1./2)*(b1+b2);
TGeoRotation* rot_b2 = new TGeoRotation("rot_b2");
rot_b2->RotateY(beta2*radian);
TGeoCombiTrans* ctr_b2 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b2);
aux_vec=aux_vec+(1./2)*(b2+b3);
TGeoRotation* rot_b3 = new TGeoRotation("rot_b3");
rot_b3->RotateY(beta3*radian);
TGeoCombiTrans* ctr_b3 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b3);
aux_vec=aux_vec+(1./2)*(b3+b4);
TGeoRotation* rot_b4 = new TGeoRotation("rot_b4");
rot_b4->RotateY(beta4*radian);
TGeoCombiTrans* ctr_b4 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b4);
aux_vec=aux_vec+(1./2)*(b4+b5);
TGeoRotation* rot_b5 = new TGeoRotation("rot_b5");
rot_b5->RotateY(beta5*radian);
TGeoCombiTrans* ctr_b5 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b5);
aux_vec=aux_vec+(1./2)*(b5+b6);
TGeoRotation* rot_b6 = new TGeoRotation("rot_b6");
rot_b6->RotateY(beta6*radian);
TGeoCombiTrans* ctr_b6 = new TGeoCombiTrans(aux_vec.X(),aux_vec.Y(),aux_vec.Z(),rot_b6);
aux_vec=aux_vec+(1./2)*(b6+pipe_vec);
TGeoRotation rot_psd_tube_loc("rot_psd_tube_loc");
rot_psd_tube_loc.RotateY(beta6*radian);
TGeoTranslation tr_psd_tube_loc("tr_psd_tube", aux_vec.X(),aux_vec.Y(),aux_vec.Z());
TGeoHMatrix ctr_psd_tube_aux = orig_combi*tr_psd_tube_loc*rot_psd_tube_loc;
TGeoHMatrix* ctr_psd_tube = new TGeoHMatrix(ctr_psd_tube_aux);
//------------------------------------DEFINITIONS OF VOLUMES----------------------------------------
//--- make the top container volume
Double_t worldx = 800 * mm;
Double_t worldy = 220 * mm;
Double_t worldz = 18100 * mm;
TString assemblyName = "pipe_";
assemblyName=assemblyName+geoTag;
TGeoVolumeAssembly* full_assembly = new TGeoVolumeAssembly(assemblyName);
geom->SetTopVolume(full_assembly);
full_assembly->SetVisibility(kTRUE);
TGeoVolume* conical_beam_pipe = new TGeoVolumeAssembly("conical_beam_pipe");
conical_beam_pipe->SetVisibility(kFALSE);
TGeoVolume* vacuum_conical_beam_pipe = new TGeoVolumeAssembly("vacuum_conical_beam_pipe");
vacuum_conical_beam_pipe->SetVisibility(kFALSE);
TGeoVolume* bellow_ass = new TGeoVolumeAssembly("Bellow assembly");
bellow_ass->SetVisibility(kFALSE);
TGeoVolume* vacuum_bellow_ass = new TGeoVolumeAssembly("Vacuum_bellow assembly");
vacuum_bellow_ass->SetVisibility(kFALSE);
// DOWNSTREAM_CARBON-FIBRE_RICH_MUCH_FLANGE_TO_BELLOW_ASS------------------------------------------------------------------------------------
TGeoBBox* rich_much_flange_box = new TGeoBBox("rich_much_flange_box", 15.2, 15.2, 1.5);
TGeoTube* rich_much_flange_hole = new TGeoTube("rich_much_flange_hole", 0., 12.6, 1.6);
TGeoCompositeShape* rich_much_flange_composite =
new TGeoCompositeShape("flange_composite_rich", "rich_much_flange_box-rich_much_flange_hole");
TGeoVolume* rich_much_downstream_flange =
new TGeoVolume("rich_much_downstream_flange", rich_much_flange_composite, CF);
rich_much_downstream_flange->SetLineColor(kGray);
// VACUUM IN THE FLANGE----------------------------------------------------------------------------------------------
TGeoTube* vacuum_flange_hole = new TGeoTube("vacuum_flange_hole", 0., 12.5, 1.5);
TGeoVolume* vacuum_downstream_flange =
new TGeoVolume("vacuum_downstream_flange", vacuum_flange_hole, Vacuum);
vacuum_downstream_flange->SetLineColor(kRed);
// CONICAL_BEAM_PIPE----------------------------------------------------------------------------------------------------------
TGeoCone* conus = new TGeoCone("conus", conus_lenght, conus_rmin1, conus_rmax1, conus_rmin2, conus_rmax2);
TGeoVolume* conus_volume = new TGeoVolume("conus_volume", conus, CF);
conus_volume->SetLineColor(kGray);
//-------------------------------VACUUM IN CONE-------------------------------------------------------------------
TGeoCone* vacuum_conus = new TGeoCone("vacuum_conus", conus_lenght, 0, conus_rmin1, 0, conus_rmin2);
TGeoVolume* vacuum_conus_volume = new TGeoVolume("vacuum_conus_volume", vacuum_conus, Vacuum);
vacuum_conus_volume->SetLineColor(kGreen);
// CONNECTING TUBE--------------------------------------------------------------------------------------------------------------------------------------------------------
TGeoCtub* tube_connection = new TGeoCtub("tube_connection", 55. * mm, 56. * mm, 15. * mm, 0., 360., -0.022286009, 0., -0.999751636, 0., 0., 1.);
TGeoVolume* tube_connection_volume = new TGeoVolume("tube_connection_volume", tube_connection, CF);
tube_connection_volume->SetLineColor(kGray);
//------------------------VACUUM IN THE CONNECTING TUBE--------------------------------------------------------------
TGeoCtub* vacuum_tube_connection = new TGeoCtub("vacuum_tube_connection", 0. * mm, 55. * mm, 15. * mm, 0., 360., -0.022286009, 0., -0.999751636, 0., 0., 1.);
TGeoVolume* vacuum_tube_connection_volume = new TGeoVolume("vacuum_tube_connection_volume", vacuum_tube_connection, Vacuum);
vacuum_tube_connection_volume->SetLineColor(kGreen);
// STS tube-----------------------------------------------------------------------------------------------------
TGeoCtub* tube_connection_sts = new TGeoCtub("tube_connection_sts", 55. * mm, 56. * mm, 15. * mm, 0., 360., 0., 0., -1., 0.011143697, 0., 0.999937907);
TGeoVolume* tube_connection_sts_volume = new TGeoVolume("tube_connection_sts_volume", tube_connection_sts, CF);
tube_connection_sts_volume->SetLineColor(kGray);
//-------------------------------BELLOW DEFINITION----------------------------------------------------------------
//UPSTREAM FLANGE
TGeoBBox* flange_box = new TGeoBBox("flange_box", 15.2, 15.2, 1.5);
TGeoTube* flange_hole = new TGeoTube("flange_hole", 0., 12.5, 1.6);
TGeoCompositeShape* flange_composite = new TGeoCompositeShape("flange_composite", "flange_box-flange_hole");
TGeoVolume* bellow_flange_0 = new TGeoVolume("bellow_flange_0", flange_composite, CF);
bellow_flange_0->SetLineColor(kRed);
//BELLOW SEGMENT 1
TGeoCtub* bellow_s1 = new TGeoCtub("bellow_s1", bellow_rmin, bellow_rmax, short_segment/2-0.001, 0., 360.,
n01.X(), n01.Y(), n01.Z(), n12.X(), n12.Y(), n12.Z());
TGeoVolume* bellow_1 = new TGeoVolume("bellow_s1", bellow_s1, CF);
bellow_1->SetLineColor(kRed);
//BELLOW SEGMENT 2
TGeoCtub* bellow_s2 = new TGeoCtub("bellow_s2", bellow_rmin, bellow_rmax, long_segment/2-0.001, 0., 360.,
n21.X(), n21.Y(), n21.Z(), n23.X(), n23.Y(), n23.Z());
TGeoVolume* bellow_2 = new TGeoVolume("bellow_s2", bellow_s2, CF);
bellow_2->SetLineColor(kRed);
//BELLOW SEGMENT 3
TGeoCtub* bellow_s3 = new TGeoCtub("bellow_s3", bellow_rmin, bellow_rmax, middle_segment/2-0.001, 0., 360.,
n32.X(), n32.Y(), n32.Z(), n34.X(), n34.Y(), n34.Z());
TGeoVolume* bellow_3 = new TGeoVolume("bellow_s3", bellow_s3, CF);
bellow_3->SetLineColor(kRed);
//BELLOW SEGMENT 4
TGeoCtub* bellow_s4 = new TGeoCtub("bellow_s4", bellow_rmin, bellow_rmax, long_segment/2-0.001, 0., 360.,
n43.X(), n43.Y(), n43.Z(), n45.X(), n45.Y(), n45.Z());
TGeoVolume* bellow_4 = new TGeoVolume("bellow_s4", bellow_s4, CF);
bellow_4->SetLineColor(kRed);
//BELLOW SEGMENT 5
TGeoCtub* bellow_s5 = new TGeoCtub("bellow_s5", bellow_rmin, bellow_rmax, short_segment/2-0.001, 0., 360.,
n54.X(), n54.Y(), n54.Z(), n56.X(), n56.Y(), n56.Z());
TGeoVolume* bellow_5 = new TGeoVolume("bellow_s5", bellow_s5, CF);
bellow_5->SetLineColor(kRed);
//DOWNSTREAM FLANGE
TGeoTube* flange_cyl = new TGeoTube("flange_cyl", 8.9, 15., 1.5);
TGeoVolume* bellow_flange_1 = new TGeoVolume("bellow_flange_1", flange_cyl, CF);
bellow_flange_1->SetLineColor(kRed);
//-------------------------------BELLOW VACUUM DEFINITION----------------------------------------------------------------
//VACUUM UPSTREAM FLANGE
TGeoVolume* vacuum_bellow_flange_0 = new TGeoVolume("vacuum_bellow_flange_0", vacuum_flange_hole, Vacuum);
vacuum_bellow_flange_0->SetLineColor(kGreen);
//VACUUM BELLOW SEGMENT 1
TGeoCtub* vacuum_bellow_s1 = new TGeoCtub("vacuum_bellow_s1", 0, bellow_rmin, short_segment/2, 0., 360.,
n01.X(), n01.Y(), n01.Z(), n12.X(), n12.Y(), n12.Z());
TGeoVolume* vacuum_bellow_1 = new TGeoVolume("vacuum_bellow_s1", vacuum_bellow_s1, Vacuum);
vacuum_bellow_1->SetLineColor(kGreen);
//VACUUM BELLOW SEGMENT 2
TGeoCtub* vacuum_bellow_s2 = new TGeoCtub("vacuum_bellow_s2", 0, bellow_rmin, long_segment/2, 0., 360.,
n21.X(), n21.Y(), n21.Z(), n23.X(), n23.Y(), n23.Z());
TGeoVolume* vacuum_bellow_2 = new TGeoVolume("vacuum_bellow_s2", vacuum_bellow_s2, Vacuum);
vacuum_bellow_2->SetLineColor(kGreen);
//VACUUM BELLOW SEGMENT 3
TGeoCtub* vacuum_bellow_s3 = new TGeoCtub("vacuum_bellow_s3", 0, bellow_rmin, middle_segment/2, 0., 360.,
n32.X(), n32.Y(), n32.Z(), n34.X(), n34.Y(), n34.Z());
TGeoVolume* vacuum_bellow_3 = new TGeoVolume("vacuum_bellow_s3", vacuum_bellow_s3, Vacuum);
vacuum_bellow_3->SetLineColor(kGreen);
//VACUUM BELLOW SEGMENT 4
TGeoCtub* vacuum_bellow_s4 = new TGeoCtub("vacuum_bellow_s4", 0, bellow_rmin, long_segment/2, 0., 360.,
n43.X(), n43.Y(), n43.Z(), n45.X(), n45.Y(), n45.Z());
TGeoVolume* vacuum_bellow_4 = new TGeoVolume("vacuum_bellow_s4", vacuum_bellow_s4, Vacuum);
vacuum_bellow_4->SetLineColor(kGreen);
//VACUUM BELLOW SEGMENT 5
TGeoCtub* vacuum_bellow_s5 = new TGeoCtub("vacuum_bellow_s5", 0, bellow_rmin, short_segment/2, 0., 360.,
n54.X(), n54.Y(), n54.Z(), n56.X(), n56.Y(), n56.Z());
TGeoVolume* vacuum_bellow_5 = new TGeoVolume("vacuum_bellow_s5", vacuum_bellow_s5, Vacuum);
vacuum_bellow_5->SetLineColor(kGreen);
//VACUUM DOWNSTREAM FLANGE
TGeoTube* vacuum_flange_cyl_hole = new TGeoTube("vacuum_flange_cyl_hole", 0., 8.9, 1.5);
TGeoVolume* vacuum_bellow_flange_1 = new TGeoVolume("vacuum_bellow_flange_1", vacuum_flange_cyl_hole, Vacuum);
vacuum_bellow_flange_1->SetLineColor(kGreen);
//------------------------------PSD TUBE-------------------------------------------------------------------------
TGeoTube* psd_tube_s = new TGeoTube("psd_tube_s", beam_pipe_rmin, beam_pipe_rmax, beam_pipe_length/2);
TGeoVolume* psd_tube = new TGeoVolume("psd_tube", psd_tube_s, CF);
psd_tube->SetLineColor(kGray);
//------------------------------VACUUM PSD TUBE-------------------------------------------------------------------------
TGeoTube* vacuum_psd_tube_s = new TGeoTube("vacuum_psd_tube_s", 0. * mm, beam_pipe_rmin, beam_pipe_length/2);
TGeoVolume* vacuum_psd_tube = new TGeoVolume("vacuum_psd_tube", vacuum_psd_tube_s, Vacuum);
vacuum_psd_tube->SetLineColor(kGreen);
//----------------Bellow with flanges-----------------------------
bellow_ass->AddNode(bellow_flange_0, 1, ctr_b0);
bellow_ass->AddNode(bellow_1, 1, ctr_b1);
bellow_ass->AddNode(bellow_2, 1, ctr_b2);
bellow_ass->AddNode(bellow_3, 1, ctr_b3);
bellow_ass->AddNode(bellow_4, 1, ctr_b4);
bellow_ass->AddNode(bellow_5, 1, ctr_b5);
bellow_ass->AddNode(bellow_flange_1, 1, ctr_b6);
//----------------Vacuum in bellow and flanges-----------------------------
vacuum_bellow_ass->AddNode(vacuum_bellow_flange_0, 1, ctr_b0);
vacuum_bellow_ass->AddNode(vacuum_bellow_1, 1, ctr_b1);
vacuum_bellow_ass->AddNode(vacuum_bellow_2, 1, ctr_b2);
vacuum_bellow_ass->AddNode(vacuum_bellow_3, 1, ctr_b3);
vacuum_bellow_ass->AddNode(vacuum_bellow_4, 1, ctr_b4);
vacuum_bellow_ass->AddNode(vacuum_bellow_5, 1, ctr_b5);
vacuum_bellow_ass->AddNode(vacuum_bellow_flange_1, 1, ctr_b6);
//-------------------CONICAL section--------------------------------------------------
conical_beam_pipe->AddNode(rich_much_downstream_flange, 1, new TGeoTranslation(0, 0, 1570 * mm));
conical_beam_pipe->AddNode(conus_volume, 1, new TGeoTranslation(0, 0, 0));
conical_beam_pipe->AddNode(tube_connection_volume, 1, ctr_sts_conus_connection);
// conical_beam_pipe->AddNode(tube_connection_sts_volume, 1, ctr_sts_tube); //inset in STS box - omitted; if used, needs some fine tunning
//-------------------VACUUM in CONICAL section--------------------------------------------------
vacuum_conical_beam_pipe->AddNode(vacuum_conus_volume, 1, new TGeoTranslation(0, 0, 0));
vacuum_conical_beam_pipe->AddNode(vacuum_tube_connection_volume, 1, ctr_sts_conus_connection);
//------------------INSERT into top volume
full_assembly->AddNode(conical_beam_pipe, 1, origin_combi_cone);
full_assembly->AddNode(vacuum_conical_beam_pipe, 1, origin_combi_cone);
full_assembly->AddNode(bellow_ass, 1, origin_combi);
full_assembly->AddNode(vacuum_bellow_ass, 1, origin_combi);
full_assembly->AddNode(psd_tube, 1, ctr_psd_tube);
full_assembly->AddNode(vacuum_psd_tube, 1, ctr_psd_tube);
//beampipe->AddNode(full_assembly,1, new TGeoTranslation(0, 0, 0*mm));
// --- close the geometry
geom->CloseGeometry();
//--- draw the ROOT box
geom->SetVisLevel(4);
full_assembly->Draw();
if (gPad && !gROOT->IsBatch()) gPad->GetViewer3D();
// --------------- Finish -----------------------------------------------
TString geo_bin_filename = "pipe_";
TString geo_name = geo_bin_filename + geoTag;
geo_bin_filename = geo_bin_filename + geoTag + ".geo.root";
TFile* binfile = TFile::Open(geo_bin_filename, "RECREATE");
geom->GetTopVolume()->Write(geo_name); // outputting on the top volume
TGeoTranslation* trans = new TGeoTranslation(0.0, 0.0, 79.0003); // pushing the beampipe to touch the STS
trans->Write("trans");
cout << endl;
cout << "Geometry " << geom->GetTopVolume()->GetName() << " written to " << geo_bin_filename << endl;
binfile->Close();
//--- close the geometry
geom->CloseGeometry();
// gGeoManager->CheckOverlaps(0.000000001);
// gGeoManager->GetListOfOverlaps()->Print();
}
......@@ -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();
}