From 0dd94efd191e202a06be8c3fee86add50425f9f0 Mon Sep 17 00:00:00 2001 From: Scott Snyder <scott.snyder@cern.ch> Date: Thu, 28 Jun 2012 16:27:29 +0200 Subject: [PATCH] Update for clhep 2 (LArGeoHec-00-00-38) --- .../LArGeoModel/LArGeoHec/GNUmakefile | 7 + .../LArGeoHec/HEC2WheelConstruction.h | 39 + .../LArGeoHec/HECClampConstruction.h | 45 ++ .../LArGeoHec/HECModuleConstruction.h | 42 ++ .../LArGeoHec/HECWheelConstruction.h | 45 ++ .../LArGeoModel/LArGeoHec/cmt/requirements | 22 + .../LArGeoModel/LArGeoHec/doc/MainPage.h | 19 + .../LArGeoHec/src/HEC2WheelConstruction.cxx | 260 +++++++ .../LArGeoHec/src/HECClampConstruction.cxx | 459 ++++++++++++ .../LArGeoHec/src/HECModuleConstruction.cxx | 706 ++++++++++++++++++ .../LArGeoHec/src/HECWheelConstruction.cxx | 283 +++++++ 11 files changed, 1927 insertions(+) create mode 100755 LArCalorimeter/LArGeoModel/LArGeoHec/GNUmakefile create mode 100755 LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HEC2WheelConstruction.h create mode 100755 LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECClampConstruction.h create mode 100755 LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECModuleConstruction.h create mode 100755 LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECWheelConstruction.h create mode 100755 LArCalorimeter/LArGeoModel/LArGeoHec/cmt/requirements create mode 100644 LArCalorimeter/LArGeoModel/LArGeoHec/doc/MainPage.h create mode 100755 LArCalorimeter/LArGeoModel/LArGeoHec/src/HEC2WheelConstruction.cxx create mode 100755 LArCalorimeter/LArGeoModel/LArGeoHec/src/HECClampConstruction.cxx create mode 100755 LArCalorimeter/LArGeoModel/LArGeoHec/src/HECModuleConstruction.cxx create mode 100755 LArCalorimeter/LArGeoModel/LArGeoHec/src/HECWheelConstruction.cxx diff --git a/LArCalorimeter/LArGeoModel/LArGeoHec/GNUmakefile b/LArCalorimeter/LArGeoModel/LArGeoHec/GNUmakefile new file mode 100755 index 00000000000..a577fb56798 --- /dev/null +++ b/LArCalorimeter/LArGeoModel/LArGeoHec/GNUmakefile @@ -0,0 +1,7 @@ +# Packages needed to compile this one: + +PACKAGES := DetectorDescription/GeoModel/GeoModelKernel +PACKAGES += LArCalorimeter/LArGeoModel/LArGeoCode + +# Standardized compilation commands. +include $(MAKEPACKAGE) diff --git a/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HEC2WheelConstruction.h b/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HEC2WheelConstruction.h new file mode 100755 index 00000000000..1a9d302317e --- /dev/null +++ b/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HEC2WheelConstruction.h @@ -0,0 +1,39 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file HEC2WheelConstruction.h + * + * @brief Declaration of HEC2WheelConstruction class + * + * $Id: HEC2WheelConstruction.h,v 1.2 2007-11-27 20:02:16 fincke Exp $ + */ +#ifndef __HEC2WheelConstruction_H__ +#define __HEC2WheelConstruction_H__ + +class GeoFullPhysVol; + +namespace LArGeo +{ + /** @class LArGeo::HEC2WheelConstruction + @brief GeoModel description of LAr HEC + + The geometry is built and placed within HEC envelope which is implemented + by LArGeoEndcap. + */ + class HEC2WheelConstruction + { + public: + HEC2WheelConstruction(); + virtual ~HEC2WheelConstruction(); + // Get the envelope containing this detector. + GeoFullPhysVol* GetEnvelope(bool fullGeo, bool posZSide=true); + + private: + GeoFullPhysVol* m_physiHEC; + bool m_posZSide; + }; + +} +#endif // __HEC2WheelConstruction_H__ diff --git a/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECClampConstruction.h b/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECClampConstruction.h new file mode 100755 index 00000000000..fa44c4e9823 --- /dev/null +++ b/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECClampConstruction.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// HECClampConstruction.h +// +// Construct Outer Conneting Bars and Rails for HEC +// and apply them +// +// M. Fincke 25.Oct2007 +// +#ifndef __HECClampConstruction_H__ +#define __HECClampConstruction_H__ + +#include <string> + +class GeoFullPhysVol; +class GeoPhysVol; + +namespace LArGeo +{ + + class HECClampConstruction + { + public: + HECClampConstruction(bool front=true, bool posZSide=true); + virtual ~HECClampConstruction(); + void AddClamps(GeoFullPhysVol*physiHECWheel); + + + private: + GeoPhysVol* GetClampingBar(bool rail=false,bool left=false); + bool m_front; + bool m_rail; + bool m_left; + bool m_posZSide; + int m_moduleNumber ; + double m_moduleRouter ; + double m_modulePhistart ; + double m_rOuter ; + double m_moduleDeltaPhi ; + }; + +} +#endif // __HECClampConstruction_H__ diff --git a/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECModuleConstruction.h b/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECModuleConstruction.h new file mode 100755 index 00000000000..799c7911f8f --- /dev/null +++ b/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECModuleConstruction.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file HECModuleConstruction.h + * + * @brief Declaration of HECModuleConstruction class + * + * $Id: HECModuleConstruction.h,v 1.1 2007-10-09 16:43:20 fincke Exp $ + */ +#ifndef __HECModuleConstruction_H__ +#define __HECModuleConstruction_H__ + +class GeoFullPhysVol; + +namespace LArGeo +{ + /** @class LArGeo::HECModuleConstruction + @brief GeoModel description of LAr HECModule + + The geometry is built and placed within HECModule envelope which is implemented + by LArGeoEndcap. + */ + class HECModuleConstruction + { + public: + HECModuleConstruction(bool threeBoards=false, bool frontWheel=true, bool tb=false, int tbyear=2002); + virtual ~HECModuleConstruction(); + // Get the envelope containing this detector. + GeoFullPhysVol* GetEnvelope(); + + private: + GeoFullPhysVol* m_physiHECModule; + bool m_threeBoards; + bool m_frontWheel; + bool m_tb; + int m_tbyear; + }; + +} +#endif // __HECModuleConstruction_H__ diff --git a/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECWheelConstruction.h b/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECWheelConstruction.h new file mode 100755 index 00000000000..360a58ccf49 --- /dev/null +++ b/LArCalorimeter/LArGeoModel/LArGeoHec/LArGeoHec/HECWheelConstruction.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// HECWheelConstruction.h +// +// Construct an Atlas HEC Wheel (Front or Rear) +// +// Oct 2007 M. Fincke +// + +#ifndef __HECWheelConstruction_H__ +#define __HECWheelConstruction_H__ + +#include <string> + +class GeoFullPhysVol; + +namespace LArGeo +{ + + class HECWheelConstruction + { + public: + HECWheelConstruction(bool fullGeo, std::string wheelType="front", bool threeBoards=false, bool posZSide=true); + virtual ~HECWheelConstruction(); + + // Get the envelope containing this detector. + GeoFullPhysVol* GetEnvelope(); + + private: + GeoFullPhysVol* m_physiHECWheel; + bool m_posZSide; + bool m_rail; + bool m_left; + bool m_threeBoards; + bool m_frontWheel; + std::string m_wheelType; + double m_clampLength; + double m_clampAngle; + bool m_fullGeo; // true->FULL, false->RECO + }; + +} +#endif // __HECWheelConstruction_H__ diff --git a/LArCalorimeter/LArGeoModel/LArGeoHec/cmt/requirements b/LArCalorimeter/LArGeoModel/LArGeoHec/cmt/requirements new file mode 100755 index 00000000000..1f86956925c --- /dev/null +++ b/LArCalorimeter/LArGeoModel/LArGeoHec/cmt/requirements @@ -0,0 +1,22 @@ +package LArGeoHec + +author Pavol Stavina <stavina@mppmu.mpg.de> + +# This package defines the geometry for the ATLAS liquid-argon +# hadronic endcap calorimeter. + +use AtlasPolicy AtlasPolicy-* + +# Build the library (and export the headers) +library LArGeoHec *.cxx +apply_pattern installed_library + +private +use AthenaKernel AthenaKernel-* Control +use StoreGate StoreGate-* Control +use AtlasCLHEP AtlasCLHEP-* External +use GaudiInterface GaudiInterface-* External +use GeoModelKernel GeoModelKernel-* DetectorDescription/GeoModel +use RDBAccessSvc RDBAccessSvc-* Database/AthenaPOOL +use GeoModelInterfaces GeoModelInterfaces-* DetectorDescription/GeoModel +use GeoModelUtilities GeoModelUtilities-* DetectorDescription/GeoModel \ No newline at end of file diff --git a/LArCalorimeter/LArGeoModel/LArGeoHec/doc/MainPage.h b/LArCalorimeter/LArGeoModel/LArGeoHec/doc/MainPage.h new file mode 100644 index 00000000000..f885a380e71 --- /dev/null +++ b/LArCalorimeter/LArGeoModel/LArGeoHec/doc/MainPage.h @@ -0,0 +1,19 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + + +@mainpage + +GeoModel description of LAr HEC + +-------------------------------- + REQUIREMENTS +-------------------------------- + +@include requirements +@htmlinclude used_packages.html + +*/ diff --git a/LArCalorimeter/LArGeoModel/LArGeoHec/src/HEC2WheelConstruction.cxx b/LArCalorimeter/LArGeoModel/LArGeoHec/src/HEC2WheelConstruction.cxx new file mode 100755 index 00000000000..8bfa24300be --- /dev/null +++ b/LArCalorimeter/LArGeoModel/LArGeoHec/src/HEC2WheelConstruction.cxx @@ -0,0 +1,260 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +///////////////////////////////////////////////////////////////////// +// HEC2WheelConstruction.cxx +// +// This should only be TEMPORARY! +// It is a way of placing the individual HEC Wheels into the Endcap cryostat. +// (Needs a modificatio in LArGeoEndcap/EndcpcrypstatConstruction, where +// the present HECConstruction get the old HEC; replace HECConstruction by +// HEC2WheelConstruction there and you should get this construciotnof 2 separate wheels.) +// What we really want is placing the HEC wheels individually into the Endcap cryostat. +// +// When placing the wheel we have to take into account that they are fastened +// to the cryostat at their rear ends. +// This means that, longitudinally, they will shrink from front to back as the cryostat +// cools down. +// The number given in the database at the moment (Oct 2007) are still the warm +// dimensions!... +// +// In here, use hard coded numbers for the placement (outch!....) +// but then this is hopefully only very, very temporary!!!! +// +// mgf. +// +///////////////////////////////////////////////////////////////////// +#include "LArGeoHec/HEC2WheelConstruction.h" +#include "LArGeoHec/HECWheelConstruction.h" + +#include "GeoModelKernel/GeoElement.h" +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoVPhysVol.h" +#include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoPcon.h" +#include "GeoModelKernel/GeoTubs.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoTransform.h" +#include "GeoModelKernel/GeoAlignableTransform.h" +#include "GeoModelKernel/GeoIdentifierTag.h" +#include "GeoModelKernel/GeoSerialTransformer.h" +#include "GeoModelKernel/GeoSerialIdentifier.h" +#include "GeoModelKernel/GeoXF.h" +#include "CLHEP/Geometry/Transform3D.h" +#include "CLHEP/Vector/Rotation.h" +#include "CLHEP/Units/PhysicalConstants.h" +#include "CLHEP/GenericFunctions/Variable.hh" +#include "StoreGate/StoreGateSvc.h" +#include "StoreGate/DataHandle.h" +#include "GeoModelInterfaces/AbsMaterialManager.h" +#include "GeoModelInterfaces/StoredMaterialManager.h" +#include "GeoModelUtilities/StoredPhysVol.h" +#include "GeoModelUtilities/StoredAlignX.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/Bootstrap.h" +#include "AthenaKernel/getMessageSvc.h" + +#include "GeoModelUtilities/GeoDBUtils.h" +#include "RDBAccessSvc/IRDBAccessSvc.h" +#include "RDBAccessSvc/IRDBRecord.h" +#include "RDBAccessSvc/IRDBRecordset.h" +//#include "RDBAccessSvc/IRDBQuery.h" +#include "GeoModelInterfaces/IGeoModelSvc.h" + +#include <string> +#include <cmath> +#include <iostream> + + +using CLHEP::cm; +using CLHEP::mm; +using CLHEP::deg; +using HepGeom::Transform3D; +using HepGeom::Translate3D; + + +//Constructor +LArGeo::HEC2WheelConstruction::HEC2WheelConstruction(): + m_physiHEC(0), + m_posZSide(false) +{ + +} + +//~Destructor +LArGeo::HEC2WheelConstruction::~HEC2WheelConstruction() +{;} + + +GeoFullPhysVol* LArGeo::HEC2WheelConstruction::GetEnvelope(bool fullGeo, bool posZSide) +{ + m_posZSide = posZSide; + + if(m_physiHEC) return m_physiHEC->clone(); + + // Get access to the material manager: + + ISvcLocator *svcLocator = Gaudi::svcLocator(); + + MsgStream log(Athena::getMessageSvc(),"HEC2WheelConstruction " ); + + + log << MSG::DEBUG << "+++++++++++++++++++++++++++++++++++++++++++++++++++++" << endreq; + log << MSG::DEBUG << "+ +" << endreq; + log << MSG::DEBUG << "+ Start of HEC2Wheel GeoModel definition +" << endreq; + log << MSG::DEBUG << "+ +" << endreq; + log << MSG::DEBUG << "+++++++++++++++++++++++++++++++++++++++++++++++++++++" << endreq; + + + StoreGateSvc *detStore; + if (svcLocator->service("DetectorStore", detStore, false )==StatusCode::FAILURE) { + throw std::runtime_error("Error in HEC2WheelConstruction, cannot access DetectorStore"); + } + + DataHandle<StoredMaterialManager> materialManager; + if (StatusCode::SUCCESS != detStore->retrieve(materialManager, std::string("MATERIALS"))) { + throw std::runtime_error("Error in HEC2WheelConstruction, cannot access Material Manager"); + } + + StatusCode sc; + IRDBAccessSvc *pAccessSvc; + sc=svcLocator->service("RDBAccessSvc",pAccessSvc); + if (sc != StatusCode::SUCCESS) { + throw std::runtime_error ("Cannot locate RDBAccessSvc!!"); + } + + IGeoModelSvc *geoModel; + sc = svcLocator->service ("GeoModelSvc",geoModel); + if (sc != StatusCode::SUCCESS) { + throw std::runtime_error ("Cannot locate GeoModelSvc!!"); + } + + std::string AtlasVersion = geoModel->atlasVersion(); + std::string LArVersion = geoModel->LAr_VersionOverride(); + std::string detectorKey = LArVersion.empty() ? AtlasVersion : LArVersion; + std::string detectorNode = LArVersion.empty() ? "ATLAS" : "LAr"; + + IRDBRecordset_ptr hadronicEndcap = pAccessSvc->getRecordsetPtr("HadronicEndcap",detectorKey, detectorNode); + if(hadronicEndcap->size()>0) + log << MSG::ALWAYS << "Using numbers from HadronicEndcap tag: " << hadronicEndcap->tagName() << endreq; + else + throw std::runtime_error("Error in HECConstruction: hadronicEendcap not found"); + + IRDBRecordset_ptr hecLongitudinalBlock = pAccessSvc->getRecordsetPtr("HecLongitudinalBlock",detectorKey, detectorNode); + if(hecLongitudinalBlock->size()>0) + log << MSG::ALWAYS << "Using numbers from HecLongitudinalBlock tag: " << hecLongitudinalBlock->tagName() << endreq; + else + throw std::runtime_error("Error in HECConstruction: hecLongitudinalBlock not found"); + + IRDBRecordset_ptr larPosition = pAccessSvc->getRecordsetPtr("LArPosition",detectorKey, detectorNode); + if (larPosition->size()==0 ) { + larPosition = pAccessSvc->getRecordsetPtr("LArPosition", "LArPosition-00"); + if (larPosition->size()==0 ) { + throw std::runtime_error("Error, no lar position table in database!"); + } + } + + // This is a start for letting everyhting go cold (shrinkCold = 1.0 means warm; = 0.997 means cold) + double shrinkCold = 1.0 ; + + double rInner1 = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMN")*cm; + double rInner2 = shrinkCold * (*hecLongitudinalBlock)[1]->getDouble("BLRMN")*cm; + double rOuter = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMX")*cm; + double wheelGap = shrinkCold * (*hadronicEndcap)[0]->getDouble("GAPWHL")*cm; + + + GeoMaterial *LAr = materialManager->getMaterial("std::LiquidArgon"); + if (!LAr) throw std::runtime_error("Error in HEC2WheelConstruction, std::LiquidArgon is not found."); + + GeoPcon* solidHEC; //pointer to the solid HEC + const GeoLogVol* logicHEC; //pointer to the logical HEC + GeoFullPhysVol* physiHEC; //pointer to the physical HEC + + + + // YIKES! Hard-coded numbers!!! + + if (rOuter<2100.*mm) rOuter = shrinkCold *2130*mm; // Needs fixing in database to make room for HEC Clamping bars! + // Caution: We'll need 2 Routers - One for Wheel, one for Module! + + double HEC1length = shrinkCold * 816.5*mm; + double HEC2length = shrinkCold * 961.0*mm; + double TotalWarmHEC = HEC1length + wheelGap + HEC2length ; // For the moment, this defines the HEC rear face + double TotalHECLength = TotalWarmHEC; // (where is that -cold- in the cryostat? + + double zCoordinate[4]; + zCoordinate[0]=shrinkCold * 0.0*cm; + zCoordinate[1]=shrinkCold * 28.05*cm; + zCoordinate[2]=shrinkCold * 28.051*cm; + zCoordinate[3]=shrinkCold * (181.9*cm+4.0*mm); // JFB, MGF: more room in the mother fiducal volume for misalignment. + // 37.2, 47.5, 203 cm for R + + solidHEC = new GeoPcon(0., 2.*M_PI); + for (int i=0; i< 4; i++) + { + if (i<2) solidHEC->addPlane(zCoordinate[i],rInner1 - shrinkCold*1.*mm,rOuter); + else solidHEC->addPlane(zCoordinate[i],rInner2 - shrinkCold*1.*mm,rOuter); + } + + std::string hecName = "LAr::HEC::Mother"; + logicHEC = new GeoLogVol(hecName, solidHEC , LAr); + physiHEC = new GeoFullPhysVol(logicHEC); + + //--- Make the Front Wheel alignable: + + const IRDBRecord *posHec1 = GeoDBUtils::getTransformRecord(larPosition, m_posZSide ? "HEC1_POS":"HEC1_NEG"); + Transform3D xfPosHec1 = posHec1 ? GeoDBUtils::getTransform(posHec1) : Translate3D(0.,0.,0.); + GeoAlignableTransform *xfHec1 = new GeoAlignableTransform(xfPosHec1); + + std::string tag1 = m_posZSide? std::string("HEC1_POS") : std::string("HEC1_NEG"); + + HECWheelConstruction theFrontHEC(fullGeo,"front",false,m_posZSide) ; + GeoFullPhysVol* EnvelopeF = theFrontHEC.GetEnvelope(); + + StoredPhysVol *sPhysVolHec1 = new StoredPhysVol(EnvelopeF); + sc=detStore->record(sPhysVolHec1,tag1); + if(!sc.isSuccess()) throw std::runtime_error ((std::string("Cannot store")+tag1).c_str()); + + StoredAlignX *sAlignX1 = new StoredAlignX(xfHec1); + sc=detStore->record(sAlignX1,tag1); + if(!sc.isSuccess()) throw std::runtime_error ((std::string("Cannot store")+tag1).c_str()); + + physiHEC->add(xfHec1); + physiHEC->add(new GeoIdentifierTag(0)); + physiHEC->add(EnvelopeF); + + //--- Now the Rear Wheel: + + double Zpos = TotalHECLength - HEC2length ; // It is fixed at its end; position it from there. + const IRDBRecord *posHec2 = GeoDBUtils::getTransformRecord(larPosition, m_posZSide ? "HEC2_POS":"HEC2_NEG"); + Transform3D xfPosHec2 = posHec2 ? GeoDBUtils::getTransform(posHec2):Translate3D(0.,0.,Zpos); + + + GeoAlignableTransform *xfHec2 = new GeoAlignableTransform(xfPosHec2); + + std::string tag2 = m_posZSide? std::string("HEC2_POS") : std::string("HEC2_NEG"); + + HECWheelConstruction theRearHEC(fullGeo,"rear",false,m_posZSide); + GeoFullPhysVol* EnvelopeR = theRearHEC.GetEnvelope(); + + StoredPhysVol *sPhysVolHec2 = new StoredPhysVol(EnvelopeR); + sc=detStore->record(sPhysVolHec2,tag2); + if(!sc.isSuccess()) throw std::runtime_error ((std::string("Cannot store")+tag2).c_str()); + + StoredAlignX *sAlignX2 = new StoredAlignX(xfHec2); + sc=detStore->record(sAlignX2,tag2); + if(!sc.isSuccess()) throw std::runtime_error ((std::string("Cannot store")+tag2).c_str()); + + physiHEC->add(xfHec2); + physiHEC->add(new GeoIdentifierTag(1)); + physiHEC->add(EnvelopeR); + + + + + + return physiHEC; +} diff --git a/LArCalorimeter/LArGeoModel/LArGeoHec/src/HECClampConstruction.cxx b/LArCalorimeter/LArGeoModel/LArGeoHec/src/HECClampConstruction.cxx new file mode 100755 index 00000000000..7ff83f528d7 --- /dev/null +++ b/LArCalorimeter/LArGeoModel/LArGeoHec/src/HECClampConstruction.cxx @@ -0,0 +1,459 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// HECClampConstruction.cxx 1.0.0 +// +// GetClampingBar: +// Construct Outer Connecting Bars and Support Rails for the +// HEC Wheels (Front or Rear) +// AddClamps: +// Places the Bars and Rails on the HEC Wheel +// +// 25. Oct 2007 M. Fincke-Keeler +// +//==================================================================== +#include "LArGeoHec/HECClampConstruction.h" +#include "LArGeoHec/HECModuleConstruction.h" + +#include "GeoModelKernel/GeoElement.h" +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoVPhysVol.h" +#include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoPcon.h" +#include "GeoModelKernel/GeoTubs.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoTransform.h" +#include "GeoModelKernel/GeoAlignableTransform.h" +#include "GeoModelKernel/GeoIdentifierTag.h" +#include "GeoModelKernel/GeoSerialTransformer.h" +#include "GeoModelKernel/GeoSerialIdentifier.h" +#include "GeoModelKernel/GeoXF.h" +#include "CLHEP/Geometry/Transform3D.h" +#include "CLHEP/Vector/Rotation.h" +#include "CLHEP/Units/PhysicalConstants.h" +#include "CLHEP/GenericFunctions/Variable.hh" +#include "StoreGate/StoreGateSvc.h" +#include "StoreGate/DataHandle.h" +#include "GeoModelInterfaces/AbsMaterialManager.h" +#include "GeoModelInterfaces/StoredMaterialManager.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/Bootstrap.h" +#include "AthenaKernel/getMessageSvc.h" + + +#include "RDBAccessSvc/IRDBAccessSvc.h" +#include "RDBAccessSvc/IRDBRecord.h" +#include "RDBAccessSvc/IRDBRecordset.h" +#include "GeoModelInterfaces/IGeoModelSvc.h" + +#include <string> +#include <cmath> +#include <iostream> + +using CLHEP::cm; +using CLHEP::mm; +using CLHEP::deg; +using HepGeom::RotateZ3D; +using HepGeom::Translate3D; +using HepGeom::TranslateZ3D; + + +//Constructor +LArGeo::HECClampConstruction::HECClampConstruction(bool front, bool posZSide) + : m_rail(false), + m_left(false), + m_moduleNumber(0), + m_moduleRouter(0), + m_modulePhistart(0), + m_rOuter(0), + m_moduleDeltaPhi(0) +{ + m_front = front; + m_posZSide = posZSide; +} + +//~Destructor +LArGeo::HECClampConstruction::~HECClampConstruction() +{ +} + + +GeoPhysVol* LArGeo::HECClampConstruction::GetClampingBar(bool rail,bool left) +{ + + ISvcLocator *svcLocator = Gaudi::svcLocator(); + + MsgStream log(Athena::getMessageSvc(),"HECClampConstruction " ); + log << MSG::DEBUG << " In HECClampConstruction " << endreq; + + + StoreGateSvc *detStore; + if (svcLocator->service("DetectorStore", detStore, false )==StatusCode::FAILURE) { + throw std::runtime_error("Error in HECModuleConstruction(ClampBar), cannot access DetectorStore"); + } + + + // Get access to the material manager: + DataHandle<StoredMaterialManager> materialManager; + if (StatusCode::SUCCESS != detStore->retrieve(materialManager, std::string("MATERIALS"))) { + throw std::runtime_error("Error in HECModuleConstruction(ClampBar), cannot access Material Manager"); + } + GeoMaterial *LAr = materialManager->getMaterial("std::LiquidArgon"); + if (!LAr) throw std::runtime_error("Error in HECModuleConstruction(ClampBar), std::LiquidArgon is not found."); + GeoMaterial *Iron = materialManager->getMaterial("std::Iron"); + if (!Iron) throw std::runtime_error("Error in HECModuleConstruction(ClampBar), std::Iron is not found."); + + + StatusCode sc; + IRDBAccessSvc *pAccessSvc; + sc=svcLocator->service("RDBAccessSvc",pAccessSvc); + if (sc != StatusCode::SUCCESS) { + throw std::runtime_error ("Cannot locate RDBAccessSvc!!"); + } + + IGeoModelSvc *geoModel; + sc = svcLocator->service ("GeoModelSvc",geoModel); + if (sc != StatusCode::SUCCESS) { + throw std::runtime_error ("Cannot locate GeoModelSvc!!"); + } + + std::string AtlasVersion = geoModel->atlasVersion(); + std::string LArVersion = geoModel->LAr_VersionOverride(); + + std::string detectorKey = LArVersion.empty() ? AtlasVersion : LArVersion; + std::string detectorNode = LArVersion.empty() ? "ATLAS" : "LAr"; + + IRDBRecordset_ptr hecLongitudinalBlock = pAccessSvc->getRecordsetPtr("HecLongitudinalBlock",detectorKey, detectorNode); + IRDBRecordset_ptr hadronicEndcap = pAccessSvc->getRecordsetPtr("HadronicEndcap",detectorKey, detectorNode); + + + //---------------------------------------------------------------- + // Collect all the numbers we need from the database: + //---------------------------------------------------------------- + // + // NOT READY YET + // + + //---------------------------------------------------------------- + // Add outer clamping bars for Atlas wheels + //---------------------------------------------------------------- + // NB.: The outer clamping bars have notches for the HEC cables. + // that sit at different levels for Front/Rear Wheel + // + double shrinkCold = 1.0; // thermal expansion factor: 1.0 = warm + + int moduleNumber = (*hadronicEndcap)[0]->getInt("NSCT"); + double moduleRouter = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMX")*cm; + double modulePhistart = 264.375*deg; // (270.-11.25/2.)*deg + double rOuter = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMX")*cm; + double moduleDeltaPhi = 2*M_PI/moduleNumber; //11.25*deg; + m_moduleNumber = moduleNumber; + m_moduleRouter = moduleRouter; + m_modulePhistart= modulePhistart; + m_rOuter = rOuter; + m_moduleDeltaPhi= moduleDeltaPhi ; + + std::string clampName = "LAr::HEC::Clamp"; + std::string larName = "LAr::HEC::Clamp::LiquidArgon"; + double g4allow = 0.01 *mm; + double extThick = shrinkCold * 37.*mm; + double extLength = shrinkCold * 84.*mm; + double clampWidth = shrinkCold * 147.0 *mm; + double clampThick = shrinkCold * 50.*mm; + double notchLevel = shrinkCold * 25.*mm; + double notchHeight = shrinkCold * 15.*mm; + double notchWidth = shrinkCold * 20.*mm; + double slotWidth = shrinkCold * 20.*mm; + double clampLength = shrinkCold * 815.*mm; + double clampAngle = 2.* asin(clampWidth/(2.*(moduleRouter+clampThick/2.))); + double slotAngle = 2.* asin(notchWidth/(2.*(moduleRouter+clampThick/2.))); + + std::vector<double> notchLocation; + if (m_front){ + if (!rail){ +// notchLocation.push_back(shrinkCold * 201.*mm); +// notchLocation.push_back(shrinkCold * 469.*mm); +// notchLocation.push_back(shrinkCold * 737.*mm); + notchLocation.push_back(shrinkCold * 200.*mm); // adjust for shortened clamp + notchLocation.push_back(shrinkCold * 468.*mm); + notchLocation.push_back(shrinkCold * 736.*mm); + } + else { +// notchLocation.push_back(shrinkCold * 206.*mm); +// notchLocation.push_back(shrinkCold * 474.*mm); +// notchLocation.push_back(shrinkCold * 742.*mm); + notchLocation.push_back(shrinkCold * 201.*mm); // adjust for shortened rail + notchLocation.push_back(shrinkCold * 469.*mm); + notchLocation.push_back(shrinkCold * 737.*mm); + clampWidth = shrinkCold * 148.5 *mm; + clampThick = shrinkCold * 98.*mm; // 98.*mm (this is the total overall rail thickness) + clampLength = shrinkCold * 815.*mm; + } + } + else { + if (!rail){ +// notchLocation.push_back(shrinkCold * 364.0*mm); +// notchLocation.push_back(shrinkCold * 832.0*mm); + notchLocation.push_back(shrinkCold * 363.0*mm); // adjust for shortened clamp + notchLocation.push_back(shrinkCold * 831.0*mm); + clampLength = shrinkCold * 960.*mm; + } + else { +// notchLocation.push_back(shrinkCold * 372.5*mm); +// notchLocation.push_back(shrinkCold * 840.5*mm); + notchLocation.push_back(shrinkCold * 364.*mm); // adjust for shortened rail + notchLocation.push_back(shrinkCold * 832.*mm); + clampWidth = shrinkCold * 148.5 *mm; + clampThick = shrinkCold * 98.*mm; + clampLength = shrinkCold * 960.*mm; + extLength = shrinkCold * 132.*mm; + } + notchWidth = shrinkCold * 16.*mm; + notchHeight = shrinkCold * 16.*mm; + notchLevel = shrinkCold * 0.*mm; + } + + + + + // Construct the the slots and notches here. For the support rails, they have to be inserted + // into the physExt[0] volume. For the regular clamps they go into physClamp. + GeoTubs* clampExt[3]; + const GeoLogVol* logExt[3]; + GeoPhysVol* physExt[3]; + + GeoTubs* Notch = new GeoTubs(moduleRouter+notchLevel+g4allow, moduleRouter+notchLevel+notchHeight-g4allow, + notchWidth/2., + modulePhistart-(clampAngle/2.) , clampAngle); + const GeoLogVol* logNotch = new GeoLogVol(larName, Notch, LAr); + GeoPhysVol* physiNotch = new GeoPhysVol(logNotch); + + GeoTubs* Slot = new GeoTubs(moduleRouter+g4allow, moduleRouter+notchLevel-g4allow, slotWidth/2. , + modulePhistart-(slotAngle/2.) , slotAngle); + const GeoLogVol* logSlot = new GeoLogVol(larName, Slot, LAr); + GeoPhysVol* physiSlot = new GeoPhysVol(logSlot); + + + + GeoTubs* clampBar; + const GeoLogVol* logClamp; + GeoPhysVol* physClamp; + + if(!rail){ + clampBar = new GeoTubs(moduleRouter, moduleRouter+clampThick, clampLength/2. , + modulePhistart-(clampAngle/2.) , clampAngle); + logClamp = new GeoLogVol(clampName, clampBar, Iron); + physClamp= new GeoPhysVol(logClamp); + } + else{ + + //For the support rails, make the mother LAr and the place the steel inside: + + clampBar = new GeoTubs(moduleRouter, moduleRouter+clampThick, clampLength/2. , + modulePhistart-(clampAngle/2.) , clampAngle); + logClamp = new GeoLogVol(larName, clampBar, LAr); + physClamp= new GeoPhysVol(logClamp); + + + clampExt[0] = new GeoTubs(moduleRouter+g4allow, moduleRouter+clampThick-extThick, + clampLength/2. , modulePhistart-(clampAngle/2.), clampAngle); + clampExt[1] = new GeoTubs(moduleRouter+clampThick-extThick+g4allow, moduleRouter+clampThick-g4allow, + clampLength/2. , modulePhistart, clampAngle/2.); + clampExt[2] = new GeoTubs(moduleRouter+clampThick-extThick+g4allow, moduleRouter+clampThick-g4allow, + extLength/2. , modulePhistart, clampAngle/2.); + + + + + for (int iext=0; iext<3; iext++){ + + logExt[iext] = new GeoLogVol(clampName, clampExt[iext], Iron); + physExt[iext]= new GeoPhysVol(logExt[iext]); + + + if (iext==0) { + for ( unsigned int i = 0; i < notchLocation.size(); i++ ) + { + physExt[0]->add( new GeoIdentifierTag(i) ); + physExt[0]->add( new GeoTransform(Translate3D(0,0,-clampLength/2.+notchLocation[i])) ); + physExt[0]->add( physiNotch ); + if (m_front){ + physExt[0]->add( new GeoIdentifierTag(i) ); + physExt[0]->add( new GeoTransform(Translate3D(0,0,-clampLength/2.+notchLocation[i])) ); + physExt[0]->add( physiSlot ); + } + } + } + + + if (iext==1 && !left) physClamp->add(new GeoTransform(RotateZ3D(-clampAngle/2.))); + else if(iext==2 && left) physClamp->add(new GeoTransform(TranslateZ3D((clampLength-extLength)/2.) + *RotateZ3D(-clampAngle/2.))); + else if(iext==2) physClamp->add(new GeoTransform(TranslateZ3D((clampLength-extLength)/2.) + *RotateZ3D( 0.))); + + if (left) physClamp->add( new GeoIdentifierTag(16) ); + else physClamp->add( new GeoIdentifierTag(32) ); + + + physClamp->add(physExt[iext]); + + } + + + for (int i=0; i<3; i++){ + clampExt[i]->ref(); clampExt[i]->unref(); + logExt[i]->ref(); logExt[i]->unref(); + physExt[i]->ref(); physExt[i]->unref(); + } + + } + + + for ( unsigned int i = 0; i < notchLocation.size(); i++ ) + { + if(!rail){ + physClamp->add( new GeoIdentifierTag(i) ); + physClamp->add( new GeoTransform(Translate3D(0,0,-clampLength/2.+notchLocation[i])) ); + physClamp->add( physiNotch ); + } + } + + if(m_front) + { + for ( unsigned int i = 0; i < notchLocation.size(); i++ ) + { + if(!rail){ + physClamp->add( new GeoIdentifierTag(i) ); + physClamp->add( new GeoTransform(Translate3D(0,0,-clampLength/2.+notchLocation[i])) ); + physClamp->add( physiSlot ); + } + } + + } + + + + Slot->ref(); Slot->unref(); + logSlot->ref(); logSlot->unref(); + physiSlot->ref(); physiSlot->unref(); + clampBar->ref(); clampBar->unref(); + logClamp->ref(); logClamp->unref(); + Notch->ref(); Notch->unref(); + logNotch->ref(); logNotch->unref(); + physiNotch->ref(); physiNotch->unref(); + + + return physClamp; +} + + + +void LArGeo::HECClampConstruction::AddClamps(GeoFullPhysVol* physiHECWheel) +{ + //---------------------------------------------------------------- + // Add Outer Connecting Bars to HEC Wheel + //---------------------------------------------------------------- + + double shrinkCold = 1.0 ; // thermal expansion factor: 1.0 = warm + + std::string clampName = "LAr::HEC::Clamp"; + std::string larName = "LAr::HEC::Clamp::LiquidArgon"; + double clampLength = shrinkCold * 815.*mm; + double railLength = shrinkCold * 815.*mm; + double railOffset = shrinkCold * 0.*mm; + if (!m_front) { + clampLength = shrinkCold * 960.*mm; + railLength = shrinkCold * 960.*mm; + railOffset = shrinkCold * 0.*mm; + } + + GeoVPhysVol* clampingBar = GetClampingBar(false,false); + GeoVPhysVol* clampingRailR = GetClampingBar(true,false); + GeoVPhysVol* clampingRailL = GetClampingBar(true,true); + + + + // In the below positioning sequence, the ORDER MATTERS! + // + + GeoTransform *xt = new GeoTransform(TranslateZ3D(clampLength/2.)); + physiHECWheel->add(xt); + + GeoSerialIdentifier *sIC = new GeoSerialIdentifier(0); + Genfun::Variable IndexC; + + if (m_posZSide) + { + Genfun::GENFUNCTION ModuleRotationAngleC = -m_modulePhistart+m_moduleDeltaPhi + m_moduleDeltaPhi*IndexC; + GeoXF::TRANSFUNCTION tC = GeoXF::Pow(RotateZ3D(1.0),ModuleRotationAngleC); + GeoSerialTransformer *sTC = new GeoSerialTransformer (clampingBar,&tC,((m_moduleNumber/2)-1)); + physiHECWheel->add(sIC); + physiHECWheel->add(sTC); + sTC->ref(); sTC->unref(); + } + else + { + Genfun::GENFUNCTION ModuleRotationAngleC = -m_modulePhistart-m_moduleDeltaPhi+180*deg - m_moduleDeltaPhi*IndexC; + GeoXF::TRANSFUNCTION tC = GeoXF::Pow(RotateZ3D(1.0),ModuleRotationAngleC); + GeoSerialTransformer *sTC = new GeoSerialTransformer (clampingBar,&tC,((m_moduleNumber/2)-1)); + physiHECWheel->add(sIC); + physiHECWheel->add(sTC); + sTC->ref(); sTC->unref(); + } + + + physiHECWheel->add(new GeoTransform(TranslateZ3D(railLength/2.-railOffset)*RotateZ3D(-m_modulePhistart-(180.*deg)))); + //GeoSerialIdentifier *sIR = new GeoSerialIdentifier(15); // For the pos z-side this is the position of module no.15 + //physiHECWheel->add(sIR); // No need to aplly it if we position clamps in this order + //// But for the neg z-side we do have to re-number, because the rails have sided-ness! + if (!m_posZSide) + { + GeoSerialIdentifier *sIR = new GeoSerialIdentifier(31); + physiHECWheel->add(sIR); + } + physiHECWheel->add(clampingRailL); + + + physiHECWheel->add(xt); + Genfun::Variable IndexC2; + + if (m_posZSide) + { + Genfun::GENFUNCTION ModuleRotationAngleC2 = -m_modulePhistart+m_moduleDeltaPhi-(180.*deg) + m_moduleDeltaPhi*IndexC2; + GeoXF::TRANSFUNCTION tC2 = GeoXF::Pow(RotateZ3D(1.0),ModuleRotationAngleC2); + GeoSerialTransformer *sTC2 = new GeoSerialTransformer (clampingBar,&tC2,((m_moduleNumber/2)-1)); + physiHECWheel->add(sTC2); + sTC2->ref(); sTC2->unref(); + } + else + { + Genfun::GENFUNCTION ModuleRotationAngleC2 = -m_modulePhistart-m_moduleDeltaPhi - m_moduleDeltaPhi*IndexC2; + GeoXF::TRANSFUNCTION tC2 = GeoXF::Pow(RotateZ3D(1.0),ModuleRotationAngleC2); + GeoSerialTransformer *sTC2 = new GeoSerialTransformer (clampingBar,&tC2,((m_moduleNumber/2)-1)); + physiHECWheel->add(sTC2); + sTC2->ref(); sTC2->unref(); + } + + physiHECWheel->add(new GeoTransform(TranslateZ3D(railLength/2.)*RotateZ3D(-m_modulePhistart))); + if (!m_posZSide) + { + GeoSerialIdentifier *sIR = new GeoSerialIdentifier(15); + physiHECWheel->add(sIR); + } + physiHECWheel->add(clampingRailR); + + + clampingBar->ref(); clampingBar->unref(); + clampingRailR->ref(); clampingRailR->unref(); + clampingRailL->ref(); clampingRailL->unref(); + xt->ref(); xt->unref(); + sIC->ref(); sIC->unref(); + +} + + + diff --git a/LArCalorimeter/LArGeoModel/LArGeoHec/src/HECModuleConstruction.cxx b/LArCalorimeter/LArGeoModel/LArGeoHec/src/HECModuleConstruction.cxx new file mode 100755 index 00000000000..5fdbfcf6960 --- /dev/null +++ b/LArCalorimeter/LArGeoModel/LArGeoHec/src/HECModuleConstruction.cxx @@ -0,0 +1,706 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// HECModuleConstruction.cxx 1.0.0 +// Derived from the HECConstruction - M. Fincke, Sept.2007 +// +#include "LArGeoHec/HECModuleConstruction.h" + +#include "GeoModelKernel/GeoElement.h" +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoVPhysVol.h" +#include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoPcon.h" +#include "GeoModelKernel/GeoTubs.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoTransform.h" +#include "GeoModelKernel/GeoAlignableTransform.h" +#include "GeoModelKernel/GeoIdentifierTag.h" +#include "GeoModelKernel/GeoSerialTransformer.h" +#include "GeoModelKernel/GeoSerialIdentifier.h" +#include "GeoModelKernel/GeoXF.h" +#include "CLHEP/Geometry/Transform3D.h" +#include "CLHEP/Vector/Rotation.h" +#include "CLHEP/Units/PhysicalConstants.h" +#include "CLHEP/GenericFunctions/Variable.hh" +#include "StoreGate/StoreGateSvc.h" +#include "StoreGate/DataHandle.h" +#include "GeoModelInterfaces/AbsMaterialManager.h" +#include "GeoModelInterfaces/StoredMaterialManager.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/Bootstrap.h" +#include "AthenaKernel/getMessageSvc.h" +#include "RDBAccessSvc/IRDBAccessSvc.h" +#include "RDBAccessSvc/IRDBRecord.h" +#include "RDBAccessSvc/IRDBRecordset.h" +//#include "RDBAccessSvc/IRDBQuery.h" +#include "GeoModelInterfaces/IGeoModelSvc.h" + +#include <string> +#include <cmath> +#include <iostream> + + +using CLHEP::cm; +using CLHEP::mm; +using CLHEP::deg; +using HepGeom::Translate3D; +using HepGeom::TranslateY3D; +using HepGeom::TranslateZ3D; + + +//Constructor +LArGeo::HECModuleConstruction::HECModuleConstruction(bool threeBoards, bool frontWheel, bool tb, int tbyear): + m_physiHECModule(0) +{ + m_threeBoards = threeBoards; // If true, build 3 boards in gap. Else just one thick board. + m_frontWheel = frontWheel; // If true, build a front Module. Else build a rear Module. + m_tb = tb; // If true, build a Module for testbeam. + m_tbyear = tbyear; // If testbeam, specify the testbeam year. + +// if (tb && ( tbyear!=2002 && tbyear!=2004 )) { +// throw std::runtime_error ("TESTBEAM HEC: Asking for an unsupported HEC testbeam year!!!!! "); +// } + +} + +//~Destructor +LArGeo::HECModuleConstruction::~HECModuleConstruction() +{;} + + +GeoFullPhysVol* LArGeo::HECModuleConstruction::GetEnvelope() +{ + if(m_physiHECModule) return m_physiHECModule->clone(); + + + + ISvcLocator *svcLocator = Gaudi::svcLocator(); + + MsgStream log(Athena::getMessageSvc(),"HECModuleConstruction " ); + + log << MSG::DEBUG << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endreq; + log << MSG::DEBUG << "+ +" << endreq; + log << MSG::DEBUG << "+ Start of HECModule GeoModel definition +" << endreq; + log << MSG::DEBUG << "+ +" << endreq; + log << MSG::DEBUG << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endreq; + + + StoreGateSvc *detStore; + if (svcLocator->service("DetectorStore", detStore, false )==StatusCode::FAILURE) { + throw std::runtime_error("Error in HECModuleConstruction, cannot access DetectorStore"); + } + + + DataHandle<StoredMaterialManager> materialManager; + if (StatusCode::SUCCESS != detStore->retrieve(materialManager, std::string("MATERIALS"))) { + throw std::runtime_error("Error in HECModuleConstruction, cannot access Material Manager"); + } + + GeoMaterial *LAr = materialManager->getMaterial("std::LiquidArgon"); + if (!LAr) throw std::runtime_error("Error in HECModuleConstruction, std::LiquidArgon is not found."); + + GeoMaterial *Iron = materialManager->getMaterial("std::Iron"); + if (!Iron) throw std::runtime_error("Error in HECModuleConstruction, std::Iron is not found."); + + GeoMaterial *Copper = materialManager->getMaterial("std::Copper"); + if (!Copper) throw std::runtime_error("Error in HECModuleConstruction, std::Copper is not found."); + + GeoMaterial *Kapton = materialManager->getMaterial("std::Kapton"); + if (!Kapton) throw std::runtime_error("Error in HECModuleConstruction, std::Kapton is not found."); + + + + StatusCode sc; + IRDBAccessSvc *pAccessSvc; + sc=svcLocator->service("RDBAccessSvc",pAccessSvc); + if (sc != StatusCode::SUCCESS) { + throw std::runtime_error ("Cannot locate RDBAccessSvc!!"); + } + + + IGeoModelSvc *geoModel; + sc = svcLocator->service ("GeoModelSvc",geoModel); + if (sc != StatusCode::SUCCESS) { + throw std::runtime_error ("Cannot locate GeoModelSvc!!"); + } + + std::string AtlasVersion = geoModel->atlasVersion(); + std::string LArVersion = geoModel->LAr_VersionOverride(); + + std::string detectorKey = LArVersion.empty() ? AtlasVersion : LArVersion; + std::string detectorNode = LArVersion.empty() ? "ATLAS" : "LAr"; + + IRDBRecordset_ptr hadronicEndcap = pAccessSvc->getRecordsetPtr("HadronicEndcap",detectorKey, detectorNode); + if(hadronicEndcap->size()>0) + log << MSG::DEBUG << "Using numbers from HadronicEndcap tag: " << hadronicEndcap->tagName() << endreq; + else + throw std::runtime_error("Error in HECConstruction: hadronicEendcap not found"); + + IRDBRecordset_ptr hecLongitudinalBlock = pAccessSvc->getRecordsetPtr("HecLongitudinalBlock",detectorKey, detectorNode); + if(hecLongitudinalBlock->size()>0) + log << MSG::DEBUG << "Using numbers from HecLongitudinalBlock tag: " << hecLongitudinalBlock->tagName() << endreq; + else + throw std::runtime_error("Error in HECConstruction: hecLongitudinalBlock not found"); + + //---------------------------------------------------------------- + // Collect all the numbers we need from the database: + //---------------------------------------------------------------- + + double shrinkCold = 1.0; //thermal expansion factor: 1.0 = warm geometry + //kapton is treated the same at Cu and Fe at the moment + + int moduleNumber = (*hadronicEndcap)[0]->getInt("NSCT"); + double moduleRinner1 = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMN")*cm; + double moduleRinner2 = shrinkCold * (*hecLongitudinalBlock)[1]->getDouble("BLRMN")*cm; + double moduleRouter = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMX")*cm; + if (m_tbyear==2004) moduleRouter = moduleRinner1 + 787*mm; // Mini Modules for 2004 testbeam CAUTION! Hard-coded number!!! + double copperPad = shrinkCold * (*hadronicEndcap)[0]->getDouble("COPPER")*cm; + double gapSize = shrinkCold * (*hadronicEndcap)[0]->getDouble("LARG")*cm; + double drModOverlap = shrinkCold * (*hadronicEndcap)[0]->getDouble("DRMODOVERLAP")*cm; + double kaptonWidth[2]; + kaptonWidth[0] = shrinkCold * (*hadronicEndcap)[0]->getDouble("ESTPL")*cm; + kaptonWidth[1] = shrinkCold * (*hadronicEndcap)[0]->getDouble("PADPL")*cm; + int gapN[7]; + for(int id=0;id<7;id++) gapN[id] = (int) (*hecLongitudinalBlock)[id]->getDouble("BLMOD"); + double firstFrontAbsThickness= shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("PLATE0")*cm; + double firstRearAbsThickness = shrinkCold * (*hecLongitudinalBlock)[3]->getDouble("PLATE0")*cm; + double frontAbsThickness = shrinkCold * (*hadronicEndcap)[0]->getDouble("PLATE_0")*cm; + double rearAbsThickness = shrinkCold * (*hadronicEndcap)[0]->getDouble("PLATE_1")*cm; + double tieRodPositionX[4]; + double tieRodPositionY[4]; + tieRodPositionX[0] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSX_0")*cm; + tieRodPositionY[0] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSR_0")*cm; + tieRodPositionX[1] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSX_1")*cm; + tieRodPositionY[1] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSR_1")*cm; + tieRodPositionX[2] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSX_2")*cm; + tieRodPositionY[2] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSR_2")*cm; + tieRodPositionX[3] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSX_3")*cm; + tieRodPositionY[3] = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODPOSR_3")*cm; + double tieRodDiameter = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODDIM_0")*cm; + double spacerDiameter = shrinkCold * (*hadronicEndcap)[0]->getDouble("SPCDIM_0")*cm; + double spacerDeadZone = shrinkCold * 3.0*mm; + if (!m_frontWheel) + { + tieRodDiameter = shrinkCold * (*hadronicEndcap)[0]->getDouble("RODDIM_1")*cm; + spacerDiameter = shrinkCold * (*hadronicEndcap)[0]->getDouble("SPCDIM_1")*cm; + } + + + //--- Get the right Absorber thickness and Depth number depending on Front or Rear Wheel (and TB) + // (2002 and 2004 testbeam have only 1/2 rear depth) + int depthNumber = 3; + int depthOffset = depthNumber; // need this to start rear wheel depth-number at 3 + double absThickness = frontAbsThickness; + double firstAbsThickness = firstFrontAbsThickness; + if (!m_frontWheel) { + depthNumber = 4; + if (m_tb) depthNumber= 2; + absThickness = rearAbsThickness; + firstAbsThickness = firstRearAbsThickness; + } + + + //---- Calculate the sizes of the 7 longitudinal Depths ------------------------------------- + double depthS[7]; + depthS[0] = firstFrontAbsThickness + gapN[0]*(frontAbsThickness+gapSize); + depthS[1] = gapN[1]*(frontAbsThickness+gapSize); + depthS[2] = gapN[2]*(frontAbsThickness+gapSize); + depthS[3] = firstRearAbsThickness + gapN[3]*(rearAbsThickness+gapSize); + depthS[4] = gapN[4]*(rearAbsThickness+gapSize); + depthS[5] = gapN[5]*(rearAbsThickness+gapSize); + depthS[6] = gapN[6]*(rearAbsThickness+gapSize); + + //--- From the depth Size, calculate the boundary planes of the Module Mother volume --------- + // (Add 0.1 mm to avoid clashes) + double zCoordinate[4]; + double depthSize[4]; + int gapNumber[4]; + int gaptally[4]; + double g4allow = shrinkCold * 0.1*mm ; + double g4allowS = 0.001*mm ; + if (m_frontWheel){ + zCoordinate[0] = shrinkCold * 0.0*cm; + zCoordinate[1] = depthS[0]; + zCoordinate[2] = depthS[0] + g4allow; + zCoordinate[3] = depthS[0]+depthS[1]+depthS[2] + g4allow; // End of front Module + gaptally[0]=0; + for (int i=0; i<3; i++) { + if (i>0) gaptally[i] = gaptally[i-1] + gapN[i-1]; + gapNumber[i] = gapN[i]; + depthSize[i] = depthS[i]; + } + } + else{ + zCoordinate[0] = shrinkCold * 0.0*cm; + zCoordinate[1] = depthS[3]+depthS[4]+depthS[5]+depthS[6]+g4allow; // End of rear Atlas Module + if(m_tb) zCoordinate[1]= depthS[3]+depthS[4]+g4allow; // For TB only 1/2 rear depth + gaptally[0] = 0; + for (int i=0; i<4; i++) { // Re-number the rear wheel + if (i>0) gaptally[i] =gaptally[i-1] + gapN[i+3-1]; + gapNumber[i] = gapN[i+3]; // gaps and depths to have + depthSize[i] = depthS[i+3]; // their index start at Zero. + } + } + + //--- Calculate where to put the tie-rod spacers into the available LAr gap. + // This depends on the configuration of the boards. + + // +/-ztie are the center z-coordinates of the LAr sub-gaps + // rodSize is the length of spacer to be fit into the LAr that is not occupied by boards + // Small tolerance to fit G4 volumes into one another + double ztie[2]; + double rodSize; + + //-- For Three-board approach: + if (m_threeBoards) { + double halfGap = gapSize/2.; + double halfGapLAr = (gapSize - kaptonWidth[1])/2.; + double restLAr = (halfGapLAr-kaptonWidth[0])/2. ; + ztie[0] = restLAr/2 + kaptonWidth[1]/2.; + ztie[1] = halfGap - restLAr/2.; + rodSize = restLAr - g4allowS; + } + else{ + //-- For One-board approach: + double halfGap = gapSize/2.; + double halfGapLAr = (gapSize - kaptonWidth[1])/2. - kaptonWidth[0]; + ztie[0] = (halfGap-halfGapLAr/2.); + ztie[1] = 0.0; // fix complilation warning + rodSize = halfGapLAr-g4allowS; + } + + + //---- And here we have some more (yikes!) hard-coded values: ------------------------ + int nZplane = 4; + if (!m_frontWheel) nZplane = 2; + int nRods = 4; + if (m_tbyear==2004) nRods = 2; + double modulePhistart = 264.375*deg; // (270.-11.25/2.)*deg + double moduleDeltaPhi = 2*M_PI/moduleNumber; //11.25*deg; + int sectMax = 2; + if(!m_frontWheel) sectMax = 1; + int rearOffset = 24; // The rear wheel slice numbering starts at 24 + // This complies with the old HECConstruction. + + //--- A dead-zone in the LAr gap of depth deadZone all around the module + // requires a radial shift of size larshift + double deadZone = shrinkCold * 3.*mm; + double larShift = deadZone / sin(moduleDeltaPhi/2.); + + //--- To create a (dead) inter-module gap of 2mm (i.e. 1mm on either side of each module) + // between the absorbers, use a radial shift of -1.02*cm. + // This does that: + double deadGap = shrinkCold * 1.*mm; + double radialShift = deadGap / sin(moduleDeltaPhi/2.); + + + + + + //-------------------------------------------------------------------// + //-------------------------------------------------------------------// + // Now start building the Module geometry // + // First create all the little bits so that they are // + // ready to be inserted into the bigger pieces when they get // + // are created. // + //-------------------------------------------------------------------// + //-------------------------------------------------------------------// + + std::string moduleName = "LAr::HEC::Module"; + std::string depthName = moduleName + "::Depth"; + std::string sliceName = depthName + "::Slice"; + std::string electrodeName = sliceName + "::Electrode"; + std::string copperName = electrodeName + "::Copper"; + std::string tieRodName = sliceName + "::TieRod"; + std::string deadTieName = sliceName + "::TieRodDead"; + std::string absorberName = depthName + "::Absorber"; + std::string firstAbsorberName = depthName + "::FirstAbsorber"; + std::string absTieRodName = absorberName + "::TieRod"; + std::string firstabsTieRodName = firstAbsorberName + "::TieRod"; + + //---- Tie rods to go into Absorbers -------------------------------------- + + GeoTubs* solidAbsorberTieRod = new GeoTubs(0.*cm,tieRodDiameter/2.,absThickness/2.,0.*deg,360.*deg); + const GeoLogVol* logiAbsorberTieRod = new GeoLogVol(absTieRodName,solidAbsorberTieRod,Iron); //,0,0,0); + GeoPhysVol* physiAbsorberTieRod = new GeoPhysVol(logiAbsorberTieRod); + + GeoTubs* solidFirstAbsorberTieRod = new GeoTubs(0.*cm,tieRodDiameter/2.,firstAbsThickness/2.,0.*deg,360.*deg); + const GeoLogVol* logiFirstAbsorberTieRod = new GeoLogVol(firstabsTieRodName,solidFirstAbsorberTieRod,Iron); //,0,0,0); + GeoPhysVol* physiFirstAbsorberTieRod = new GeoPhysVol(logiFirstAbsorberTieRod); + + + //---- Tie rods to go into Slices (i.e. sensitive LAr gaps) ----------------- + + GeoTubs* solidTieRod = new GeoTubs(0.*cm,spacerDiameter/2.,rodSize/2.,0.*deg,360.*deg); + const GeoLogVol* logiTieRod = new GeoLogVol(tieRodName, solidTieRod, Iron); + GeoPhysVol* physiTieRod = new GeoPhysVol(logiTieRod); + + + GeoTubs* solidDeadTie = new GeoTubs(g4allowS+spacerDiameter/2., + spacerDeadZone+spacerDiameter/2., + rodSize/2., + 0.*deg,360.*deg); + const GeoLogVol* logiDeadTie = new GeoLogVol(deadTieName, solidDeadTie, LAr); + GeoPhysVol* physiDeadTie = new GeoPhysVol(logiDeadTie); + + + //---- Create PAD board and EST boards, then also Slices (ie. LAr gaps) and put the boards into Slices ------------ + // This requires a loop, because the frontWheel has two sections (iSect) of different radial size. + // The same goes for the Absorbers - create them in this loop, too. + // (NB: Each wheel has only one "firstAbsorber"; Create that ahead of everything else.) + // And finally equip the LAr Slices as well as the Absorbers with their respective tie-rods. + + + GeoTubs* solidPadBoard[2] ; + const GeoLogVol* logiPadBoard[2]; + GeoPhysVol* physiPadBoard[2]; + + GeoTubs* solidCopperPad[2]; + const GeoLogVol* logiCopperPad[2]; + GeoPhysVol* physiCopperPad[2]; + + GeoTubs* solidEstBoard[2]; + const GeoLogVol* logiEstBoard[2]; + GeoPhysVol* physiEstBoard[2]; + + GeoTubs* solidSlice[2]; + const GeoLogVol* logiSlice[2]; + GeoPhysVol* physiSlice[2]; + + GeoTubs* solidAbsorber[2]; + const GeoLogVol* logiAbsorber[2]; + GeoPhysVol* physiAbsorber[2]; + + // First Absorbers in front of first and third samplings (need only one type in each wheel) + double rOuterF = moduleRouter-radialShift; + double rInnerF = moduleRinner2-radialShift; + if (m_frontWheel) rInnerF= moduleRinner1-radialShift; + GeoTubs* solidFirstAbsorber = new GeoTubs(rInnerF,rOuterF, + firstAbsThickness/2., + modulePhistart,moduleDeltaPhi); + const GeoLogVol* logiFirstAbsorber = new GeoLogVol(firstAbsorberName, solidFirstAbsorber, Copper); + GeoPhysVol* physiFirstAbsorber = new GeoPhysVol(logiFirstAbsorber); + + + for(int iSect=0; iSect<sectMax; iSect++) + { + //-------- First make the slice: ------------------ + // NB: larShift produces the inter-module gap, + // but the actual radial size of the board or slice also has to be + // made smaller by the value of deadZone. + + double rOuter = moduleRouter - larShift - deadZone; + double rInner = moduleRinner2 - larShift + deadZone; + if (iSect<1 && m_frontWheel) rInner = moduleRinner1 - larShift + deadZone;; + solidSlice[iSect] = new GeoTubs(rInner, rOuter, gapSize/2., modulePhistart, moduleDeltaPhi); + logiSlice[iSect] = new GeoLogVol(sliceName, solidSlice[iSect], LAr); + physiSlice[iSect] = new GeoPhysVol(logiSlice[iSect]); + + //-------- Now make the boards: -------- + rOuter = moduleRouter - larShift - deadZone -g4allowS; + rInner = moduleRinner2 - larShift + deadZone +g4allowS; + if (m_frontWheel && iSect==0) rInner = moduleRinner1 - larShift + deadZone +g4allowS ; + + // First, make a central PAD Board: Copper encased in Kapton + // In case of the one-board approach, that's the only board (just thicker) + if (m_threeBoards){ + solidPadBoard[iSect] = new GeoTubs(rInner,rOuter, + kaptonWidth[1]/2., + modulePhistart,moduleDeltaPhi); + } + else{ + solidPadBoard[iSect] = new GeoTubs(rInner,rOuter, + (kaptonWidth[1]/2.+ kaptonWidth[0]), + modulePhistart,moduleDeltaPhi); + } + logiPadBoard[iSect] = new GeoLogVol(electrodeName, solidPadBoard[iSect], Kapton ); + physiPadBoard[iSect] = new GeoPhysVol(logiPadBoard[iSect]); + + // The central board contains copper pads for readout + solidCopperPad[iSect] = new GeoTubs(rInner,rOuter,copperPad/2., + modulePhistart,moduleDeltaPhi); + logiCopperPad[iSect] = new GeoLogVol(copperName, solidCopperPad[iSect], Copper); + physiCopperPad[iSect] = new GeoPhysVol(logiCopperPad[iSect]); + physiPadBoard[iSect]->add(physiCopperPad[iSect]); + + // For the three-board approach, make an individual EST board and place it twice in the LAr gap + if(m_threeBoards){ + solidEstBoard[iSect] = new GeoTubs(rInner,rOuter,kaptonWidth[0]/2., + modulePhistart,moduleDeltaPhi); + logiEstBoard[iSect] = new GeoLogVol(electrodeName, solidEstBoard[iSect], Kapton ); + physiEstBoard[iSect] = new GeoPhysVol(logiEstBoard[iSect]); + } + + //--- Insert the Boards into the Slice --------- + + physiSlice[iSect]->add(new GeoIdentifierTag(1)); + physiSlice[iSect]->add(physiPadBoard[iSect]); + + + // For the three-board approach, make an individual EST board and place it twice in the LAr gap + if(m_threeBoards){ + double halfGapLAr = (gapSize - kaptonWidth[1])/2.; + double ESTPos = (kaptonWidth[1]+halfGapLAr)/2.; + physiSlice[iSect]->add(new GeoIdentifierTag(0)); + physiSlice[iSect]->add(new GeoTransform(Translate3D(0,0,(-ESTPos)))); + physiSlice[iSect]->add(physiEstBoard[iSect]); + physiSlice[iSect]->add(new GeoIdentifierTag(2)); + physiSlice[iSect]->add(new GeoTransform(Translate3D(0,0,ESTPos))); + physiSlice[iSect]->add(physiEstBoard[iSect]); + } + + + + + //--- Create the absorbers ----- + + rOuter = moduleRouter - radialShift; + rInner = moduleRinner2 - radialShift; + if (iSect<1 && m_frontWheel) rInner = moduleRinner1 - radialShift; + solidAbsorber[iSect] = new GeoTubs(rInner,rOuter,absThickness/2., modulePhistart,moduleDeltaPhi); + logiAbsorber[iSect] = new GeoLogVol(absorberName, solidAbsorber[iSect], Copper); + physiAbsorber[iSect] = new GeoPhysVol(logiAbsorber[iSect]); + + + + //--- Insert tie rods into the Absorbers and Slices ----- + // There are three pairs (left/right symmetric-> handled by loop over isignX) + // and they need to be placed in z on either side of the board(s) (loop over isign) + // (Note; we did the radial shift for the absorber(and slice); have to compensate for that now in Y position) + + + for(int indexRod=1; indexRod<nRods; indexRod++) { + for(double isignX=-1;isignX<2;isignX=isignX+2.){ + + physiAbsorber[iSect]->add(new GeoIdentifierTag(indexRod)); + physiAbsorber[iSect]->add(new GeoTransform(Translate3D(isignX*tieRodPositionX[indexRod], + -tieRodPositionY[indexRod]+radialShift, 0))); + physiAbsorber[iSect]->add(physiAbsorberTieRod); + if (iSect==0){ // fill the FirstAbsorber with tie-rods at the same time) + physiFirstAbsorber->add(new GeoIdentifierTag(indexRod)); + physiFirstAbsorber->add(new GeoTransform(Translate3D(isignX*tieRodPositionX[indexRod], + -tieRodPositionY[indexRod]+radialShift, 0))); + physiFirstAbsorber->add(physiFirstAbsorberTieRod); + } + + // For the LAr slices, we have to insert the spacers around the boards (in Z): + + for(int itie=0; itie<2; itie++ ){ // itie=0 inserts spacers, itie=1 inserts spacer dead-zone + for(double isignZ=-1;isignZ<2;isignZ=isignZ+2.){ + physiSlice[iSect]->add(new GeoIdentifierTag(indexRod)); + physiSlice[iSect]->add(new GeoTransform + (Translate3D(isignX*tieRodPositionX[indexRod], + -tieRodPositionY[indexRod]+larShift, + isignZ*ztie[0]))); + if (itie==0) { physiSlice[iSect]->add(physiTieRod); } + else { physiSlice[iSect]->add(physiDeadTie);} + + if (m_threeBoards) { + physiSlice[iSect]->add(new GeoIdentifierTag(indexRod)); + physiSlice[iSect]->add(new GeoTransform + (Translate3D(isignX*tieRodPositionX[indexRod], + -tieRodPositionY[indexRod]+larShift, + isignZ*ztie[1]))); + if (itie==0) { physiSlice[iSect]->add(physiTieRod); } + else { physiSlice[iSect]->add(physiDeadTie);} + } + } + } + + + + } + } + + //--- This is for the lonely un-paired tie-rod at the narrow end of the module (Absorber): + physiAbsorber[iSect]->add(new GeoIdentifierTag(0)); + physiAbsorber[iSect]->add(new GeoTransform(Translate3D(tieRodPositionX[0], + -tieRodPositionY[0]+radialShift,0))); + physiAbsorber[iSect]->add(physiAbsorberTieRod); + if (iSect==0){ + physiFirstAbsorber->add(new GeoIdentifierTag(0)); + physiFirstAbsorber->add(new GeoTransform(Translate3D(tieRodPositionX[0], + -tieRodPositionY[0]+radialShift,0))); + physiFirstAbsorber->add(physiFirstAbsorberTieRod); + } + + //--- And the lonely Slice tie-rods: ------------- + for(int itie=0; itie<2; itie++ ){ // tie=0 inserts spacers, itie=1 inserts spacer dead-zone + for(double isignZ=-1;isignZ<2;isignZ=isignZ+2){ + physiSlice[iSect]->add(new GeoIdentifierTag(0)); + physiSlice[iSect]->add(new GeoTransform(Translate3D(tieRodPositionX[0], + -tieRodPositionY[0]+larShift, + isignZ*ztie[0]))); + if (itie==0) { physiSlice[iSect]->add(physiTieRod); } + else { physiSlice[iSect]->add(physiDeadTie);} + + if (m_threeBoards) { + physiSlice[iSect]->add(new GeoIdentifierTag(0)); + physiSlice[iSect]->add(new GeoTransform(Translate3D(tieRodPositionX[0], + -tieRodPositionY[0]+larShift, + isignZ*ztie[1]))); + if (itie==0) { physiSlice[iSect]->add(physiTieRod); } + else { physiSlice[iSect]->add(physiDeadTie);} + } + } + } + + }//for iSect + + + + // Now that Slices and Absorbers are filled with their components, + // create the Depths and place the slices and absorbers into them + + + //---------------------------------------------------------------- + // Depths + //---------------------------------------------------------------- + // There are 3 depths in the front wheel, and 4 in the rear wheel. + // Create them and equip them with fully assembled slices and absorbers. + + GeoTubs* solidDepth[4] ; + const GeoLogVol* logiDepth[4] ; + GeoPhysVol* physiDepth[4] ; + + for(int iDepth=0; iDepth<depthNumber; iDepth++) + { + double rOuter = moduleRouter; + double rInner = moduleRinner2; + if (iDepth<1 && m_frontWheel) rInner= moduleRinner1; + solidDepth[iDepth] = new GeoTubs(rInner-drModOverlap,rOuter, + depthSize[iDepth]/2.,modulePhistart,moduleDeltaPhi); + logiDepth[iDepth] = new GeoLogVol(depthName, solidDepth[iDepth], LAr); + physiDepth[iDepth] = new GeoPhysVol(logiDepth[iDepth]); + + + // Position the sensitive LAr Slice-gaps and absorbers into the just created Depth: + // Absorber size and position + double firstAbs = 0.; + if (iDepth==0) firstAbs = firstAbsThickness; + double slicePositionZ = firstAbs + gapSize/2.0 -depthSize[iDepth]/2.0; + double absorberPositionZ = firstAbs + gapSize + absThickness/2.0 - depthSize[iDepth]/2.0; + + // sliceCopyNo is the copy number of the slice and runs consecutively from + // front to back throughout the module. + // The first gap in the rear Wheel has number 24 (=rearOffset). + // sliceNo refers to how many slice types there are (0,1 in Front ; 0 in Rear) + // gapNumber is the number of gaps in a given Depth + int sliceNo = 0; + int sliceCopyNo = 0; + if(!m_frontWheel) sliceCopyNo = rearOffset ; + + if (iDepth>0) + { + sliceCopyNo += gaptally[iDepth]; + if(m_frontWheel) sliceNo=1; + } + + // Serially install all slices and _regular_ absorbers into the depths + Genfun::Variable Index; + GeoXF::TRANSFUNCTION TS = + TranslateY3D(-larShift)*GeoXF::Pow(TranslateZ3D(1.0),slicePositionZ + (absThickness+gapSize)*Index); + GeoXF::TRANSFUNCTION TA = + TranslateY3D(-radialShift)*GeoXF::Pow(TranslateZ3D(1.0),absorberPositionZ + (absThickness+gapSize)*Index); + + GeoSerialIdentifier *sI = new GeoSerialIdentifier(sliceCopyNo); + GeoSerialTransformer *sTS = new GeoSerialTransformer(physiSlice[sliceNo], &TS, gapNumber[iDepth]); + GeoSerialTransformer *sTAF = new GeoSerialTransformer(physiAbsorber[sliceNo], &TA, gapNumber[iDepth]); + physiDepth[iDepth]->add(sI); + physiDepth[iDepth]->add(sTS); + physiDepth[iDepth]->add(sI); + physiDepth[iDepth]->add(sTAF); + + } //for iDepth + + + // The first absorber is special (1/2 thickness) install that now + double firstAbsorberPositionZ = firstAbsThickness/2.- depthSize[0]/2.0; + if(m_frontWheel) physiDepth[0]->add(new GeoIdentifierTag(0)); + else physiDepth[0]->add(new GeoIdentifierTag(1)); + physiDepth[0]->add(new GeoTransform(Translate3D(0,-radialShift,firstAbsorberPositionZ))); + physiDepth[0]->add(physiFirstAbsorber); + + + //---------------------------------------------------------------- + // HEC Module + //---------------------------------------------------------------- + + + GeoPcon* solidHECModule = new GeoPcon(modulePhistart, moduleDeltaPhi); + for (int i=0; i< nZplane; i++) + { + double innerRadius = moduleRinner2; + if (i<2 && m_frontWheel) innerRadius=moduleRinner1; + solidHECModule->addPlane(zCoordinate[i],innerRadius-drModOverlap,moduleRouter); + } + const GeoLogVol* logicHECModule = new GeoLogVol(moduleName, solidHECModule , LAr); + GeoFullPhysVol* physiHECModule = new GeoFullPhysVol(logicHECModule); + + + //--- Place the fully instrumented depths into the Module: ---- + + double depthPositionZ = 0.; + + for(int iDepth=0; iDepth<depthNumber; iDepth++) + { + depthPositionZ +=depthSize[iDepth]/2.; + if(!m_frontWheel) physiHECModule->add(new GeoIdentifierTag(iDepth+depthOffset)); + else physiHECModule->add(new GeoIdentifierTag(iDepth)); + physiHECModule->add(new GeoTransform(Translate3D(0,0,depthPositionZ))); + physiHECModule->add(physiDepth[iDepth]); + depthPositionZ +=depthSize[iDepth]/2.; + } //for iDepth + + + + // Return the physical volume that contains everything we've placed. + + //-- clean up: + solidAbsorberTieRod->ref(); solidAbsorberTieRod->unref(); + logiAbsorberTieRod->ref(); logiAbsorberTieRod->unref(); + physiAbsorberTieRod->ref(); physiAbsorberTieRod->unref(); + solidFirstAbsorberTieRod->ref(); solidFirstAbsorberTieRod->unref(); + logiFirstAbsorberTieRod->ref(); logiFirstAbsorberTieRod->unref(); + physiFirstAbsorberTieRod->ref(); physiFirstAbsorberTieRod->unref(); + solidTieRod->ref(); solidTieRod->unref(); + logiTieRod->ref(); logiTieRod->unref(); + physiTieRod->ref(); physiTieRod->unref(); + solidDeadTie->ref(); solidDeadTie->unref(); + logiDeadTie->ref(); logiDeadTie->unref(); + physiDeadTie->ref(); physiDeadTie->unref(); + solidFirstAbsorber->ref(); solidFirstAbsorber->unref(); + logiFirstAbsorber->ref(); logiFirstAbsorber->unref(); + physiFirstAbsorber->ref(); physiFirstAbsorber->unref(); + for(int iSect=0; iSect<sectMax; iSect++) + { + solidCopperPad[iSect]->ref(); solidCopperPad[iSect]->unref(); + logiCopperPad[iSect]->ref(); logiCopperPad[iSect]->unref(); + physiCopperPad[iSect]->ref(); physiCopperPad[iSect]->unref(); + solidPadBoard[iSect]->ref(); solidPadBoard[iSect]->unref(); + logiPadBoard[iSect]->ref(); logiPadBoard[iSect]->unref(); + physiPadBoard[iSect]->ref(); physiPadBoard[iSect]->unref(); + if(m_threeBoards){ + solidEstBoard[iSect]->ref(); solidEstBoard[iSect]->unref(); + logiEstBoard[iSect]->ref(); logiEstBoard[iSect]->unref(); + physiEstBoard[iSect]->ref(); physiEstBoard[iSect]->unref(); + } + solidAbsorber[iSect]->ref(); solidAbsorber[iSect]->unref(); + logiAbsorber[iSect]->ref(); logiAbsorber[iSect]->unref(); + physiAbsorber[iSect]->ref(); physiAbsorber[iSect]->unref(); + solidSlice[iSect]->ref(); solidSlice[iSect]->unref(); + logiSlice[iSect]->ref(); logiSlice[iSect]->unref(); + physiSlice[iSect]->ref(); physiSlice[iSect]->unref(); + } + for(int iDepth=0; iDepth<depthNumber; iDepth++){ + solidDepth[iDepth]->ref(); solidDepth[iDepth]->unref(); + logiDepth[iDepth]->ref(); logiDepth[iDepth]->unref(); + physiDepth[iDepth]->ref(); physiDepth[iDepth]->unref(); + } + + return physiHECModule; +} diff --git a/LArCalorimeter/LArGeoModel/LArGeoHec/src/HECWheelConstruction.cxx b/LArCalorimeter/LArGeoModel/LArGeoHec/src/HECWheelConstruction.cxx new file mode 100755 index 00000000000..4cf9a858152 --- /dev/null +++ b/LArCalorimeter/LArGeoModel/LArGeoHec/src/HECWheelConstruction.cxx @@ -0,0 +1,283 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// HECWheelConstruction.cxx 1.0.0 +// +// This provides a mother volume for the ATLAS Front HEC or Rear HEC, +// gets the modules from the HECModuleConstruction and arranges +// them into a FrontWheel or RearWheel respectively. +// The LAr gaps can be equipped with either one thick PAD+EST board +// or with 3 individual boards (1 PAD + 2 EST). +// +// M. Fincke-Keeler +// +//==================================================================== +#include "LArGeoHec/HECWheelConstruction.h" +#include "LArGeoHec/HECClampConstruction.h" +#include "LArGeoHec/HECModuleConstruction.h" + +#include "GeoModelKernel/GeoElement.h" +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoVPhysVol.h" +#include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoPcon.h" +#include "GeoModelKernel/GeoTubs.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoTransform.h" +#include "GeoModelKernel/GeoAlignableTransform.h" +#include "GeoModelKernel/GeoIdentifierTag.h" +#include "GeoModelKernel/GeoSerialTransformer.h" +#include "GeoModelKernel/GeoSerialIdentifier.h" +#include "GeoModelKernel/GeoXF.h" +#include "CLHEP/Geometry/Transform3D.h" +#include "CLHEP/Vector/Rotation.h" +#include "CLHEP/Units/PhysicalConstants.h" +#include "CLHEP/GenericFunctions/Variable.hh" +#include "StoreGate/StoreGateSvc.h" +#include "StoreGate/DataHandle.h" +#include "GeoModelInterfaces/AbsMaterialManager.h" +#include "GeoModelInterfaces/StoredMaterialManager.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/Bootstrap.h" +#include "AthenaKernel/getMessageSvc.h" + + +#include "RDBAccessSvc/IRDBAccessSvc.h" +#include "RDBAccessSvc/IRDBRecord.h" +#include "RDBAccessSvc/IRDBRecordset.h" +//#include "RDBAccessSvc/IRDBQuery.h" +#include "GeoModelInterfaces/IGeoModelSvc.h" + +#include <string> +#include <cmath> +#include <iostream> + + +using CLHEP::cm; +using CLHEP::mm; +using CLHEP::deg; +using HepGeom::RotateZ3D; + + +//Constructor +LArGeo::HECWheelConstruction::HECWheelConstruction(bool fullGeo, std::string wheelType, bool threeBoards, bool posZSide): + m_physiHECWheel(0), + m_rail(false), + m_left(false), + m_clampLength(0), + m_clampAngle(0), + m_fullGeo(fullGeo) +{ + m_threeBoards = threeBoards; + m_posZSide = posZSide; + m_wheelType = wheelType; + if (m_wheelType=="front") m_frontWheel = true; + else m_frontWheel = false; +} + +//~Destructor +LArGeo::HECWheelConstruction::~HECWheelConstruction() +{;} + + +GeoFullPhysVol* LArGeo::HECWheelConstruction::GetEnvelope() +{ + if(m_physiHECWheel) return m_physiHECWheel->clone(); + + // Get access to the material manager: + + ISvcLocator *svcLocator = Gaudi::svcLocator(); + + MsgStream log(Athena::getMessageSvc(),"HECWheelConstruction " ); + + log << MSG::DEBUG << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endreq; + log << MSG::DEBUG << "+ +" << endreq; + log << MSG::DEBUG << "+ Start of HECWheel GeoModel definition +" << endreq; + log << MSG::DEBUG << "+ +" << endreq; + log << MSG::DEBUG << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endreq; + + + StoreGateSvc *detStore; + if (svcLocator->service("DetectorStore", detStore, false )==StatusCode::FAILURE) { + throw std::runtime_error("Error in HECWheelConstruction, cannot access DetectorStore"); + } + + + DataHandle<StoredMaterialManager> materialManager; + if (StatusCode::SUCCESS != detStore->retrieve(materialManager, std::string("MATERIALS"))) { + throw std::runtime_error("Error in HECWheelConstruction, cannot access Material Manager"); + } + + GeoMaterial *LAr = materialManager->getMaterial("std::LiquidArgon"); + if (!LAr) throw std::runtime_error("Error in HECWheelConstruction, std::LiquidArgon is not found."); + + GeoMaterial *Iron = materialManager->getMaterial("std::Iron"); + if (!Iron) throw std::runtime_error("Error in HECWheelConstruction, std::Iron is not found."); + + + + StatusCode sc; + IRDBAccessSvc *pAccessSvc; + sc=svcLocator->service("RDBAccessSvc",pAccessSvc); + if (sc != StatusCode::SUCCESS) { + throw std::runtime_error ("Cannot locate RDBAccessSvc!!"); + } + + + IGeoModelSvc *geoModel; + sc = svcLocator->service ("GeoModelSvc",geoModel); + if (sc != StatusCode::SUCCESS) { + throw std::runtime_error ("Cannot locate GeoModelSvc!!"); + } + + std::string AtlasVersion = geoModel->atlasVersion(); + std::string LArVersion = geoModel->LAr_VersionOverride(); + + std::string detectorKey = LArVersion.empty() ? AtlasVersion : LArVersion; + std::string detectorNode = LArVersion.empty() ? "ATLAS" : "LAr"; + + IRDBRecordset_ptr hadronicEndcap = pAccessSvc->getRecordsetPtr("HadronicEndcap",detectorKey, detectorNode); + if(hadronicEndcap->size()>0) + log << MSG::DEBUG << "Using numbers from HadronicEndcap tag: " << hadronicEndcap->tagName() << endreq; + else + throw std::runtime_error("Error in HECConstruction: hadronicEendcap not found"); + + IRDBRecordset_ptr hecLongitudinalBlock = pAccessSvc->getRecordsetPtr("HecLongitudinalBlock",detectorKey, detectorNode); + if(hecLongitudinalBlock->size()>0) + log << MSG::DEBUG << "Using numbers from HecLongitudinalBlock tag: " << hecLongitudinalBlock->tagName() << endreq; + else + throw std::runtime_error("Error in HECConstruction: hecLongitudinalBlock not found"); + + IRDBRecordset_ptr coldContraction = pAccessSvc->getRecordsetPtr("ColdContraction",detectorKey, detectorNode); + if(coldContraction->size()>0) + log << MSG::DEBUG << "Numbers from ColdContraction db (not used yet) tag: " << coldContraction->tagName() << endreq; + else + throw std::runtime_error("Error in HECConstruction: ColdContraction not found"); + + //---------------------------------------------------------------- + // Collect all the numbers we need from the database: + //---------------------------------------------------------------- + + // This will have to come into action once we are all ready to go cold: + // (what's still missing right now are the proper densities to go with it) + //double shrinkCold = (*coldContraction)[0]->getDouble("ABSORBERCONTRACTION"); + + double shrinkCold = 1.0; // thermal expansion factor: 1.0 = warm geometry + + int moduleNumber = (*hadronicEndcap)[0]->getInt("NSCT"); + double drModOverlap = shrinkCold * (*hadronicEndcap)[0]->getDouble("DRMODOVERLAP")*cm; + double rOuter = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMX")*cm; + if (rOuter<2100.*mm) rOuter = shrinkCold * 2130*mm; // Needs fixing in database to make room for HEC Clamping bars! + // Caution: We'll need 2 Routers - One for Wheel, one for Module! + double rInner1 = shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("BLRMN")*cm; + double rInner2 = shrinkCold * (*hecLongitudinalBlock)[1]->getDouble("BLRMN")*cm; + double firstFrontAbsThickness= shrinkCold * (*hecLongitudinalBlock)[0]->getDouble("PLATE0")*cm; + double firstRearAbsThickness = shrinkCold * (*hecLongitudinalBlock)[3]->getDouble("PLATE0")*cm; + double frontAbsThickness = shrinkCold * (*hadronicEndcap)[0]->getDouble("PLATE_0")*cm; + double rearAbsThickness = shrinkCold * (*hadronicEndcap)[0]->getDouble("PLATE_1")*cm; + double gapSize = shrinkCold * (*hadronicEndcap)[0]->getDouble("LARG")*cm; + int gapNumber[7]; + for (int id=0; id<7;id++) gapNumber[id] = (int) (*hecLongitudinalBlock)[id]->getDouble("BLMOD"); + + + //---- Calculate the sizes of the 7 longitudinal Depths ------------------------------------- + double depthSize[7]; + depthSize[0] = firstFrontAbsThickness + gapNumber[0]*(frontAbsThickness+gapSize); + depthSize[1] = gapNumber[1]*(frontAbsThickness+gapSize); + depthSize[2] = gapNumber[2]*(frontAbsThickness+gapSize); + depthSize[3] = firstRearAbsThickness + gapNumber[3]*(rearAbsThickness+gapSize); + depthSize[4] = gapNumber[4]*(rearAbsThickness+gapSize); + depthSize[5] = gapNumber[5]*(rearAbsThickness+gapSize); + depthSize[6] = gapNumber[6]*(rearAbsThickness+gapSize); + + //--- From the depth Size, calculate the boundary planes of the Wheel Mother volume --------- + // (Add 0.2 mm to avoid clashes) + double g4allow = shrinkCold * 0.2*mm;; + double zCoordinate[4]; + if (m_frontWheel){ + zCoordinate[0] = shrinkCold * 0.0*cm; + zCoordinate[1] = depthSize[0]; //280.5*mm; (end of the section with the long plates) + zCoordinate[2] = depthSize[0] + g4allow; //280.6*mm; + zCoordinate[3] = depthSize[0] + depthSize[1] + depthSize[2] + g4allow; // End of front Module + } + else{ + zCoordinate[0] = shrinkCold * 0.0*cm; + zCoordinate[1] = depthSize[3] + depthSize[4] + depthSize[5] + depthSize[6] + g4allow; // End of rear + } + + //---- And here we have some (yikes!) hard-coded values: ------------------------------------- + // The somewhat odd looking phistart arranges that the y-axis lines up + // with the (radial) symmetry axis of of the module. + // This is important for the calculator. + // + double modulePhistart = 264.375*deg; // (270.-11.25/2.)*deg + double moduleDeltaPhi = 2*M_PI/moduleNumber; //11.25*deg; + + int nZplane = 4; + if (!m_frontWheel) nZplane = 2; + + + + //---------------------------------------------------------------- + // HECWheel + //---------------------------------------------------------------- + GeoPcon* solidHECWheel = new GeoPcon(0., 2.*M_PI); + for (int i=0; i< nZplane; i++) + { + double innerRadius = rInner2; + if (i<2 && m_frontWheel) innerRadius=rInner1; + solidHECWheel->addPlane(zCoordinate[i],innerRadius-drModOverlap,rOuter); + } + std::string hecFrontName = "LAr::HEC::LiquidArgon"; + const GeoLogVol* logicHECWheel = new GeoLogVol(hecFrontName, solidHECWheel , LAr); + GeoFullPhysVol* physiHECWheel = new GeoFullPhysVol(logicHECWheel); + + + if(m_fullGeo) { + + //---------------------------------------------------------------- + // Get HEC Modules + //---------------------------------------------------------------- + // NB: HECModuleConstruction( threeBoards, frontWheel, TB,TByear) ; + + HECModuleConstruction HECModule(m_threeBoards,m_frontWheel,false,0) ; + GeoVPhysVol* moduleEnvelope = HECModule.GetEnvelope(); + + //---------------------------------------------------------------- + // Place Modules into HEC Wheel + //---------------------------------------------------------------- + // Rotation angle is: 11.25/2 + Index * 11.25*deg + // Modules are numbered mirror-symmetric in pos/neg z-side! + + GeoSerialIdentifier *sIF = new GeoSerialIdentifier(0); + Genfun::Variable Index; + + if (m_posZSide) { + Genfun::GENFUNCTION ModuleRotationAngle = -modulePhistart + moduleDeltaPhi*Index; + GeoXF::TRANSFUNCTION t = GeoXF::Pow(RotateZ3D(1.0),ModuleRotationAngle); + GeoSerialTransformer *sTF = new GeoSerialTransformer (moduleEnvelope,&t,moduleNumber); + physiHECWheel->add(sIF); + physiHECWheel->add(sTF); + } else { + //For the neg z-side have to build everything in the opposite sense from pos-z wheel. + Genfun::GENFUNCTION ModuleRotationAngle1 = -modulePhistart+180*deg-moduleDeltaPhi - moduleDeltaPhi*Index; + GeoXF::TRANSFUNCTION t1 = GeoXF::Pow(RotateZ3D(1.0),ModuleRotationAngle1); + GeoSerialTransformer *sTF1 = new GeoSerialTransformer (moduleEnvelope,&t1,moduleNumber); + physiHECWheel->add(sIF); + physiHECWheel->add(sTF1); + } + + //---------------------------------------------------------------- + // Add Outer Connecting Bars to HEC Wheel + //---------------------------------------------------------------- + + HECClampConstruction HECClamp (m_frontWheel,m_posZSide); + HECClamp.AddClamps(physiHECWheel); + } + + return physiHECWheel; +} + -- GitLab