diff --git a/compact/display_detailed.xml b/compact/display_detailed.xml index 896000a00..69fde959c 100644 --- a/compact/display_detailed.xml +++ b/compact/display_detailed.xml @@ -128,10 +128,11 @@ - + + diff --git a/compact/pid/drich.xml b/compact/pid/drich.xml index cde823bfa..927e0e836 100644 --- a/compact/pid/drich.xml +++ b/compact/pid/drich.xml @@ -43,6 +43,12 @@ + + + + + + - `DRICH_debug_optics`: 1 = all components become vacuum, except for mirrors; test opticalphotons from IP 2 = all components become vacuum, except for mirrors and `gasvol`, test charged particles from IP @@ -121,6 +127,9 @@ - `rmin` and `rmax`: inner and outer radius (at the front plane; radial bounds are conical) - `thickness`: radiator thickness, defined separately for aerogel and filter - `pitch`: controls the angle of the radiator (0=vertical) + - `segmentations`:controls tiling method. They can be "trapezoidal", "square" or "unique". + A unique segmentation means, no tiling of aerogel. + + +#include +#include #include @@ -80,21 +75,27 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec auto radiatorRmax = radiatorElem.attr(_Unicode(rmax)); auto radiatorPitch = radiatorElem.attr(_Unicode(pitch)); auto radiatorFrontplane = radiatorElem.attr(_Unicode(frontplane)); - // - aerogel auto aerogelElem = radiatorElem.child(_Unicode(aerogel)); auto aerogelMatName = aerogelElem.attr(_Unicode(material)); auto aerogelMat = desc.material(aerogelMatName); auto aerogelVis = desc.visAttributes(aerogelElem.attr(_Unicode(vis))); auto aerogelThickness = aerogelElem.attr(_Unicode(thickness)); - + // - aerogel structure + auto coronasElem = radiatorElem.child(_Unicode(coronas)); + auto coronasMat = desc.material(coronasElem.attr(_Unicode(material))); + auto coronasVis = desc.visAttributes(coronasElem.attr(_Unicode(vis))); + auto coronasThickness = coronasElem.attr(_Unicode(thickness)); + int numCrowns = coronasElem.attr(_Unicode(num)); + auto segmentationType = coronasElem.attr("segmentation"); + auto segmentsStr = coronasElem.attr(_Unicode(num_segments)); + auto radiiStr = coronasElem.attr(_Unicode(radii)); // - filter auto filterElem = radiatorElem.child(_Unicode(filter)); auto filterMatName = filterElem.attr(_Unicode(material)); auto filterMat = desc.material(filterMatName); auto filterVis = desc.visAttributes(filterElem.attr(_Unicode(vis))); auto filterThickness = filterElem.attr(_Unicode(thickness)); - // - airgap between filter and aerogel auto airgapElem = radiatorElem.child(_Unicode(airgap)); auto airgapMat = desc.material(airgapElem.attr(_Unicode(material))); @@ -340,39 +341,161 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec // BUILD RADIATOR ==================================================================== // solid and volume: create aerogel and filter - Cone aerogelSolid(aerogelThickness / 2, radiatorRmin, radiatorRmax, - radiatorRmin + boreDelta * aerogelThickness / vesselLength, - radiatorRmax + snoutDelta * aerogelThickness / snoutLength); - Cone airgapSolid(airgapThickness / 2, radiatorRmin + boreDelta * aerogelThickness / vesselLength, + + // ------------------------------------------------------------------------ + Cone aerogelSolid(aerogelThickness / 2.0, radiatorRmin, radiatorRmax, + radiatorRmin + boreDelta * aerogelThickness / vesselLength, radiatorRmax); + + Volume aerogelVol; + double halfAerogelThickness = aerogelThickness / 2.0; + const int nHalves = 2; + std::vector numSegments; + std::stringstream ss(segmentsStr); + std::string val; + while (std::getline(ss, val, ',')) { + numSegments.push_back(std::stoi(val)); + } + + std::vector radii; + std::stringstream radiiSS(radiiStr); + std::string radius; + while (std::getline(radiiSS, radius, ',')) { + radii.push_back(std::stod(radius)); + } + auto radiatorPos = Position(0., 0., radiatorFrontplane + 0.5 * aerogelThickness) + originFront; + auto aerogelPlacement = Translation3D(radiatorPos) * RotationY(radiatorPitch); + + aerogelVol = Volume(detName + "_aerogel", aerogelSolid, aerogelMat); + aerogelVol.setVisAttributes(aerogelVis); + auto aerogelPV = gasvolVol.placeVolume(aerogelVol, aerogelPlacement); + DetElement aerogelDE(det, "aerogel_de", 0); + aerogelDE.setPlacement(aerogelPV); + + if (segmentationType == "trapezoidal") { + double crownHeight = halfAerogelThickness; + std::vector innerRadiusBottoms_half[nHalves]; + std::vector innerRadiusTops_half[nHalves]; + std::vector outerRadiusBottoms_half[nHalves]; + std::vector outerRadiusTops_half[nHalves]; + std::vector crownSolids[nHalves]; + std::vector segmentSolids[nHalves]; + Solid crownSolidUnion_half[nHalves], segmentSolidUnion_half[nHalves], + crownAndSegmentSolid_half[nHalves]; + // ------------------------------------------------------------------------ + // HALF 1 + // ------------------------------------------------------------------------ + for (int h = 0; h < nHalves; h++) { + //double zPos_half = (pow(-1,(h+1)))*crownHeight / 2.0; + for (int i = 0; i < numCrowns; i++) { + double centralRadius = radii[i]; + double rMinBottom, rMinTop, rMaxBottom, rMaxTop; + + if (i == 0) { + rMinBottom = centralRadius - boreDelta * (coronasThickness / 2.0) / vesselLength; + rMinTop = rMinBottom + snoutDelta * halfAerogelThickness / snoutLength; + rMaxBottom = rMinBottom + boreDelta * coronasThickness / vesselLength; + rMaxTop = rMinTop + boreDelta * coronasThickness / vesselLength; + } else { + double innerRadius = centralRadius - coronasThickness / 2.0; + double outerRadius = centralRadius + coronasThickness / 2.0; + + // FIX PROTRUSION + if (i == numCrowns - 1) { + double safetyMargin = 0.05 * dd4hep::cm; + outerRadius -= safetyMargin; + } + + rMinBottom = innerRadius; + rMinTop = innerRadius; + rMaxBottom = outerRadius; + rMaxTop = outerRadius; + } + + innerRadiusBottoms_half[h].push_back(rMinBottom); + innerRadiusTops_half[h].push_back(rMinTop); + outerRadiusBottoms_half[h].push_back(rMaxBottom); + outerRadiusTops_half[h].push_back(rMaxTop); + + Cone crownSolid(crownHeight / 2.0, rMinBottom, rMaxBottom, rMinTop, rMaxTop); + crownSolids[h].push_back(crownSolid); + std::string crownName = "CarbonCrown_Half1_" + std::to_string(i); + Volume crownVol(crownName, crownSolid, coronasMat); + crownVol.setVisAttributes(coronasVis); + //aerogelVol.placeVolume(crownVol, Position(0., 0., zPos_half1)); + } + crownSolidUnion_half[h] = std::accumulate( + crownSolids[h].begin() + 1, crownSolids[h].end(), crownSolids[h][0], + [](const Solid& a, const Solid& b) { return UnionSolid(a, b, Position(0., 0., 0.)); }); + + // ---- Segments Half 1 ----- + for (int i = 0; i < numCrowns - 1; i++) { + int N = numSegments[i]; + + double rMin_Zminus = outerRadiusBottoms_half[h][i]; + double rMax_Zminus = innerRadiusBottoms_half[h][i + 1]; + double rMin_Zplus = outerRadiusTops_half[h][i]; + double rMax_Zplus = innerRadiusTops_half[h][i + 1]; + + double segmentSpacing = 2 * M_PI / N; + double segmentAngularWidth = coronasThickness / rMin_Zminus; + + for (int p = 0; p < N; p++) { + double phiStart = p * segmentSpacing; + double phiEnd = phiStart + segmentAngularWidth; + + ConeSegment segmentSolid(crownHeight / 2.0, rMin_Zminus, rMax_Zminus, rMin_Zplus, + rMax_Zplus, phiStart, phiEnd); + segmentSolids[h].push_back(segmentSolid); + std::string segName = + "CarbonSegment_Half1_" + std::to_string(i) + "_" + std::to_string(p); + Volume segVol(segName, segmentSolid, coronasMat); + segVol.setVisAttributes(coronasVis); + //aerogelVol.placeVolume(segVol, Position(0., 0., zPos_half)); + } + } //crown + + segmentSolidUnion_half[h] = std::accumulate( + segmentSolids[h].begin() + 1, segmentSolids[h].end(), segmentSolids[h][0], + [](const Solid& a, const Solid& b) { return UnionSolid(a, b, Position(0., 0., 0.)); }); + + crownAndSegmentSolid_half[h] = UnionSolid(crownSolidUnion_half[h], segmentSolidUnion_half[h]); + } //halves + std::string crName[2] = {"_crown_and_segment_1", "_crown_and_segment_2"}; + + for (int h = 0; h < nHalves; h++) { + // aerogel structure positioning + double localZ = pow(-1, h + 1) * 0.5 * crownHeight; + Transform3D placement = Transform3D(RotationY(radiatorPitch), Position(0., 0., localZ)); + Volume crownAndSegmentVolume(detName + crName[h], crownAndSegmentSolid_half[h], coronasMat); + crownAndSegmentVolume.setVisAttributes(coronasVis); + auto crownPV = aerogelVol.placeVolume(crownAndSegmentVolume, placement); + DetElement crownDE(det, crName[h], 0); + crownDE.setPlacement(crownPV); + } + } //trapezoidal + + else if (segmentationType == "square") { + printout(WARNING, "DRICH_geo", "Square segmentation requested but not implemented yet."); + } //Square + + Cone airgapSolid(airgapThickness / 2.0, + radiatorRmin + boreDelta * aerogelThickness / vesselLength, radiatorRmax + snoutDelta * aerogelThickness / snoutLength, radiatorRmin + boreDelta * (aerogelThickness + airgapThickness) / vesselLength, radiatorRmax + snoutDelta * (aerogelThickness + airgapThickness) / snoutLength); Cone filterSolid( - filterThickness / 2, + filterThickness / 2.0, radiatorRmin + boreDelta * (aerogelThickness + airgapThickness) / vesselLength, radiatorRmax + snoutDelta * (aerogelThickness + airgapThickness) / snoutLength, radiatorRmin + boreDelta * (aerogelThickness + airgapThickness + filterThickness) / vesselLength, radiatorRmax + snoutDelta * (aerogelThickness + airgapThickness + filterThickness) / snoutLength); - - Volume aerogelVol(detName + "_aerogel", aerogelSolid, aerogelMat); Volume airgapVol(detName + "_airgap", airgapSolid, airgapMat); Volume filterVol(detName + "_filter", filterSolid, filterMat); - aerogelVol.setVisAttributes(aerogelVis); airgapVol.setVisAttributes(airgapVis); filterVol.setVisAttributes(filterVis); - // aerogel placement and surface properties - // TODO [low-priority]: define skin properties for aerogel and filter - // FIXME: radiatorPitch might not be working correctly (not yet used) - auto radiatorPos = Position(0., 0., radiatorFrontplane + 0.5 * aerogelThickness) + originFront; - auto aerogelPlacement = Translation3D(radiatorPos) * // re-center to originFront - RotationY(radiatorPitch); // change polar angle to specified pitch - auto aerogelPV = gasvolVol.placeVolume(aerogelVol, aerogelPlacement); - DetElement aerogelDE(det, "aerogel_de", 0); - aerogelDE.setPlacement(aerogelPV); - // airgap and filter placement and surface properties if (!debugOptics) { @@ -868,9 +991,9 @@ static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetec addVecToMap("pos", sensorPos); addVecToMap("normX", sensorNormX); addVecToMap("normY", sensorNormY); - printout(VERBOSE, "DRICH_geo", "sensor %s:", sensorIDname.c_str()); + printout(DEBUG, "DRICH_geo", "sensor %s:", sensorIDname.c_str()); for (auto kv : pssVarMap->variantParameters) - printout(VERBOSE, "DRICH_geo", " %s: %f", kv.first.c_str(), + printout(DEBUG, "DRICH_geo", " %s: %f", kv.first.c_str(), pssVarMap->get(kv.first)); #endif printout(DEBUG, "DRICH_geo", "sensor %s:", sensorIDname.c_str());