diff --git a/Detector/TV/src/TV_geo.cpp b/Detector/TV/src/TV_geo.cpp index 080b01bb17764b50ba4656504f65ef162e9c900d..c7bf431820e89073f980332e2c5e22cc0798d5be 100644 --- a/Detector/TV/src/TV_geo.cpp +++ b/Detector/TV/src/TV_geo.cpp @@ -59,6 +59,7 @@ namespace { std::pair generate_cooling_pipes(); void swapCuts( const unsigned nPipe, TVector3& fV, TVector3& bV, int Direction ); void generate_corrugated_foil(); + void generate_iris_foil(); }; /// Initializing constructor @@ -643,9 +644,12 @@ namespace { deLeft.add( deOpt ); } - bool corrugated_foil = dd4hep::_toInt( "TV:FoilCorrugated" ); + int foil_shape = 0; + try { + foil_shape = dd4hep::_toInt( "TV:FoilShapeTag" ); + } catch ( std::runtime_error& e ) { foil_shape = dd4hep::_toInt( "TV:FoilCorrugated" ); } - if ( build_rf_box && corrugated_foil ) { + if ( build_rf_box && foil_shape == 1 ) { pv = lvLeft.placeVolume( volume( "lvRFBoxLeft" ) ); pv->SetName( "pvRFBoxLeft" ); deOpt = DetElement( deLeft, "RFBoxLeft", deLeft.id() ); @@ -656,11 +660,24 @@ namespace { deOpt.setPlacement( pv ); } if ( build_rf_foil ) { - if ( corrugated_foil ) { generate_corrugated_foil(); } + if ( foil_shape == 1 ) { generate_corrugated_foil(); } + if ( foil_shape == 2 ) { generate_iris_foil(); } dd4hep::Volume vol = volume( "lvRFFoil" ); - dd4hep::Position pos_left( 0.0, 0.0, corrugated_foil ? dd4hep::_toDouble( "TV:RFFoilLeftPosZ" ) : 0.0 ); - dd4hep::Position pos_right( 0.0, 0.0, corrugated_foil ? dd4hep::_toDouble( "TV:RFFoilRightPosZ" ) : 0.0 ); + dd4hep::Position pos_left; + dd4hep::Position pos_right; + + if ( foil_shape == 0 ) { + pos_left = dd4hep::Position( 0, 0, 0.0 ); + pos_right = dd4hep::Position( 0, 0, 0.0 ); + } else if ( foil_shape == 1 ) { + pos_left = dd4hep::Position( 0.0, 0.0, dd4hep::_toDouble( "TV:RFFoilLeftPosZ" ) ); + pos_right = dd4hep::Position( 0.0, 0.0, dd4hep::_toDouble( "TV:RFFoilRightPosZ" ) ); + } else if ( foil_shape == 2 ) { + // NB the right/left = +ve/-ve is deliberately opposite from that of the modules + pos_left = dd4hep::Position( 0, 0, -Right2LeftDist / 2.0 ); + pos_right = dd4hep::Position( 0, 0, +Right2LeftDist / 2.0 ); + } pv = lvLeft.placeVolume( vol, pos_left ); pv->SetName( "pvRFFoilLeft" ); @@ -764,6 +781,206 @@ namespace { dd4hep::detail::destroyHandle( de_module_with_support ); } + void TVBuild::generate_iris_foil() { + // Define the iris-like foil contaning two parts: + // * the actual foil pipe is placed twice, with a 90 degree rotation + // * the identical foil support sections are placed along the z-axis + + dd4hep::PlacedVolume pv; + dd4hep::Assembly iris_foil( "lvRFFoil" ); + + const int nStations = dd4hep::_toInt( "TV:NoOfStations" ); + const double RFBoxZPosition = dd4hep::_toDouble( "TV:RFBoxZPosition" ); + + const double IrisFoilThickness = dd4hep::_toDouble( "TV:IrisFoilThickness" ); + const double IrisFoilStraightLength = dd4hep::_toDouble( "TV:IrisFoilStraightLength" ); + const double IrisFoilConnectLength = dd4hep::_toDouble( "TV:IrisFoilConnectLength" ); + const double IrisFoilCurveRadiusInner = dd4hep::_toDouble( "TV:IrisFoilCurveRadiusInner" ); + const double IrisFoilCurveRadiusOuter = dd4hep::_toDouble( "TV:IrisFoilCurveRadiusOuter" ); + const double IrisFoilHoleSize = dd4hep::_toDouble( "TV:IrisFoilHoleSize" ); + const double IrisFoilZSize = dd4hep::_toDouble( "TV:RFFoilZSize" ); + const double IrisFoilSupportThickness = dd4hep::_toDouble( "TV:IrisFoilSupportThickness" ); + const double IrisFoilSupportLength = dd4hep::_toDouble( "TV:IrisFoilSupportLength" ); + const double SiEdge = dd4hep::_toDouble( "TV:SiEdge" ); + const double eps = dd4hep::_toDouble( "TV:Epsilon" ); + dd4hep::Material foilMat = description.material( "TV:IrisFoilFoil" ); + dd4hep::Material supportMat = description.material( "TV:IrisSupport" ); + + // Define the actual foil + + // Basic shapes + dd4hep::Box boxStraight( IrisFoilThickness / 2.0, IrisFoilStraightLength / 2.0, IrisFoilZSize / 2.0 ); + dd4hep::Box boxConnect( IrisFoilThickness / 2.0, IrisFoilConnectLength / 2.0, IrisFoilZSize / 2.0 ); + dd4hep::ConeSegment coneCurve( IrisFoilZSize / 2.0, IrisFoilCurveRadiusInner, IrisFoilCurveRadiusOuter, + IrisFoilCurveRadiusInner, IrisFoilCurveRadiusOuter, -90.0 * dd4hep::degree, + 00.0 * dd4hep::degree ); + // Combine the straight and connect sections + dd4hep::UnionSolid foilUnion1( + "IrisFoilUnion1", boxStraight, boxConnect, + dd4hep::Position( 0.0, -IrisFoilConnectLength / 2.0 - IrisFoilStraightLength / 2.0, 0.0 ) ); + // Combine the curved section + dd4hep::UnionSolid foilUnion2( "IrisFoilUnion2", foilUnion1, coneCurve, + dd4hep::Position( -IrisFoilCurveRadiusOuter + IrisFoilThickness / 2.0, + -IrisFoilConnectLength - IrisFoilStraightLength / 2.0, 0.0 ) ); + // Then subtract holes for the sensors + dd4hep::SubtractionSolid IrisFoilUnionLeft = foilUnion2; + for ( int i = 0; i < nStations; i++ ) { + // Calculate the z-position and size for the hole + const double station_z = dd4hep::_toDouble( dd4hep::_toString( i, "TV:Station%02dZ" ) ); + dd4hep::Box hole( 2.0 * IrisFoilThickness, IrisFoilStraightLength / 2.0 + IrisFoilConnectLength / 2.0, + IrisFoilHoleSize / 2.0 ); + IrisFoilUnionLeft = dd4hep::SubtractionSolid( + "IrisFoilUnionLeft", IrisFoilUnionLeft, hole, + dd4hep::Transform3D( dd4hep::Position( 0.0, 0.0, station_z - RFBoxZPosition ) ) // note the shift in + // z-position + ); + } + + // Generate the final logical volume + dd4hep::Volume lvIrisFoilLeft( "lvIrisFoilFoilLeft", IrisFoilUnionLeft, foilMat ); + + // Place the foil pipe + dd4hep::Position posIrisFoil( dd4hep::_toDouble( "TV:IrisFoilSupportToBeamX" ) - IrisFoilThickness / 2.0 - + SiEdge, // Shift by GuardRing thickness to avoid overlap + dd4hep::_toDouble( "TV:IrisFoilSupportToBeamY" ) + IrisFoilStraightLength / 2.0, + RFBoxZPosition ); + pv = iris_foil.placeVolume( lvIrisFoilLeft, dd4hep::Transform3D( dd4hep::RotationZ( M_PI / 4.0 ) ) * + dd4hep::Transform3D( posIrisFoil ) ); + pv->SetName( "pvIrisFoilFoil_rot45" ); + // Place the foil pipe again with a 90 degree rotation + pv = iris_foil.placeVolume( lvIrisFoilLeft, dd4hep::Transform3D( dd4hep::RotationZ( 3.0 * M_PI / 4.0 ) ) * + dd4hep::Transform3D( posIrisFoil ) ); + pv->SetName( "pvIrisFoilFoil_rot135" ); + + // Basic shapes + dd4hep::Box IrisFoilSupportUnion( IrisFoilSupportThickness / 2.0, IrisFoilSupportLength / 2.0, + IrisFoilZSize / 2.0 ); + dd4hep::Box IrisFoilSupportHole( 2.0 * IrisFoilSupportThickness, IrisFoilSupportLength / 2.0 / 2.0 + eps, + 2.0 * IrisFoilZSize ); + dd4hep::SubtractionSolid IrisFoilSupportFrame( + "IrisFoilSupportFrame", IrisFoilSupportUnion, IrisFoilSupportHole, + dd4hep::Position( 0.0, -IrisFoilSupportLength / 2.0 / 2.0, -RFBoxZPosition ) ); + + const double IrisFoilSupportBarEndsLength = dd4hep::_toDouble( "TV:IrisFoilSupportBarEndsLength" ); + const double IrisFoilSupportBarInterLength = dd4hep::_toDouble( "TV:IrisFoilSupportBarInterLength" ); + const double IrisFoilSupportMaxAllowedGap = dd4hep::_toDouble( "TV:IrisFoilSupportMaxAllowedGap" ); + const double IrisFoilSupportStationTolerance = dd4hep::_toDouble( "TV:IrisFoilSupportStationTolerance" ); + + // Add support bars at the ends of the foil + dd4hep::Box IrisFoilSupportBarEnds( IrisFoilSupportThickness / 2.0, IrisFoilSupportLength / 2.0 / 2.0, + IrisFoilSupportBarEndsLength / 2.0 ); + dd4hep::UnionSolid IrisFoilSupport( "IrisFoilSupport", IrisFoilSupportFrame, IrisFoilSupportBarEnds, + dd4hep::Position( 0.0, -IrisFoilSupportLength / 2.0 / 2.0, + -IrisFoilZSize / 2.0 + IrisFoilSupportBarEndsLength / 2.0 ) ); + IrisFoilSupport = + dd4hep::UnionSolid( "IrisFoilSupport", IrisFoilSupport, IrisFoilSupportBarEnds, + dd4hep::Position( 0.0, -IrisFoilSupportLength / 2.0 / 2.0, + +IrisFoilZSize / 2.0 - IrisFoilSupportBarEndsLength / 2.0 ) ); + + // Add support inters between stations + dd4hep::Box IrisFoilSupportBarInter( IrisFoilSupportThickness / 2.0, IrisFoilSupportLength / 2.0 / 2.0, + IrisFoilSupportBarInterLength / 2.0 ); + + bool irisSupportManual; + try { + // check whether iris support z locations have been defined + double irisCheck = dd4hep::_toDouble( "TV:IrisSupport00Z" ); + irisSupportManual = true; + } catch ( std::runtime_error& e ) { irisSupportManual = false; } + + if ( irisSupportManual ) { + std::vector irisSupportZLocs; + int nIrisSupport = 0; + while ( true ) { + try { + irisSupportZLocs.push_back( dd4hep::_toDouble( dd4hep::_toString( nIrisSupport, "TV:IrisSupport%02dZ" ) ) - + dd4hep::_toDouble( "TV:RFBoxZPosition" ) ); + nIrisSupport++; + } catch ( std::runtime_error& e ) { break; } + } + for ( int i = 0; i < nIrisSupport - 1; i++ ) { + std::cout << "Placing a support no. " << i << " at " << irisSupportZLocs[i] << std::endl; + IrisFoilSupport = + dd4hep::UnionSolid( "IrisFoilSupport", IrisFoilSupport, IrisFoilSupportBarInter, + dd4hep::Position( 0.0, -IrisFoilSupportLength / 2.0 / 2.0, irisSupportZLocs[i] ) ); + } + } else { + // then automatically set location of supports + double lastSupportZ = -IrisFoilZSize / 2.0 + IrisFoilSupportBarInterLength / 2.0; + int countInter = 0; + for ( int i = 0; i < nStations - 1; i++ ) { + const double currentStationZ = + dd4hep::_toDouble( dd4hep::_toString( i, "TV:Station%02dZ" ) ) - dd4hep::_toDouble( "TV:RFBoxZPosition" ); + const double nextStationZ = dd4hep::_toDouble( dd4hep::_toString( i + 1, "TV:Station%02dZ" ) ) - + dd4hep::_toDouble( "TV:RFBoxZPosition" ); + const double gapFromLastSupport = nextStationZ + IrisFoilSupportStationTolerance - lastSupportZ; + const double gapBetweenStations = nextStationZ - currentStationZ - 2 * IrisFoilSupportStationTolerance; + const double gapFromLastSupportToThisStation = currentStationZ + IrisFoilSupportStationTolerance - lastSupportZ; + if ( gapFromLastSupportToThisStation > IrisFoilSupportMaxAllowedGap ) { + std::cout << "Error: The gap from the last support to the next station is too large. Consider increasing the " + "'IrisFoilSupportMaxAllowedGap' parameter larger than " + << gapFromLastSupportToThisStation << " mm" << std::endl; + } + + std::cout << "currentStationZ: " << currentStationZ << std::endl; + std::cout << "nextStationZ: " << nextStationZ << std::endl; + std::cout << "gapFromLastSupport: " << gapFromLastSupport << std::endl; + std::cout << "gapBetweenStations: " << gapBetweenStations << std::endl; + + if ( gapFromLastSupport > IrisFoilSupportMaxAllowedGap ) { + int numInter = static_cast( gapBetweenStations / IrisFoilSupportMaxAllowedGap ) + 1; + double interZ; + if ( numInter > 1 ) { + double interval = gapBetweenStations / ( numInter - 1 ); + for ( int j = 0; j < numInter; j++ ) { + interZ = ( currentStationZ + nextStationZ ) / 2.0 - ( numInter - 1 ) * interval / 2.0 + j * interval; + std::cout << "Placing " << numInter << " supports no. " << countInter << " at " << interZ << std::endl; + dd4hep::Position posInter( 0.0, 0.0, interZ ); + IrisFoilSupport = + dd4hep::UnionSolid( "IrisFoilSupport", IrisFoilSupport, IrisFoilSupportBarInter, + dd4hep::Position( 0.0, -IrisFoilSupportLength / 2.0 / 2.0, interZ ) ); + countInter++; + } + } else { + interZ = ( currentStationZ + nextStationZ ) / 2.0; + if ( interZ > nextStationZ - IrisFoilSupportStationTolerance ) { + std::cout << "The support is too close to the next station, skipping it" << std::endl; + continue; + } + std::cout << "Placing one support no. " << countInter << " at " << interZ << std::endl; + dd4hep::Position posInter( 0.0, 0.0, interZ ); + IrisFoilSupport = dd4hep::UnionSolid( "IrisFoilSupport", IrisFoilSupport, IrisFoilSupportBarInter, + dd4hep::Position( 0.0, -IrisFoilSupportLength / 2.0 / 2.0, interZ ) ); + countInter++; + } + lastSupportZ = interZ; + } + } + } + + // Generate the final logical volume + dd4hep::Volume lvIrisSupportQuarter( "lvIrisSupportQuarter", IrisFoilSupport, supportMat ); + lvIrisSupportQuarter.setVisAttributes( description, "TV:IrisFoilSupport" ); + + // Place the support sections + dd4hep::Position posIrisFoilSupport( + dd4hep::_toDouble( "TV:IrisFoilSupportToBeamX - 0.5*TV:IrisFoilSupportThickness" ) - + SiEdge, // Shift by GuardRing thickness to avoid overlap + dd4hep::_toDouble( "TV:IrisFoilSupportToBeamY + 0.5*TV:IrisFoilSupportLength" ), + dd4hep::_toDouble( "TV:RFBoxZPosition" ) ); + + pv = iris_foil.placeVolume( lvIrisSupportQuarter, dd4hep::Transform3D( dd4hep::RotationZ( M_PI / 4.0 ) ) * + dd4hep::Transform3D( posIrisFoilSupport ) ); + pv->SetName( "pvIrisFoilSupport_rot45" ); + // Place the foil pipe again with a 90 degree rotation + pv = iris_foil.placeVolume( lvIrisSupportQuarter, dd4hep::Transform3D( dd4hep::RotationZ( 3.0 * M_PI / 4.0 ) ) * + dd4hep::Transform3D( posIrisFoilSupport ) ); + pv->SetName( "pvIrisFoilSupport_rot135" ); + + // register the volume + registerVolume( iris_foil.name(), iris_foil ); + } + void TVBuild::generate_corrugated_foil() { // Define the corrugated foil contaning two parts: // * the TnT sections at each station position, which are all identical diff --git a/compact/components/TV/branch-run5-baseline/RFFoil/RFFoil_iris.xml b/compact/components/TV/branch-run5-baseline/RFFoil/RFFoil_iris.xml new file mode 100644 index 0000000000000000000000000000000000000000..a3d1c53e34cbfd673f06357ebaee8c70bbc7277b --- /dev/null +++ b/compact/components/TV/branch-run5-baseline/RFFoil/RFFoil_iris.xml @@ -0,0 +1,13 @@ + + + + diff --git a/compact/components/TV/branch-run5-baseline/parameters.xml b/compact/components/TV/branch-run5-baseline/parameters.xml index 012fa2f919a2e744dc233ae5a5b00cf6c57d5329..ea179c19610941bed1654f862ba222942bbcaf73 100644 --- a/compact/components/TV/branch-run5-baseline/parameters.xml +++ b/compact/components/TV/branch-run5-baseline/parameters.xml @@ -156,18 +156,20 @@ - + + - + - - + + - - + + + @@ -179,6 +181,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -883,7 +981,14 @@ - + + + + + + + + @@ -891,6 +996,17 @@ + + + + + + + + + + + @@ -912,6 +1028,30 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/compact/components/TV/branch-run5-baseline/visualization.xml b/compact/components/TV/branch-run5-baseline/visualization.xml index 879640c6f71d63d5f42afd1ab9dc4fed0da0ebca..2908fc0eb0944b7041349bf7bc4f618d7d547ecb 100644 --- a/compact/components/TV/branch-run5-baseline/visualization.xml +++ b/compact/components/TV/branch-run5-baseline/visualization.xml @@ -34,6 +34,7 @@ +