Skip to content
Snippets Groups Projects
Commit 0fb63eac authored by Christopher Dilks's avatar Christopher Dilks Committed by Sylvester Joosten
Browse files

Resolve "Detailed Dual RICH implementation"

parent a54a6a23
No related branches found
No related tags found
1 merge request!72Resolve "Detailed Dual RICH implementation"
...@@ -164,7 +164,7 @@ ...@@ -164,7 +164,7 @@
<!--include ref="compact/dirc.xml"/--> <!--include ref="compact/dirc.xml"/-->
<!--include ref="compact/mrich.xml"/--> <!--include ref="compact/mrich.xml"/-->
<include ref="compact/forward_trd.xml"/> <include ref="compact/forward_trd.xml"/>
<include ref="compact/gaseous_rich.xml"/> <include ref="compact/drich.xml"/>
<documentation level="10"> <documentation level="10">
## Central calorimetry ## Central calorimetry
......
...@@ -324,7 +324,7 @@ Examples: ...@@ -324,7 +324,7 @@ Examples:
### PID Detector Region Parameters ### PID Detector Region Parameters
</documentation> </documentation>
<constant name="ForwardRICH_length" value="1.1*m"/> <constant name="ForwardRICH_length" value="180.0*cm"/>
<constant name="ForwardTRD_length" value="10.0*cm"/> <constant name="ForwardTRD_length" value="10.0*cm"/>
<constant name="ForwardTOF_length" value="3.0*cm"/> <constant name="ForwardTOF_length" value="3.0*cm"/>
...@@ -353,7 +353,7 @@ Examples: ...@@ -353,7 +353,7 @@ Examples:
Generic tracking space allocations Generic tracking space allocations
</documentation> </documentation>
<constant name="ForwardTracking_length" value="0.0*cm"/> <constant name="ForwardTracking_length" value="25.0*cm"/>
<documentation> <documentation>
`BackwardTracking_length` and `ForwardTracking_length` compensate for the asymmetry of the setup `BackwardTracking_length` and `ForwardTracking_length` compensate for the asymmetry of the setup
</documentation> </documentation>
......
...@@ -77,6 +77,15 @@ ...@@ -77,6 +77,15 @@
<vis name="ci_GEMVis" r= "0.8" g="0.4" b="0.3" alpha="0.8" showDaughters="true" visible="true"/> <vis name="ci_GEMVis" r= "0.8" g="0.4" b="0.3" alpha="0.8" showDaughters="true" visible="true"/>
<vis name="ci_HCALVis" r= "0.6" g="0" b="0.6" alpha="1.0" showDaughters="true" visible="true"/> <vis name="ci_HCALVis" r= "0.6" g="0" b="0.6" alpha="1.0" showDaughters="true" visible="true"/>
<vis name="DRICH_vessel_vis" alpha="1.0" r="1.0" g="1.0" b="1.0" showDaughters="true" visible="true" />
<vis name="DRICH_gas_vis" alpha="1.0" r="1.0" g="0.0" b="0.0" showDaughters="true" visible="true" />
<vis name="DRICH_aerogel_vis" alpha="1.0" r="0.0" g="1.0" b="1.0" showDaughters="true" visible="true" />
<vis name="DRICH_filter_vis" alpha="1.0" r="1.0" g="1.0" b="0.0" showDaughters="true" visible="true" />
<vis name="DRICH_mirror_vis" alpha="1.0" r="0.5" g="0.5" b="0.5" showDaughters="true" visible="true" />
<vis name="DRICH_sensor_vis" alpha="1.0" r="0.0" g="1.0" b="0.0" showDaughters="true" visible="true" />
</display>
<comment> <comment>
Deprecated colors. Deprecated colors.
vis name="GreenVis" alpha="1.0" r= "0.0" g="1.0" b="0.0" showDaughters="true" visible="true"/ vis name="GreenVis" alpha="1.0" r= "0.0" g="1.0" b="0.0" showDaughters="true" visible="true"/
......
<?xml version="1.0" encoding="UTF-8"?>
<lccdd>
<define>
<!-- TODO [low priority]: some of these, viz. radii, could be parameterized
with respect to other variables; for now they are hard coded in case
other detectors' parameters are changing -->
<!-- parameters for re-scaling fun4all design to ATHENA -->
<constant name="DRICH_scale" value="0.963"/> <!-- overall scale factor from fun4all to ATHENA -->
<constant name="DRICH_f4a_length" value="161.0*cm"/> <!-- z-length of fun4all design -->
<!-- vessel (=snout+tank) geometry -->
<constant name="DRICH_zmin" value="BarrelTracking_length/2.0 + ForwardTracking_length "/> <!-- vessel front -->
<constant name="DRICH_Length" value="ForwardRICH_length"/> <!-- overall vessel length (including snout) -->
<constant name="DRICH_rmin0" value="ForwardPID_rmin1"/> <!-- bore radius at dRICh vessel frontplane -->
<constant name="DRICH_rmin1" value="19.0*cm"/> <!-- bore radius at dRICh vessel backplane -->
<constant name="DRICH_wall_thickness" value="0.5*cm"/> <!-- thickness of radial walls -->
<constant name="DRICH_window_thickness" value="0.1*cm"/> <!-- thickness of entrance and exit walls -->
<!-- snout geometry: cone with front radius rmax0 and back radius of rmax1 -->
<constant name="DRICH_SnoutLength" value="50.0*cm"/>
<constant name="DRICH_rmax0" value="110.0*cm"/>
<constant name="DRICH_rmax1" value="125.0*cm"/>
<!-- tank geometry: cylinder, holding the majority of detector components -->
<constant name="DRICH_rmax2" value="200*cm"/> <!-- cylinder radius; 20 cm gap between dRICh and HCalBarrel -->
<!-- additional parameters -->
<constant name="DRICH_aerogel_thickness" value="4.0*cm"/> <!-- aerogel thickness -->
</define>
<detectors>
<detector
id="ForwardRICH_ID"
name="DRICH"
type="athena_DRICH"
readout="DRICHHits"
gas="C2F6_DRICH"
material="Aluminum"
vis_vessel="DRICH_vessel_vis"
vis_gas="DRICH_gas_vis"
>
<!-- envelope dimensions (see above)
- `wall_thickness`: thickness of radial walls
- `window_thickness`: thickness of entrance and exit disks
-->
<dimensions
z0="DRICH_zmin"
length="DRICH_Length"
snout_length="DRICH_SnoutLength"
rmin0="DRICH_rmin0"
rmin1="DRICH_rmin1"
rmax0="DRICH_rmax0"
rmax1="DRICH_rmax1"
rmax2="DRICH_rmax2"
nsectors="6"
wall_thickness="DRICH_wall_thickness"
window_thickness="DRICH_window_thickness"
/>
<!-- radiator defined in a wedge of azimuthal space
- `phiw` is phi width of wedge
- `thickness` defined separately for aerogel and filter
- `frontplane` is the front of the aerogel, w.r.t. front plane of vessel envelope
- `pitch` controls the angle of the radiator (0=vertical)
- filter is applied to backplane of aerogel
-->
<radiator
rmin="DRICH_rmin0 + DRICH_wall_thickness + 2.0*cm"
rmax="DRICH_rmax0 - DRICH_wall_thickness - 2.0*cm"
phiw="56*degree"
frontplane="DRICH_window_thickness + 0.5*DRICH_aerogel_thickness"
pitch="0*degree"
>
<aerogel
material="Aerogel_DRICH"
vis="DRICH_aerogel_vis"
thickness="DRICH_aerogel_thickness"
/>
<filter
material="Acrylic_DRICH"
vis="DRICH_filter_vis"
thickness="0.3*mm"
/>
</radiator>
<!-- spherical mirror is part of a sphere
- `rmin` and `rmax` provide polar angle boundaries
- `phiw` is the azimuthal width
- `radius` is the radius of the sphere
- `centerx` is the transverse position of the center
of the sphere, for the sector on the +x axis
- the back of the mirror will pass through `backplane`
- set `debug` to 1 so draw reference sphere instead, view with y-clipping
-->
<mirror
material="Acrylic_DRICH"
surface="MirrorSurface_DRICH"
vis="DRICH_mirror_vis"
backplane="DRICH_Length-2.0*cm"
thickness="0.2*cm"
radius="290*DRICH_scale*cm"
centerx="145*DRICH_scale*cm"
rmin="DRICH_rmin1 + DRICH_wall_thickness + 0.0*cm"
rmax="DRICH_rmax2 - DRICH_wall_thickness - 2.0*cm"
phiw="54*degree"
debug="0"
/>
<sensors>
<!-- geometry for a single square sensor
- based on Hamamatsu H13700 MAPMT
(https://www.hamamatsu.com/us/en/product/type/H13700/index.html)
- N.B. not ideal for a magnetic field, SiPM matrix would be better
- effective area: 48.5x48.5mm
- enclosure size: 52x52mm
- 16x16 channel matrix (see readout segmentation below)
- pixel size: 3x3mm
- `side` is the side length of the square
- `thickness` is the depth of the sensor
- `gap` provides room between the squares, to help
prevent them from overlapping
- the value of `side` will determine how many sensors there are,
since the sensor placement algorithm will try to place as many
as it can in the specified patch below
-->
<module
material="Silicon"
surface="SensorSurface_DRICH"
vis="DRICH_sensor_vis"
side="48*mm"
thickness="35*mm"
gap="0.5*(52-48)*mm + 2*mm"
/>
<!-- sensors will be tiled on this sphere
- `center{x,y,z} is defined for sector on +x axis, defined w.r.t. snout frontplane,
and `radius` is the sphere radius; the first term of each of these comes from
the fun4all design
- these attributes were determined from a spherical fit to the
sensor placement in the fun4all port
- set `debug` to 1 so draw reference sphere instead, view with y-clipping
-->
<sphere
radius="159.76*DRICH_scale*cm"
centerx="144.91*DRICH_scale*cm"
centery="0*DRICH_scale*cm"
centerz="-197.25*DRICH_scale*cm + DRICH_Length - 0.5*DRICH_scale*DRICH_f4a_length"
debug="0"
/>
<!-- sensors will be limited to a patch of the sphere
- `thetamin` and `thetamax` define pseudorapidity coverage
- `widthfactor` controls the azimuthal coverage, where lower=wider
- `taper` defines half the angle between the azimuthal boundaries
- the size of the sensor controls how many sensors are placed
-->
<sphericalpatch
thetamin="-10*degree"
thetamax="22*degree"
widthfactor="1.8"
taper="56*degree"
/>
</sensors>
</detector>
</detectors>
<readouts>
<readout name="DRICHHits">
<segmentation type="CartesianGridXY" grid_size_x="3*mm" grid_size_y="3*mm"/>
<!-- cellID: 64bits
- bits 1-8: dRICh ID
- bits 9-16: sector number
- bits 17-32: photosensor number
- bits 33-48: x pixel (signed)
- bits 49-64: y pixel (signed)
-->
<id>system:8,sector:8,module:16,x:32:-16,y:-16</id>
</readout>
</readouts>
</lccdd>
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
<composite n="15" ref="C"/> <composite n="15" ref="C"/>
<composite n="7" ref="O"/> <composite n="7" ref="O"/>
</material> </material>
<material name="Quartz"> <material name="Quartz"> <!-- different density than `SiliconDioxide` -->
<D type="density" value="2.2" unit="g/cm3"/> <D type="density" value="2.2" unit="g/cm3"/>
<composite n="1" ref="Si"/> <composite n="1" ref="Si"/>
<composite n="2" ref="O"/> <composite n="2" ref="O"/>
...@@ -45,11 +45,16 @@ ...@@ -45,11 +45,16 @@
<fraction n="0.998" ref="Fe"/> <fraction n="0.998" ref="Fe"/>
<fraction n=".002" ref="C"/> <fraction n=".002" ref="C"/>
</material> </material>
<material name="SiliconOxide"> <material name="SiliconOxide"> <!-- different density than `SiliconDioxide` -->
<D type="density" value="2.65" unit="g/cm3"/> <D type="density" value="2.65" unit="g/cm3"/>
<composite n="1" ref="Si"/> <composite n="1" ref="Si"/>
<composite n="2" ref="O"/> <composite n="2" ref="O"/>
</material> </material>
<material name="SiliconDioxide"> <!-- density from `G4_SILICON_DIOXIDE` (NIST DB) -->
<D type="density" value="2.32" unit="g/cm3"/>
<composite n="1" ref="Si"/>
<composite n="2" ref="O"/>
</material>
<material name="BoronOxide"> <material name="BoronOxide">
<D type="density" value="2.46" unit="g/cm3"/> <D type="density" value="2.46" unit="g/cm3"/>
<composite n="2" ref="B"/> <composite n="2" ref="B"/>
...@@ -258,6 +263,18 @@ ...@@ -258,6 +263,18 @@
<D type="density" value="2.21" unit="g/cm3"/> <D type="density" value="2.21" unit="g/cm3"/>
<composite n="1" ref="C"/> <composite n="1" ref="C"/>
</material> </material>
<material name="PolyvinylAcetate">
<D type="density" value="1.19" unit="g/cm3"/>
<composite n="4" ref="C"/>
<composite n="6" ref="H"/>
<composite n="2" ref="O"/>
</material>
<material name="Plexiglass">
<D type="density" value="1.19" unit="g/cm3"/>
<composite n="5" ref="C"/>
<composite n="8" ref="H"/>
<composite n="2" ref="O"/>
</material>
<material name="StainlessSteel"> <material name="StainlessSteel">
<D type="density" value="8.3" unit="g / cm3"/> <D type="density" value="8.3" unit="g / cm3"/>
<fraction n="0.74" ref="Fe"/> <fraction n="0.74" ref="Fe"/>
......
...@@ -47,6 +47,298 @@ ...@@ -47,6 +47,298 @@
1240*eV/600 1.49 1240*eV/600 1.49
1240*eV/400 1.49 1240*eV/400 1.49
"/> "/>
<!-- BEGIN dRICh material properties
- dumped from fun4all implementation
- see https://github.com/cisbani/dRICh/blob/main/share/source/g4dRIChOptics.hh
-->
<!-- dRICh gas -->
<matrix name="RINDEX__C2F6_DRICH" coldim="2" values="
1.7712*eV 1.00075
1.92389*eV 1.00075
2.10539*eV 1.00075
2.3247*eV 1.00075
2.59502*eV 1.00076
2.93647*eV 1.00076
3.38139*eV 1.00077
3.98521*eV 1.00078
4.85156*eV 1.0008
6.19921*eV 1.00084
"/>
<matrix name="ABSLENGTH__C2F6_DRICH" coldim="2" values="
1.7712*eV 1000*mm
1.92389*eV 1000*mm
2.10539*eV 1000*mm
2.3247*eV 1000*mm
2.59502*eV 1000*mm
2.93647*eV 1000*mm
3.38139*eV 1000*mm
3.98521*eV 1000*mm
4.85156*eV 1000*mm
6.19921*eV 1000*mm
"/>
<!-- dRICh aerogel -->
<matrix name="RINDEX__Aerogel_DRICH" coldim="2" values="
1.87855*eV 1.01638
1.96673*eV 1.01642
2.0549*eV 1.01647
2.14308*eV 1.01652
2.23126*eV 1.01657
2.31943*eV 1.01662
2.40761*eV 1.01667
2.49579*eV 1.01673
2.58396*eV 1.01679
2.67214*eV 1.01685
2.76032*eV 1.01691
2.84849*eV 1.01698
2.93667*eV 1.01705
3.02485*eV 1.01712
3.11302*eV 1.01719
3.2012*eV 1.01727
3.28938*eV 1.01734
3.37755*eV 1.01742
3.46573*eV 1.01751
3.55391*eV 1.01759
3.64208*eV 1.01768
3.73026*eV 1.01777
3.81844*eV 1.01787
3.90661*eV 1.01796
3.99479*eV 1.01806
4.08297*eV 1.01816
4.17114*eV 1.01827
4.25932*eV 1.01838
4.3475*eV 1.01849
4.43567*eV 1.0186
4.52385*eV 1.01872
4.61203*eV 1.01884
4.7002*eV 1.01897
4.78838*eV 1.01909
4.87656*eV 1.01922
4.96473*eV 1.01936
5.05291*eV 1.0195
5.14109*eV 1.01964
5.22927*eV 1.01979
5.31744*eV 1.01994
5.40562*eV 1.02009
5.4938*eV 1.02025
5.58197*eV 1.02041
5.67015*eV 1.02057
5.75833*eV 1.02074
5.8465*eV 1.02092
5.93468*eV 1.0211
6.02286*eV 1.02128
6.11103*eV 1.02147
6.19921*eV 1.02167
"/>
<matrix name="ABSLENGTH__Aerogel_DRICH" coldim="2" values="
1.87855*eV 154*mm
1.96673*eV 156.17*mm
2.0549*eV 158.154*mm
2.14308*eV 159.974*mm
2.23126*eV 161.651*mm
2.31943*eV 163.2*mm
2.40761*eV 164.636*mm
2.49579*eV 165.97*mm
2.58396*eV 167.213*mm
2.67214*eV 168.374*mm
2.76032*eV 169.461*mm
2.84849*eV 170.481*mm
2.93667*eV 171.439*mm
3.02485*eV 172.342*mm
3.11302*eV 173.193*mm
3.2012*eV 173.998*mm
3.28938*eV 174.759*mm
3.37755*eV 175.481*mm
3.46573*eV 176.165*mm
3.55391*eV 176.817*mm
3.64208*eV 162.708*mm
3.73026*eV 140.953*mm
3.81844*eV 122.516*mm
3.90661*eV 106.833*mm
3.99479*eV 93.4428*mm
4.08297*eV 81.9694*mm
4.17114*eV 72.1072*mm
4.25932*eV 63.6011*mm
4.3475*eV 56.2434*mm
4.43567*eV 49.8599*mm
4.52385*eV 44.3054*mm
4.61203*eV 39.4601*mm
4.7002*eV 35.2211*mm
4.78838*eV 31.5049*mm
4.87656*eV 28.2374*mm
4.96473*eV 25.359*mm
5.05291*eV 22.8166*mm
5.14109*eV 20.5674*mm
5.22927*eV 18.5724*mm
5.31744*eV 16.7992*mm
5.40562*eV 15.2205*mm
5.4938*eV 13.8125*mm
5.58197*eV 12.5541*mm
5.67015*eV 11.4277*mm
5.75833*eV 10.4166*mm
5.8465*eV 9.50928*mm
5.93468*eV 8.69176*mm
6.02286*eV 7.95608*mm
6.11103*eV 7.29168*mm
6.19921*eV 6.69064*mm
"/>
<matrix name="RAYLEIGH__Aerogel_DRICH" coldim="2" values="
1.87855*eV 309.218*mm
1.96673*eV 257.383*mm
2.0549*eV 215.968*mm
2.14308*eV 182.559*mm
2.23126*eV 155.367*mm
2.31943*eV 133.053*mm
2.40761*eV 114.606*mm
2.49579*eV 99.2482*mm
2.58396*eV 86.3795*mm
2.67214*eV 75.5291*mm
2.76032*eV 66.3313*mm
2.84849*eV 58.4918*mm
2.93667*eV 51.777*mm
3.02485*eV 45.998*mm
3.11302*eV 41.0045*mm
3.2012*eV 36.6696*mm
3.28938*eV 32.8931*mm
3.37755*eV 29.5904*mm
3.46573*eV 26.6917*mm
3.55391*eV 24.1402*mm
3.64208*eV 21.8856*mm
3.73026*eV 19.8884*mm
3.81844*eV 18.1144*mm
3.90661*eV 16.533*mm
3.99479*eV 15.1206*mm
4.08297*eV 13.856*mm
4.17114*eV 12.7208*mm
4.25932*eV 11.7005*mm
4.3475*eV 10.7791*mm
4.43567*eV 9.94752*mm
4.52385*eV 9.1938*mm
4.61203*eV 8.51136*mm
4.7002*eV 7.88964*mm
4.78838*eV 7.32468*mm
4.87656*eV 6.80988*mm
4.96473*eV 6.33864*mm
5.05291*eV 5.907*mm
5.14109*eV 5.51232*mm
5.22927*eV 5.14932*mm
5.31744*eV 4.81668*mm
5.40562*eV 4.51044*mm
5.4938*eV 4.22796*mm
5.58197*eV 3.9666*mm
5.67015*eV 3.72504*mm
5.75833*eV 3.50196*mm
5.8465*eV 3.29604*mm
5.93468*eV 3.10464*mm
6.02286*eV 2.92644*mm
6.11103*eV 2.76144*mm
6.19921*eV 2.607*mm
"/>
<!-- dRICh acrylic -->
<matrix name="RINDEX__Acrylic_DRICH" coldim="2" values="
4.13281*eV 1.5017
4.22099*eV 1.5017
4.30916*eV 1.5017
4.39734*eV 1.5017
4.48552*eV 1.5017
4.57369*eV 1.5017
4.66187*eV 1.5017
4.75005*eV 1.5017
4.83822*eV 1.5017
4.9264*eV 1.5017
5.01458*eV 1.5017
5.10275*eV 1.5017
5.19093*eV 1.5017
5.27911*eV 1.5017
5.36728*eV 1.5017
5.45546*eV 1.5017
5.54364*eV 1.5017
5.63181*eV 1.5017
5.71999*eV 1.5017
5.80817*eV 1.5017
5.89634*eV 1.5017
5.98452*eV 1.5017
6.0727*eV 1.5017
6.16087*eV 1.5017
6.24905*eV 1.5017
6.33723*eV 1.5017
6.4254*eV 1.5017
6.51358*eV 1.5017
6.60176*eV 1.5017
6.68993*eV 1.5017
6.77811*eV 1.5017
6.86629*eV 1.5017
6.95446*eV 1.5017
7.04264*eV 1.5017
7.13082*eV 1.5017
7.21899*eV 1.5017
7.30717*eV 1.5017
7.39535*eV 1.5017
7.48353*eV 1.5017
7.5717*eV 1.5017
7.65988*eV 1.5017
7.74806*eV 1.5017
7.83623*eV 1.5017
7.92441*eV 1.5017
8.01259*eV 1.5017
8.10076*eV 1.5017
8.18894*eV 1.5017
8.27712*eV 1.5017
8.36529*eV 1.5017
8.45347*eV 1.5017
"/>
<matrix name="ABSLENGTH__Acrylic_DRICH" coldim="2" values="
4.13281*eV 82.0704*mm
4.22099*eV 36.9138*mm
4.30916*eV 13.3325*mm
4.39734*eV 5.03627*mm
4.48552*eV 2.3393*mm
4.57369*eV 1.36177*mm
4.66187*eV 0.933192*mm
4.75005*eV 0.708268*mm
4.83822*eV 0.573082*mm
4.9264*eV 0.483641*mm
5.01458*eV 0.420282*mm
5.10275*eV 0.373102*mm
5.19093*eV 0.33662*mm
5.27911*eV 0.307572*mm
5.36728*eV 0.283902*mm
5.45546*eV 0.264235*mm
5.54364*eV 0.247641*mm
5.63181*eV 0.233453*mm
5.71999*eV 0.221177*mm
5.80817*eV 0.210456*mm
5.89634*eV 0.201012*mm
5.98452*eV 0.192627*mm
6.0727*eV 0.185134*mm
6.16087*eV 0.178399*mm
6.24905*eV 0.172309*mm
6.33723*eV 0.166779*mm
6.4254*eV 0.166779*mm
6.51358*eV 0.166779*mm
6.60176*eV 0.166779*mm
6.68993*eV 0.166779*mm
6.77811*eV 0.166779*mm
6.86629*eV 0.166779*mm
6.95446*eV 0.166779*mm
7.04264*eV 0.166779*mm
7.13082*eV 0.166779*mm
7.21899*eV 0.166779*mm
7.30717*eV 0.166779*mm
7.39535*eV 0.166779*mm
7.48353*eV 0.166779*mm
7.5717*eV 0.166779*mm
7.65988*eV 0.166779*mm
7.74806*eV 0.166779*mm
7.83623*eV 0.166779*mm
7.92441*eV 0.166779*mm
8.01259*eV 0.166779*mm
8.10076*eV 0.166779*mm
8.18894*eV 0.166779*mm
8.27712*eV 0.166779*mm
8.36529*eV 0.166779*mm
8.45347*eV 0.166779*mm
"/>
<!-- END dRICh optical properties -->
</properties> </properties>
<materials> <materials>
<material name="AirOptical"> <material name="AirOptical">
...@@ -86,6 +378,32 @@ ...@@ -86,6 +378,32 @@
<composite n="8" ref="H"/> <composite n="8" ref="H"/>
<property name="RINDEX" ref="RINDEX__Acrylic"/> <property name="RINDEX" ref="RINDEX__Acrylic"/>
</material> </material>
<!-- BEGIN dRICh material definitions -->
<material name="C2F6_DRICH">
<D type="density" value="0.005734" unit="g/cm3"/>
<composite n="2" ref="C"/>
<composite n="6" ref="F"/>
<property name="RINDEX" ref="RINDEX__C2F6_DRICH"/>
<property name="ABSLENGTH" ref="ABSLENGTH__C2F6_DRICH"/>
</material>
<material name="Aerogel_DRICH">
<D type="density" value="0.1" unit="g/cm3"/>
<comment> n_air = [dens(Si02)-dens(aerogel)] / [dens(Si02)-dens(Air) ] </comment>
<fraction n=" (2.32-0.1) / (2.32-0.0012)" ref="Air"/>
<fraction n="1 - (2.32-0.1) / (2.32-0.0012)" ref="SiliconDioxide"/>
<property name="RINDEX" ref="RINDEX__Aerogel_DRICH"/>
<property name="ABSLENGTH" ref="ABSLENGTH__Aerogel_DRICH"/>
<property name="RAYLEIGH" ref="RAYLEIGH__Aerogel_DRICH"/>
</material>
<material name="Acrylic_DRICH">
<D type="density" value="1.19" unit="g/cm3"/>
<comment> TO BE IMPROVED </comment>
<fraction n="0.99" ref="Plexiglass"/>
<fraction n="0.01" ref="PolyvinylAcetate"/>
<property name="RINDEX" ref="RINDEX__Acrylic_DRICH"/>
<property name="ABSLENGTH" ref="ABSLENGTH__Acrylic_DRICH"/>
</material>
<!-- END dRICh material definitions -->
</materials> </materials>
<surfaces> <surfaces>
<opticalsurface finish="polished" model="glisur" name="MirrorOpticalSurface" type="dielectric_metal" value="0"> <opticalsurface finish="polished" model="glisur" name="MirrorOpticalSurface" type="dielectric_metal" value="0">
...@@ -131,5 +449,70 @@ ...@@ -131,5 +449,70 @@
--> -->
</opticalsurface> </opticalsurface>
<!-- BEGIN dRICh surface definitions -->
<opticalsurface name="MirrorSurface_DRICH" model="unified" finish="polishedfrontpainted" type="dielectric_dielectric">
<property name="REFLECTIVITY" coldim="2" values="
2.04358*eV 0.867812
2.0664*eV 0.865156
2.09046*eV 0.863906
2.14023*eV 0.86375
2.16601*eV 0.864062
2.20587*eV 0.864531
2.23327*eV 0.864375
2.26137*eV 0.865625
2.31972*eV 0.865313
2.35005*eV 0.865
2.38116*eV 0.864844
2.41313*eV 0.863828
2.44598*eV 0.863516
2.47968*eV 0.863125
2.53081*eV 0.862187
2.58354*eV 0.861719
2.6194*eV 0.861328
2.69589*eV 0.861016
2.73515*eV 0.861094
2.79685*eV 0.861602
2.86139*eV 0.862305
2.95271*eV 0.86375
3.04884*eV 0.865586
3.12665*eV 0.867383
3.2393*eV 0.870059
3.39218*eV 0.874199
3.52508*eV 0.878105
3.66893*eV 0.88252
3.82396*eV 0.887617
3.99949*eV 0.893721
4.13281*eV 0.898184
4.27679*eV 0.902744
4.48244*eV 0.907837
4.65057*eV 0.9102
4.89476*eV 0.909316
5.02774*eV 0.906174
5.16816*eV 0.900422
5.31437*eV 0.891521
5.63821*eV 0.859954
5.90401*eV 0.820831
6.19921*eV 0.762502
"/>
</opticalsurface>
<opticalsurface name="SensorSurface_DRICH" model="glisur" finish="polished" type="dielectric_metal">
<property name="EFFICIENCY" coldim="2" values="
1*eV 1
4*eV 1
7*eV 1
"/>
<property name="IMAGINARYRINDEX" coldim="2" values="
1*eV 1.69
4*eV 1.69
7*eV 1.69
"/>
<property name="REALRINDEX" coldim="2" values="
1*eV 1.92
4*eV 1.92
7*eV 1.92
"/>
</opticalsurface>
<!-- END dRICh surface definitions -->
</surfaces> </surfaces>
</lccdd> </lccdd>
//==========================================================================
// dRICh: Dual Ring Imaging Cherenkov Detector
//--------------------------------------------------------------------------
//
// Author: Christopher Dilks (Duke University)
//
// - Design Adapted from Standalone Fun4all and GEMC implementations
// [ Evaristo Cisbani, Cristiano Fanelli, Alessio Del Dotto, et al. ]
//
//==========================================================================
#include <XML/Helper.h>
#include "TMath.h"
#include "TString.h"
#include "GeometryHelpers.h"
#include "Math/Point2D.h"
#include "DDRec/Surface.h"
#include "DDRec/DetectorData.h"
#include "DD4hep/OpticalSurfaces.h"
#include "DD4hep/DetFactoryHelper.h"
#include "DD4hep/Printout.h"
using namespace std;
using namespace dd4hep;
using namespace dd4hep::rec;
// create the detector
static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetector sens) {
xml::DetElement detElem = handle;
std::string detName = detElem.nameStr();
int detID = detElem.id();
DetElement det(detName, detID);
xml::Component dims = detElem.dimensions();
OpticalSurfaceManager surfMgr = desc.surfaceManager();
// attributes -----------------------------------------------------------
// TODO [low priority]: some attributes have default values, some do not;
// make this more consistent
// - vessel
double vesselZ0 = dims.attr<double>(_Unicode(z0));
double vesselLength = dims.attr<double>(_Unicode(length));
double vesselRmin0 = dims.attr<double>(_Unicode(rmin0));
double vesselRmin1 = dims.attr<double>(_Unicode(rmin1));
double vesselRmax0 = dims.attr<double>(_Unicode(rmax0));
double vesselRmax1 = dims.attr<double>(_Unicode(rmax1));
double vesselRmax2 = dims.attr<double>(_Unicode(rmax2));
double snoutLength = dims.attr<double>(_Unicode(snout_length));
int nSectors = getAttrOrDefault<int>(dims, _Unicode(nsectors), 6);
double wallThickness = getAttrOrDefault<double>(dims, _Unicode(wall_thickness), 0.5*cm);
double windowThickness = getAttrOrDefault<double>(dims, _Unicode(window_thickness), 0.1*cm);
auto vesselMat = desc.material(getAttrOrDefault(detElem, _Unicode(material), "Aluminum"));
auto gasvolMat = desc.material(getAttrOrDefault(detElem, _Unicode(gas), "AirOptical"));
auto vesselVis = desc.visAttributes(detElem.attr<std::string>(_Unicode(vis_vessel)));
auto gasvolVis = desc.visAttributes(detElem.attr<std::string>(_Unicode(vis_gas)));
// - radiator (applies to aerogel and filter)
auto radiatorElem = detElem.child(_Unicode(radiator));
double radiatorRmin = getAttrOrDefault<double>(radiatorElem, _Unicode(rmin), 10.*cm);
double radiatorRmax = getAttrOrDefault<double>(radiatorElem, _Unicode(rmax), 80.*cm);
double radiatorPhiw = getAttrOrDefault<double>(radiatorElem, _Unicode(phiw), 2*M_PI/nSectors);
double radiatorPitch = getAttrOrDefault<double>(radiatorElem, _Unicode(pitch), 0.*degree);
double radiatorFrontplane = getAttrOrDefault<double>(radiatorElem, _Unicode(frontplane), 2.5*cm);
// - aerogel
auto aerogelElem = radiatorElem.child(_Unicode(aerogel));
auto aerogelMat = desc.material(aerogelElem.attr<std::string>(_Unicode(material)));
auto aerogelVis = desc.visAttributes(aerogelElem.attr<std::string>(_Unicode(vis)));
double aerogelThickness = getAttrOrDefault<double>(aerogelElem, _Unicode(thickness), 2.5*cm);
// - filter
auto filterElem = radiatorElem.child(_Unicode(filter));
auto filterMat = desc.material(filterElem.attr<std::string>(_Unicode(material)));
auto filterVis = desc.visAttributes(filterElem.attr<std::string>(_Unicode(vis)));
double filterThickness = getAttrOrDefault<double>(filterElem, _Unicode(thickness), 2.5*cm);
// - mirror
auto mirrorElem = detElem.child(_Unicode(mirror));
auto mirrorMat = desc.material(mirrorElem.attr<std::string>(_Unicode(material)));
auto mirrorVis = desc.visAttributes(mirrorElem.attr<std::string>(_Unicode(vis)));
auto mirrorSurf = surfMgr.opticalSurface(getAttrOrDefault(mirrorElem, _Unicode(surface), "MirrorOpticalSurface"));
double mirrorBackplane = getAttrOrDefault<double>(mirrorElem, _Unicode(backplane), 240.*cm);
double mirrorThickness = getAttrOrDefault<double>(mirrorElem, _Unicode(thickness), 2.*mm);
double mirrorRadius = getAttrOrDefault<double>(mirrorElem, _Unicode(radius), 190*cm);
double mirrorCenterX = getAttrOrDefault<double>(mirrorElem, _Unicode(centerx), 95*cm);
double mirrorRmin = getAttrOrDefault<double>(mirrorElem, _Unicode(rmin), 10.*cm);
double mirrorRmax = getAttrOrDefault<double>(mirrorElem, _Unicode(rmax), 150.*cm);
double mirrorPhiw = getAttrOrDefault<double>(mirrorElem, _Unicode(phiw), 2*M_PI/nSectors);
int mirrorDebug = getAttrOrDefault<int>(mirrorElem, _Unicode(debug), 0);
// - sensor module
auto sensorElem = detElem.child(_Unicode(sensors)).child(_Unicode(module));
auto sensorMat = desc.material(sensorElem.attr<std::string>(_Unicode(material)));
auto sensorVis = desc.visAttributes(sensorElem.attr<std::string>(_Unicode(vis)));
auto sensorSurf = surfMgr.opticalSurface(getAttrOrDefault(sensorElem, _Unicode(surface), "MirrorOpticalSurface"));
double sensorSide = sensorElem.attr<double>(_Unicode(side));
double sensorGap = sensorElem.attr<double>(_Unicode(gap));
double sensorThickness = sensorElem.attr<double>(_Unicode(thickness));
// - sensor sphere
auto sensorSphElem = detElem.child(_Unicode(sensors)).child(_Unicode(sphere));
double sensorSphRadius = sensorSphElem.attr<double>(_Unicode(radius));
double sensorSphCenterX = sensorSphElem.attr<double>(_Unicode(centerx));
double sensorSphCenterY = sensorSphElem.attr<double>(_Unicode(centery));
double sensorSphCenterZ = sensorSphElem.attr<double>(_Unicode(centerz));
int sensorSphDebug = getAttrOrDefault<int>(sensorSphElem, _Unicode(debug), 0);
// - sensor sphere patch cuts
auto sensorSphPatchElem = detElem.child(_Unicode(sensors)).child(_Unicode(sphericalpatch));
double sensorSphPatchThetaMin = sensorSphPatchElem.attr<double>(_Unicode(thetamin));
double sensorSphPatchThetaMax = sensorSphPatchElem.attr<double>(_Unicode(thetamax));
double sensorSphPatchWidthFactor = sensorSphPatchElem.attr<double>(_Unicode(widthfactor));
double sensorSphPatchTaper = sensorSphPatchElem.attr<double>(_Unicode(taper));
// BUILD VESSEL ====================================================================
/* - `vessel`: aluminum enclosure, the mother volume of the dRICh
* - `gasvol`: gas volume, which fills `vessel`; all other volumes defined below
* are children of `gasvol`
* - the dRICh vessel geometry has two regions: the snout refers to the conic region
* in the front, housing the aerogel, while the tank refers to the cylindrical
* region, housing the rest of the detector components
*/
// snout solids
double boreDelta = vesselRmin1 - vesselRmin0;
Cone vesselSnout(
snoutLength/2.0,
vesselRmin0,
vesselRmax0,
vesselRmin0 + boreDelta * snoutLength / vesselLength,
vesselRmax1
);
Cone gasvolSnout(
/* note: `gasvolSnout` extends a bit into the tank, so it touches `gasvolTank`
* - the extension distance is equal to the tank `windowThickness`, so the
* length of `gasvolSnout` == length of `vesselSnout`
* - the extension backplane radius is calculated using similar triangles
*/
snoutLength/2.0,
vesselRmin0 + wallThickness,
vesselRmax0 - wallThickness,
vesselRmin0 + boreDelta * (snoutLength-windowThickness) / vesselLength + wallThickness,
vesselRmax1 - wallThickness + windowThickness * (vesselRmax1 - vesselRmax0) / snoutLength
);
// tank solids
Cone vesselTank(
(vesselLength - snoutLength)/2.0,
vesselSnout.rMin2(),
vesselRmax2,
vesselRmin1,
vesselRmax2
);
Cone gasvolTank(
(vesselLength - snoutLength)/2.0 - windowThickness,
gasvolSnout.rMin2(),
vesselRmax2 - wallThickness,
vesselRmin1 + wallThickness,
vesselRmax2 - wallThickness
);
// snout + tank solids
UnionSolid vesselSolid(
vesselTank,
vesselSnout,
Position(0., 0., -vesselLength/2.)
);
UnionSolid gasvolSolid(
gasvolTank,
gasvolSnout,
Position(0., 0., -vesselLength/2. + windowThickness)
);
// volumes
Volume vesselVol(detName, vesselSolid, vesselMat);
Volume gasvolVol(detName + "_gas", gasvolSolid, gasvolMat);
vesselVol.setVisAttributes(vesselVis);
gasvolVol.setVisAttributes(gasvolVis);
// reference position
auto snoutFront = Position(0., 0., -(vesselLength + snoutLength)/2.);
// sensitive detector type
sens.setType("photoncounter");
// SECTOR LOOP //////////////////////////////////
for(int isec=0; isec<nSectors; isec++) {
if(mirrorDebug*isec>0 || sensorSphDebug*isec>0) continue; // if debugging, draw only 1 sector
double sectorRotation = isec * 360/nSectors * degree; // sector rotation about z axis
// BUILD RADIATOR ====================================================================
// derived attributes
auto radiatorPos = Position(0., 0., radiatorFrontplane) + snoutFront;
// solid and volume: create aerogel and filter sectors
Tube aerogelSolid(radiatorRmin, radiatorRmax, aerogelThickness/2, -radiatorPhiw/2.0, radiatorPhiw/2.0);
Tube filterSolid( radiatorRmin, radiatorRmax, filterThickness/2, -radiatorPhiw/2.0, radiatorPhiw/2.0);
Volume aerogelVol("aerogel_v", aerogelSolid, aerogelMat);
Volume filterVol( "filter_v", filterSolid, filterMat);
aerogelVol.setVisAttributes(aerogelVis);
filterVol.setVisAttributes(filterVis);
// placement
auto aerogelPV = gasvolVol.placeVolume(aerogelVol,
RotationZ(sectorRotation) // rotate about beam axis to sector
* Translation3D(radiatorPos.x(), radiatorPos.y(), radiatorPos.z()) // re-center to snoutFront
* RotationY(radiatorPitch) // change polar angle to specified pitch
);
auto filterPV = gasvolVol.placeVolume(filterVol,
RotationZ(sectorRotation) // rotate about beam axis to sector
* Translation3D(radiatorPos.x(), radiatorPos.y(), radiatorPos.z()) // re-center to snoutFront
* RotationY(radiatorPitch) // change polar angle
* Translation3D(0., 0., (aerogelThickness+filterThickness)/2.) // move to aerogel backplane
);
// properties
// TODO [critical]: define skin properties for aerogel and filter
DetElement aerogelDE(det, Form("aerogel_de%d", isec), isec);
aerogelDE.setPlacement(aerogelPV);
//SkinSurface aerogelSkin(desc, aerogelDE, Form("mirror_optical_surface%d", isec), aerogelSurf, aerogelVol);
//aerogelSkin.isValid();
DetElement filterDE(det, Form("filter_de%d", isec), isec);
filterDE.setPlacement(filterPV);
//SkinSurface filterSkin(desc, filterDE, Form("mirror_optical_surface%d", isec), filterSurf, filterVol);
//filterSkin.isValid();
// BUILD MIRROR ====================================================================
// derived attributes
auto mirrorPos = Position(mirrorCenterX, 0., mirrorBackplane) + snoutFront;
double mirrorThetaRot = std::asin(mirrorCenterX/mirrorRadius);
double mirrorTheta1 = mirrorThetaRot - std::asin((mirrorCenterX-mirrorRmin)/mirrorRadius);
double mirrorTheta2 = mirrorThetaRot + std::asin((mirrorRmax-mirrorCenterX)/mirrorRadius);
// if debugging, draw full sphere
if(mirrorDebug>0) { mirrorTheta1=0; mirrorTheta2=M_PI; mirrorPhiw=2*M_PI; };
// solid and volume: create sphere at origin, with specified angular limits
Sphere mirrorSolid(
mirrorRadius-mirrorThickness,
mirrorRadius,
mirrorTheta1,
mirrorTheta2,
-mirrorPhiw/2.0,
mirrorPhiw/2.0
);
Volume mirrorVol("mirror_v", mirrorSolid, mirrorMat);
mirrorVol.setVisAttributes(mirrorVis);
// placement (note: transformations are in reverse order)
auto mirrorPV = gasvolVol.placeVolume(mirrorVol,
RotationZ(sectorRotation) // rotate about beam axis to sector
* Translation3D(0,0,-mirrorRadius) // move longitudinally so it intersects snoutFront
* Translation3D(mirrorPos.x(), mirrorPos.y(), mirrorPos.z()) // re-center to snoutFront
* RotationY(-mirrorThetaRot) // rotate about origin
);
// properties
DetElement mirrorDE(det, Form("mirror_de%d", isec), isec);
mirrorDE.setPlacement(mirrorPV);
SkinSurface mirrorSkin(desc, mirrorDE, Form("mirror_optical_surface%d", isec), mirrorSurf, mirrorVol);
mirrorSkin.isValid();
// BUILD SENSORS ====================================================================
// if debugging sphere properties, restrict number of sensors drawn
if(sensorSphDebug>0) { sensorSide = 2*M_PI*sensorSphRadius / 64; };
// solid and volume: single sensor module
Box sensorSolid(sensorSide/2., sensorSide/2., sensorThickness/2.);
Volume sensorVol("sensor_v", sensorSolid, sensorMat);
sensorVol.setVisAttributes(sensorVis);
// sensitivity
sensorVol.setSensitiveDetector(sens);
// SENSOR MODULE LOOP ------------------------
/* ALGORITHM: generate sphere of positions
* - NOTE: there are two coordinate systems here:
* - "global" the main ATHENA coordinate system
* - "generator" (vars end in `Gen`) is a local coordinate system for
* generating points on a sphere; it is related to the global system by
* a rotation; we do this so the "patch" (subset of generated
* positions) of sensors we choose to build is near the equator, where
* point distribution is more uniform
* - PROCEDURE: loop over `thetaGen`, with subloop over `phiGen`, each divided evenly
* - the number of points to generate depends how many sensors (+`sensorGap`)
* can fit within each ring of constant `thetaGen` or `phiGen`
* - we divide the relevant circumference by the sensor
* size(+`sensorGap`), and this number is allowed to be a fraction,
* because likely we don't care about generating a full sphere and
* don't mind a "seam" at the overlap point
* - if we pick a patch of the sphere near the equator, and not near
* the poles or seam, the sensor distribution will appear uniform
*/
// initialize module number for this sector
int imod=1;
// thetaGen loop: iterate less than "0.5 circumference / sensor size" times
double nTheta = M_PI*sensorSphRadius / (sensorSide+sensorGap);
for(int t=0; t<(int)(nTheta+0.5); t++) {
double thetaGen = t/((double)nTheta) * M_PI;
// phiGen loop: iterate less than "circumference at this latitude / sensor size" times
double nPhi = 2*M_PI * sensorSphRadius * std::sin(thetaGen) / (sensorSide+sensorGap);
for(int p=0; p<(int)(nPhi+0.5); p++) {
double phiGen = p/((double)nPhi) * 2*M_PI - M_PI; // shift to [-pi,pi]
// determine global phi and theta
// - convert {radius,thetaGen,phiGen} -> {xGen,yGen,zGen}
double xGen = sensorSphRadius * std::sin(thetaGen) * std::cos(phiGen);
double yGen = sensorSphRadius * std::sin(thetaGen) * std::sin(phiGen);
double zGen = sensorSphRadius * std::cos(thetaGen);
// - convert {xGen,yGen,zGen} -> global {x,y,z} via rotation
double x = zGen;
double y = xGen;
double z = yGen;
// - convert global {x,y,z} -> global {phi,theta}
double phi = std::atan2(y,x);
double theta = std::acos(z/sensorSphRadius);
// cut spherical patch
// TODO [low priority]: instead of cutting a patch with complicated parameters,
// can we use something simpler such as Union or
// Intersection of solids?
// - applied on global coordinates
// - theta cuts are signed, since we will offset the patch along +x;
// from the offset position, toward barrel is positive, toward beam is negative
double thetaSigned = (x<0?-1:1) * theta;
// - position of yz planes, associated to theta cuts
double xmin = sensorSphRadius * std::sin(sensorSphPatchThetaMin/2);
double xmax = sensorSphRadius * std::sin(sensorSphPatchThetaMax/2);
// - we want a phi wedge, but offset from the origin to allow more width, so
// define phiCheck to account for the offset; the amount of the offset,
// and hence the width, is controlled by `sensorSphPatchWidthFactor`
double phiCheck = std::atan2(y,(x+sensorSphCenterX)/sensorSphPatchWidthFactor);
// - apply cuts (only if not debugging)
// - NOTE: use `x<xmax` for straight cuts, or `theta<sensorSphPatchThetaMax` for
// rounded cuts (which allows for more sensors)
if( ( std::fabs(phiCheck)<sensorSphPatchTaper && x>xmin && theta<sensorSphPatchThetaMax && z>0 )
|| sensorSphDebug>0
) {
// placement (note: transformations are in reverse order)
// - transformations operate on global coordinates; the corresponding
// generator coordinates are provided in the comments
auto sensorPV = gasvolVol.placeVolume(sensorVol,
RotationZ(sectorRotation) // rotate about beam axis to sector
* Translation3D(sensorSphCenterX, sensorSphCenterY, sensorSphCenterZ) // move sphere to specified center
* Translation3D(snoutFront.x(), snoutFront.y(), snoutFront.z()) // move sphere to reference position
* RotationX(phiGen) // rotate about `zGen`
* RotationZ(thetaGen) // rotate about `yGen`
* Translation3D(sensorSphRadius, 0., 0.) // push radially to spherical surface
* RotationY(M_PI/2) // rotate sensor to be compatible with generator coords
);
// properties
sensorPV.addPhysVolID("sector", isec).addPhysVolID("module", imod);
DetElement sensorDE(det, Form("sensor_de%d_%d", isec, imod), 10000*isec+imod);
sensorDE.setPlacement(sensorPV);
SkinSurface sensorSkin(desc, sensorDE, Form("sensor_optical_surface%d", isec), sensorSurf, sensorVol);
sensorSkin.isValid();
// increment sensor module number
imod++;
}; // end patch cuts
}; // end phiGen loop
}; // end thetaGen loop
// END SENSOR MODULE LOOP ------------------------
}; // END SECTOR LOOP //////////////////////////
// place gas volume
PlacedVolume gasvolPV = vesselVol.placeVolume(gasvolVol,Position(0, 0, 0));
DetElement gasvolDE(det, "gasvol_de", 0);
gasvolDE.setPlacement(gasvolPV);
// place mother volume (vessel)
Volume motherVol = desc.pickMotherVolume(det);
PlacedVolume vesselPV = motherVol.placeVolume(vesselVol,
Position(0, 0, vesselZ0) - snoutFront
);
vesselPV.addPhysVolID("system", detID);
det.setPlacement(vesselPV);
return det;
};
// clang-format off
DECLARE_DETELEMENT(athena_DRICH, createDetector)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment