5 # First attempt to make a GDML fragment generator for the DUNE vertical drift
6 # 10kt detector geometry with 3 views (2 orthogonal + induction at angle)
7 # The lower chamber is not added yet.
8 # !!!NOTE!!!: the readout is on a positive Y plane (drift along horizontal X)
9 # due to current reco limitations)
10 # No photon detectors declared
11 # Simplified treatment of inter-module dead spaces
13 # Created: Thu Oct 1 16:45:27 CEST 2020
14 # Vyacheslav Galymov <vgalymov@ipnl.in2p3.fr>
17 # VG: Added defs to enable use in the refactored sim framework
18 # VG: 23.02.21 Adjust plane dimensions to fit a given number of ch per side
19 # VG: 23.02.21 Group CRUs in CRPs
20 # Laura Paulucci (lpaulucc@fnal.gov): Sept 2021 PDS added.
21 # Use option -pds=1 for backup design (membrane only coverage).
22 # Default (pds=0) is the reference design (~4-pi).
23 # This is linked with a larger geometry to account for photon propagation, generate it with -k=4.
24 # Field Cage is turned on with reference and backup designs to match PDS option.
25 # For not including the pds, please use option -pds=-1
28 #################################################################################
30 # Each subroutine generates a fragment GDML file, and the last subroutine
31 # creates an XML file that make_gdml.pl will use to appropriately arrange
32 # the fragment GDML files to create the final desired DUNE GDML file,
33 # to be named by make_gdml output command
35 ##################################################################################
43 Math::BigFloat->precision(-16);
46 GetOptions( "help|h" => \$help,
47 "suffix|s:s" => \$suffix,
48 "output|o:s" => \$output,
49 "wires|w:s" => \$wires,
50 "workspace|k:s" => \$wkspc,
51 "pdsconfig|pds:s" => \$pdsconfig);
53 my $FieldCage_switch="on";
54 my $Cathode_switch="off";
58 # If the user requested help, print the usage notes and exit.
63 if ( ! defined $suffix )
65 # The user didn't supply a suffix, so append nothing to the file
71 # Otherwise, stick a "-" before the suffix, so that a suffix of
72 # "test" applied to filename.gdml becomes "filename-test.gdml".
73 $suffix = "-" . $suffix;
82 elsif ( $workspace != 0 )
84 print "\t\tCreating smaller workspace geometry.\n";
87 if ( ! defined $pdsconfig )
90 print "\t\tCreating reference design: 4-pi PDS converage.\n";
92 elsif ( $pdsconfig == 1 )
94 print "\t\tCreating backup design: membrane-only PDS coverage.\n";
97 # set wires on to be the default, unless given an input by the user
98 $wires_on = 1; # 1=on, 0=off
108 ##################################################################
109 ############## Parameters for One Readout Panel ##################
111 # parameters for 1.5 x 1.7 sub-unit Charge Readout Module / Unit
112 #$widthPCBActive = 169.0; # cm
113 #$lengthPCBActive = 150.0; # cm
115 # views and channel counts
116 %nChans = ('Ind1', 256, 'Ind1Bot', 128, 'Ind2', 320, 'Col', 288);
117 $nViews = keys %nChans;
118 #print "$nViews %nChans\n";
120 # first induction view
121 $wirePitchU = 0.8695; # cm
122 $wireAngleU = 131.63; #-48.37; # deg
124 # second induction view
126 $widthPCBActive = 168.00; #$wirePitchY * $nChans{'Ind2'};
128 # last collection view
130 $lengthPCBActive = 148.9009; #$wirePitchZ * $nChans{'Col'};
133 $borderCRM = 0.0; # border space aroud each CRM
135 $widthCRM_active = $widthPCBActive;
136 $lengthCRM_active = $lengthPCBActive;
138 $widthCRM = $widthPCBActive + 2 * $borderCRM;
139 $lengthCRM = $lengthPCBActive + 2 * $borderCRM;
141 $borderCRP = 0.5; # cm
143 # number of CRMs in y and z
147 # create a smaller geometry
148 if( $workspace == 1 )
154 # create a smaller geometry
155 if( $workspace == 2 )
161 # create a smaller geometry
162 if( $workspace == 3 )
168 # create pds geometry
169 if( $workspace == 4 )
176 # calculate tpc area based on number of CRMs and their dimensions
177 # each CRP should have a 2x2 CRMs
178 $widthTPCActive = $nCRM_x * $widthCRM + $nCRM_x * $borderCRP; # around 1200 for full module
179 $lengthTPCActive = $nCRM_z * $lengthCRM + $nCRM_z * $borderCRP; # around 6000 for full module
181 # active volume dimensions
182 $driftTPCActive = 650.0;
184 # model anode strips as wires of some diameter
186 $ReadoutPlane = $nViews * $padWidth; # 3 readout planes (no space b/w)!
188 ##################################################################
189 ############## Parameters for TPC and inner volume ###############
191 # inner volume dimensions of the cryostat
196 # width of gas argon layer on top
197 $HeightGaseousAr = 100;
199 if( $workspace != 0 )
201 #active tpc + 1.0 m buffer on each side
202 $Argon_x = $driftTPCActive + $HeightGaseousAr + $ReadoutPlane + 100;
203 $Argon_y = $widthTPCActive + 200;
204 $Argon_z = $lengthTPCActive + 200;
208 # size of liquid argon buffer
209 $xLArBuffer = $Argon_x - $driftTPCActive - $HeightGaseousAr - $ReadoutPlane;
210 $yLArBuffer = 0.5 * ($Argon_y - $widthTPCActive);
211 $zLArBuffer = 0.5 * ($Argon_z - $lengthTPCActive);
214 $SteelThickness = 0.12; # membrane
216 $Cryostat_x = $Argon_x + 2*$SteelThickness;
217 $Cryostat_y = $Argon_y + 2*$SteelThickness;
218 $Cryostat_z = $Argon_z + 2*$SteelThickness;
220 ##################################################################
221 ############## DetEnc and World relevant parameters #############
223 $SteelSupport_x = 100;
224 $SteelSupport_y = 100;
225 $SteelSupport_z = 100;
227 $FracMassOfSteel = 0.5; #The steel support is not a solid block, but a mixture of air and steel
228 $FracMassOfAir = 1 - $FracMassOfSteel;
231 $SpaceSteelSupportToWall = 100;
232 $SpaceSteelSupportToCeiling = 100;
234 $DetEncX = $Cryostat_x
235 + 2*($SteelSupport_x + $FoamPadding) + $SpaceSteelSupportToCeiling;
237 $DetEncY = $Cryostat_y
238 + 2*($SteelSupport_y + $FoamPadding) + 2*$SpaceSteelSupportToWall;
240 $DetEncZ = $Cryostat_z
241 + 2*($SteelSupport_z + $FoamPadding) + 2*$SpaceSteelSupportToWall;
243 $posCryoInDetEnc_x = - $DetEncX/2 + $SteelSupport_x + $FoamPadding + $Cryostat_x/2;
246 $RockThickness = 4000;
248 # We want the world origin to be vertically centered on active TPC
249 # This is to be added to the x and y position of every volume in volWorld
251 $OriginXSet = $DetEncX/2.0
256 - $driftTPCActive/2.0;
258 $OriginYSet = $DetEncY/2.0
259 - $SpaceSteelSupportToWall
264 - $widthTPCActive/2.0;
266 # We want the world origin to be at the very front of the fiducial volume.
267 # move it to the front of the enclosure, then back it up through the concrete/foam,
268 # then through the Cryostat shell, then through the upstream dead LAr (including the
269 # dead LAr on the edge of the TPC)
270 # This is to be added to the z position of every volume in volWorld
272 $OriginZSet = $DetEncZ/2.0
273 - $SpaceSteelSupportToWall
280 ##################################################################
281 ############## Field Cage Parameters ###############
282 $FieldShaperLongTubeLength = $lengthTPCActive;
283 $FieldShaperShortTubeLength = $widthTPCActive;
284 #$FieldShaperInnerRadius = 1.485;
285 #$FieldShaperOuterRadius = 1.685;
286 #$FieldShaperTorRad = 1.69;
287 $FieldShaperInnerRadius = 0.5; #cm
288 $FieldShaperOuterRadius = 2.285; #cm
289 $FieldShaperOuterRadiusSlim = 0.75; #cm
290 $FieldShaperTorRad = 2.3; #cm
292 $FieldShaperLength = $FieldShaperLongTubeLength + 2*$FieldShaperOuterRadius+ 2*$FieldShaperTorRad;
293 $FieldShaperWidth = $FieldShaperShortTubeLength + 2*$FieldShaperOuterRadius+ 2*$FieldShaperTorRad;
295 $FieldShaperSeparation = 6.0; #cm
296 $NFieldShapers = ($driftTPCActive/$FieldShaperSeparation) - 1;
298 $FieldCageSizeX = $FieldShaperSeparation*$NFieldShapers+2;
299 $FieldCageSizeY = $FieldShaperWidth+2;
300 $FieldCageSizeZ = $FieldShaperLength+2;
303 ####################################################################
304 ######################## ARAPUCA Dimensions ########################
307 $ArapucaOut_x = 65.0;
309 $ArapucaOut_z = 65.0;
313 $ArapucaAcceptanceWindow_x = 60.0;
314 $ArapucaAcceptanceWindow_y = 1.0;
315 $ArapucaAcceptanceWindow_z = 60.0;
316 $BlockPD_x = 0.5*$widthCRM_active - 6.35; #Sub-division of Frame (4 n x, 4 in z)
317 $BlockPD_z = 0.5*$lengthCRM_active - 6.25;
318 $GapPD = 0.5; #Size of supporting bars in Frame
319 $FrameToArapucaSpace = 1.0; #At this moment, should cover the thickness of Frame + small gap to prevent overlap. VALUE NEEDS TO BE CHECKED!!!
320 $FrameToArapucaSpaceLat = $yLArBuffer - 60.0; #Arapucas 60 cm behind FC. At this moment, should cover the thickness of Frame + small gap to prevent overlap. VALUE NEEDS TO BE CHECKED!!!
321 $VerticalPDdist = 75.0; #distance of arapucas (center to center) in the y direction
322 $HorizontalPDdist = 150.0; #distance of arapucas (center to center) in the x direction
324 #Positions of the 4 arapucas with respect to the Frame center --> arapucas over the cathode
325 $list_posx_bot[0]=-2*$BlockPD_x - 1.5*$GapPD + 0.5*$ArapucaOut_x;
326 $list_posz_bot[0]= 0.5*$BlockPD_z + $GapPD;
327 $list_posx_bot[1]=- $GapPD - 0.5*$ArapucaOut_x;
328 $list_posz_bot[1]=-1.5*$BlockPD_z - 1.5*$GapPD;
329 $list_posx_bot[2]=-$list_posx_bot[1];
330 $list_posz_bot[2]=-$list_posz_bot[1];
331 $list_posx_bot[3]=-$list_posx_bot[0];
332 $list_posz_bot[3]=-$list_posz_bot[0];
336 #+++++++++++++++++++++++++ End defining variables ++++++++++++++++++++++++++
339 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
340 #+++++++++++++++++++++++++++++++++++++++++ usage +++++++++++++++++++++++++++++++++++++++++
341 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
345 print "Usage: $0 [-h|--help] [-o|--output <fragments-file>] [-s|--suffix <string>]\n";
346 print " if -o is omitted, output goes to STDOUT; <fragments-file> is input to make_gdml.pl\n";
347 print " -s <string> appends the string to the file names; useful for multiple detector versions\n";
348 print " -h prints this message, then quits\n";
355 # Create the <define> fragment file name,
356 # add file to list of fragments,
358 $DEF = $basename."_Ext" . $suffix . ".gdml";
359 push (@gdmlFiles, $DEF);
361 open(DEF) or die("Could not open file $DEF for writing");
364 <?xml version='1.0'?>
367 <color name="magenta" R="0.0" G="1.0" B="0.0" A="1.0" />
368 <color name="green" R="0.0" G="1.0" B="0.0" A="1.0" />
369 <color name="red" R="1.0" G="0.0" B="0.0" A="1.0" />
370 <color name="blue" R="0.0" G="0.0" B="1.0" A="1.0" />
371 <color name="yellow" R="1.0" G="1.0" B="0.0" A="1.0" />
378 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
379 #++++++++++++++++++++++++++++++++++++++ gen_Define +++++++++++++++++++++++++++++++++++++++
380 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
385 # Create the <define> fragment file name,
386 # add file to list of fragments,
388 $DEF = $basename."_Def" . $suffix . ".gdml";
389 push (@gdmlFiles, $DEF);
391 open(DEF) or die("Could not open file $DEF for writing");
395 <?xml version='1.0'?>
405 <position name="posCryoInDetEnc" unit="cm" x="$posCryoInDetEnc_x" y="0" z="0"/>
406 <position name="posCenter" unit="cm" x="0" y="0" z="0"/>
407 <rotation name="rUWireAboutX" unit="deg" x="$wireAngleU" y="0" z="0"/>
408 <rotation name="rPlus90AboutX" unit="deg" x="90" y="0" z="0"/>
409 <rotation name="rPlus90AboutY" unit="deg" x="0" y="90" z="0"/>
410 <rotation name="rPlus90AboutXPlus90AboutY" unit="deg" x="90" y="90" z="0"/>
411 <rotation name="rMinus90AboutX" unit="deg" x="270" y="0" z="0"/>
412 <rotation name="rMinus90AboutY" unit="deg" x="0" y="270" z="0"/>
413 <rotation name="rMinus90AboutYMinus90AboutX" unit="deg" x="270" y="270" z="0"/>
414 <rotation name="rPlus180AboutX" unit="deg" x="180" y="0" z="0"/>
415 <rotation name="rPlus180AboutY" unit="deg" x="0" y="180" z="0"/>
416 <rotation name="rPlus180AboutXPlus180AboutY" unit="deg" x="180" y="180" z="0"/>
417 <rotation name="rIdentity" unit="deg" x="0" y="0" z="0"/>
424 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
425 #+++++++++++++++++++++++++++++++++++++ gen_Materials +++++++++++++++++++++++++++++++++++++
426 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
431 # Create the <materials> fragment file name,
432 # add file to list of output GDML fragments,
434 $MAT = $basename."_Materials" . $suffix . ".gdml";
435 push (@gdmlFiles, $MAT);
438 open(MAT) or die("Could not open file $MAT for writing");
440 # Add any materials special to this geometry by defining a mulitline string
441 # and passing it to the gdmlMaterials::gen_Materials() function.
443 <!-- preliminary values -->
444 <material name="AirSteelMixture" formula="AirSteelMixture">
445 <D value=" 0.001205*(1-$FracMassOfSteel) + 7.9300*$FracMassOfSteel " unit="g/cm3"/>
446 <fraction n="$FracMassOfSteel" ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
447 <fraction n="$FracMassOfAir" ref="Air"/>
449 <material name="vm2000" formula="vm2000">
450 <D value="1.2" unit="g/cm3"/>
451 <composite n="2" ref="carbon"/>
452 <composite n="4" ref="hydrogen"/>
456 # add the general materials used anywere
457 print MAT gdmlMaterials::gen_Materials( $asmix );
463 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
464 #++++++++++++++++++++++++++++++++++++++++ gen_TPC ++++++++++++++++++++++++++++++++++++++++
465 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
466 # line clip on the rectangle boundary
477 if( abs( nx ) < tol ){
478 push( @endpts, ($x0, 0) );
479 push( @endpts, ($x0, $rcw) );
482 if( abs( ny ) < tol ){
483 push( @endpts, (0, $y0) );
484 push( @endpts, ($rcl, $y0) );
488 # left border at x = 0
489 my $y = $y0 - $x0 * $ny/$nx;
490 if( $y >= 0 && $y <= $rcw ){
491 push( @endpts, (0, $y) );
494 # right border at x = l
495 $y = $y0 + ($rcl-$x0) * $ny/$nx;
496 if( $y >= 0 && $y <= $rcw ){
497 push( @endpts, ($rcl, $y) );
498 if( scalar(@endpts) == 4 ){
503 # bottom border at y = 0
504 my $x = $x0 - $y0 * $nx/$ny;
505 if( $x >= 0 && $x <= $rcl ){
506 push( @endpts, ($x, 0) );
507 if( scalar(@endpts) == 4 ){
512 # top border at y = w
513 $x = $x0 + ($rcw-$y0)* $nx/$ny;
514 if( $x >= 0 && $x <= $rcl ){
515 push( @endpts, ($x, $rcw) );
523 my $length = $_[0]; #
526 my $nchb = $_[3]; # nch per bottom side
528 my $theta = $_[5]; # deg
531 $theta = $theta * pi()/180.0;
532 my @dirw = (cos($theta), sin($theta));
533 my @dirp = (cos($theta - pi()/2), sin($theta - pi()/2));
537 if( $alpha > pi()/2 ){
538 $alpha = pi() - $alpha;
540 my $dX = $pitch / sin( $alpha );
541 my $dY = $pitch / sin( pi()/2 - $alpha );
543 $length = $dX * $nchb;
546 $width = $dY * ($nch - $nchb);
557 #print "origin : @orig\n";
558 #print "pitch dir : @dirp\n";
559 #print "wire dir : @dirw\n";
560 #print "$length x $width cm2\n";
564 my $offset = $pitch/2;
565 foreach my $ch (0..$nch-1){
566 #print "Processing $ch\n";
568 # calculate reference point for this strip
570 $wcn[0] = $orig[0] + $offset * $dirp[0];
571 $wcn[1] = $orig[1] + $offset * $dirp[1];
573 # line clip on the rectangle boundary
574 @endpts = lineClip( $wcn[0], $wcn[1], $dirw[0], $dirw[1], $length, $width );
576 if( scalar(@endpts) != 4 ){
577 print "Could not find end points for wire $ch : @endpts\n";
578 $offset = $offset + $pitch;
582 # re-center on the mid-point
583 $endpts[0] -= $length/2;
584 $endpts[2] -= $length/2;
585 $endpts[1] -= $width/2;
586 $endpts[3] -= $width/2;
588 # calculate the strip center in the rectangle of CRU
589 $wcn[0] = ($endpts[0] + $endpts[2])/2;
590 $wcn[1] = ($endpts[1] + $endpts[3])/2;
592 # calculate the length
593 my $dx = $endpts[0] - $endpts[2];
594 my $dy = $endpts[1] - $endpts[3];
595 my $wlen = sqrt($dx**2 + $dy**2);
597 # put all info together
598 my @wire = ($ch, $wcn[0], $wcn[1], $wlen);
599 push( @wire, @endpts );
600 push( @winfo, \@wire);
601 $offset = $offset + $pitch;
611 my $TPCActive_x = $driftTPCActive;
612 my $TPCActive_y = $widthCRM_active;
613 my $TPCActive_z = $lengthCRM_active;
616 my $TPC_x = $TPCActive_x + $ReadoutPlane;
617 my $TPC_y = $widthCRM;
618 my $TPC_z = $lengthCRM;
620 print " TPC dimensions : $TPC_x x $TPC_y x $TPC_z\n";
622 $TPC = $basename."_TPC" . $suffix . ".gdml";
623 push (@gdmlFiles, $TPC);
625 open(TPC) or die("Could not open file $TPC for writing");
627 # The standard XML prefix and starting the gdml
629 <?xml version='1.0'?>
633 # compute wires for 1st induction
635 if( $wires_on == 1 ){
636 @winfo = gen_Wires( 0, 0, # $TPCActive_y,
637 $nChans{'Ind1'}, $nChans{'Ind1Bot'},
638 $wirePitchU, $wireAngleU, $padWidth );
641 # All the TPC solids save the wires.
652 <box name="CRMUPlane"
657 <box name="CRMYPlane"
662 <box name="CRMZPlane"
667 <box name="CRMActive"
674 #++++++++++++++++++++++++++++ Wire Solids ++++++++++++++++++++++++++++++
677 foreach my $wire (@winfo) {
678 my $wid = $wire->[0];
679 my $wln = $wire->[3];
681 <tube name="CRMWireU$wid"
685 aunit="deg" lunit="cm"/>
690 <tube name="CRMWireY"
694 aunit="deg" lunit="cm"/>
695 <tube name="CRMWireZ"
699 aunit="deg" lunit="cm"/>
707 # Begin structure and create wire logical volumes
710 <volume name="volTPCActive">
711 <materialref ref="LAr"/>
712 <solidref ref="CRMActive"/>
713 <auxiliary auxtype="SensDet" auxvalue="SimEnergyDeposit"/>
714 <auxiliary auxtype="StepLimit" auxunit="cm" auxvalue="0.5208*cm"/>
715 <auxiliary auxtype="Efield" auxunit="V/cm" auxvalue="500*V/cm"/>
716 <colorref ref="blue"/>
722 foreach my $wire (@winfo)
724 my $wid = $wire->[0];
726 <volume name="volTPCWireU$wid">
727 <materialref ref="Copper_Beryllium_alloy25"/>
728 <solidref ref="CRMWireU$wid"/>
734 <volume name="volTPCWireY">
735 <materialref ref="Copper_Beryllium_alloy25"/>
736 <solidref ref="CRMWireY"/>
738 <volume name="volTPCWireZ">
739 <materialref ref="Copper_Beryllium_alloy25"/>
740 <solidref ref="CRMWireZ"/>
744 # 1st induction plane
746 <volume name="volTPCPlaneU">
747 <materialref ref="LAr"/>
748 <solidref ref="CRMUPlane"/>
750 if ($wires_on==1) # add wires to U plane
752 # the coordinates were computed with a corner at (0,0)
753 # so we need to move to plane coordinates
754 my $offsetZ = 0; #-0.5 * $TPCActive_z;
755 my $offsetY = 0; #-0.5 * $TPCActive_y;
757 foreach my $wire (@winfo) {
758 my $wid = $wire->[0];
759 my $zpos = $wire->[1] + $offsetZ;
760 my $ypos = $wire->[2] + $offsetY;
763 <volumeref ref="volTPCWireU$wid"/>
764 <position name="posWireU$wid" unit="cm" x="0" y="$ypos" z="$zpos"/>
765 <rotationref ref="rUWireAboutX"/>
774 # 2nd induction plane
776 <volume name="volTPCPlaneY">
777 <materialref ref="LAr"/>
778 <solidref ref="CRMYPlane"/>
781 if ($wires_on==1) # add wires to Y plane (plane with wires reading y position)
783 for(my $i=0;$i<$nChans{'Ind2'};++$i)
785 #my $ypos = -0.5 * $TPCActive_y + ($i+0.5)*$wirePitchY + 0.5*$padWidth;
786 my $ypos = ($i + 0.5 - $nChans{'Ind2'}/2)*$wirePitchY;
787 if( (0.5 * $TPCActive_y - abs($ypos)) < 0 ){
788 die "Cannot place wire $i in view Y, as plane is too small\n";
792 <volumeref ref="volTPCWireY"/>
793 <position name="posWireY$i" unit="cm" x="0" y="$ypos" z="0"/>
794 <rotationref ref="rIdentity"/>
805 <volume name="volTPCPlaneZ">
806 <materialref ref="LAr"/>
807 <solidref ref="CRMZPlane"/>
809 if ($wires_on==1) # add wires to Z plane (plane with wires reading z position)
811 for(my $i=0;$i<$nChans{'Col'};++$i)
813 #my $zpos = -0.5 * $TPCActive_z + ($i+0.5)*$wirePitchZ + 0.5*$padWidth;
814 my $zpos = ($i + 0.5 - $nChans{'Col'}/2)*$wirePitchZ;
815 if( (0.5 * $TPCActive_z - abs($zpos)) < 0 ){
816 die "Cannot place wire $i in view Z, as plane is too small\n";
820 <volumeref ref="volTPCWireZ"/>
821 <position name="posWireZ$i" unit="cm" x="0" y="0" z="$zpos"/>
822 <rotationref ref="rPlus90AboutX"/>
832 $posUplane[0] = 0.5*$TPC_x - 2.5*$padWidth;
836 $posYplane[0] = 0.5*$TPC_x - 1.5*$padWidth;
840 $posZplane[0] = 0.5*$TPC_x - 0.5*$padWidth;
844 $posTPCActive[0] = -$ReadoutPlane/2;
845 $posTPCActive[1] = 0;
846 $posTPCActive[2] = 0;
849 #wrap up the TPC file
851 <volume name="volTPC">
852 <materialref ref="LAr"/>
853 <solidref ref="CRM"/>
855 <volumeref ref="volTPCPlaneU"/>
856 <position name="posPlaneU" unit="cm"
857 x="$posUplane[0]" y="$posUplane[1]" z="$posUplane[2]"/>
858 <rotationref ref="rIdentity"/>
861 <volumeref ref="volTPCPlaneY"/>
862 <position name="posPlaneY" unit="cm"
863 x="$posYplane[0]" y="$posYplane[1]" z="$posYplane[2]"/>
864 <rotationref ref="rIdentity"/>
867 <volumeref ref="volTPCPlaneZ"/>
868 <position name="posPlaneZ" unit="cm"
869 x="$posZplane[0]" y="$posZplane[1]" z="$posZplane[2]"/>
870 <rotationref ref="rIdentity"/>
873 <volumeref ref="volTPCActive"/>
874 <position name="posActive" unit="cm"
875 x="$posTPCActive[0]" y="$posTPCAtive[1]" z="$posTPCActive[2]"/>
876 <rotationref ref="rIdentity"/>
880 ## x="@{[$posTPCActive[0]+$padWidth]}" y="$posTPCActive[1]" z="$posTPCActive[2]"/>
890 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
891 #++++++++++++++++++++++++++++++++++++++ gen_FieldCage ++++++++++++++++++++++++++++++++++++
892 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
896 $FieldCage = $basename."_FieldCage" . $suffix . ".gdml";
897 push (@gdmlFiles, $FieldCage);
898 $FieldCage = ">" . $FieldCage;
899 open(FieldCage) or die("Could not open file $FieldCage for writing");
901 # The standard XML prefix and starting the gdml
902 print FieldCage <<EOF;
903 <?xml version='1.0'?>
906 # The printing solids used in the Field Cage
907 #print "lengthTPCActive : $lengthTPCActive \n";
908 #print "widthTPCActive : $widthTPCActive \n";
911 print FieldCage <<EOF;
913 <torus name="FieldShaperCorner" rmin="$FieldShaperInnerRadius" rmax="$FieldShaperOuterRadius" rtor="$FieldShaperTorRad" deltaphi="90" startphi="0" aunit="deg" lunit="cm"/>
914 <tube name="FieldShaperLongtube" rmin="$FieldShaperInnerRadius" rmax="$FieldShaperOuterRadius" z="$FieldShaperLongTubeLength" deltaphi="360" startphi="0" aunit="deg" lunit="cm"/>
915 <tube name="FieldShaperLongtubeSlim" rmin="$FieldShaperInnerRadius" rmax="$FieldShaperOuterRadiusSlim" z="$FieldShaperLongTubeLength" deltaphi="360" startphi="0" aunit="deg" lunit="cm"/>
916 <tube name="FieldShaperShorttube" rmin="$FieldShaperInnerRadius" rmax="$FieldShaperOuterRadius" z="$FieldShaperShortTubeLength" deltaphi="360" startphi="0" aunit="deg" lunit="cm"/>
918 <union name="FSunion1">
919 <first ref="FieldShaperLongtube"/>
920 <second ref="FieldShaperCorner"/>
921 <position name="esquinapos1" unit="cm" x="@{[-$FieldShaperTorRad]}" y="0" z="@{[0.5*$FieldShaperLongTubeLength]}"/>
922 <rotation name="rot1" unit="deg" x="90" y="0" z="0" />
925 <union name="FSunion2">
926 <first ref="FSunion1"/>
927 <second ref="FieldShaperShorttube"/>
928 <position name="esquinapos2" unit="cm" x="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[+0.5*$FieldShaperLongTubeLength+$FieldShaperTorRad]}"/>
929 <rotation name="rot2" unit="deg" x="0" y="90" z="0" />
932 <union name="FSunion3">
933 <first ref="FSunion2"/>
934 <second ref="FieldShaperCorner"/>
935 <position name="esquinapos3" unit="cm" x="@{[-$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[0.5*$FieldShaperLongTubeLength]}"/>
936 <rotation name="rot3" unit="deg" x="90" y="270" z="0" />
939 <union name="FSunion4">
940 <first ref="FSunion3"/>
941 <second ref="FieldShaperLongtube"/>
942 <position name="esquinapos4" unit="cm" x="@{[-$FieldShaperShortTubeLength-2*$FieldShaperTorRad]}" y="0" z="0"/>
945 <union name="FSunion5">
946 <first ref="FSunion4"/>
947 <second ref="FieldShaperCorner"/>
948 <position name="esquinapos5" unit="cm" x="@{[-$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength]}"/>
949 <rotation name="rot5" unit="deg" x="90" y="180" z="0" />
952 <union name="FSunion6">
953 <first ref="FSunion5"/>
954 <second ref="FieldShaperShorttube"/>
955 <position name="esquinapos6" unit="cm" x="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength-$FieldShaperTorRad]}"/>
956 <rotation name="rot6" unit="deg" x="0" y="90" z="0" />
959 <union name="FieldShaperSolid">
960 <first ref="FSunion6"/>
961 <second ref="FieldShaperCorner"/>
962 <position name="esquinapos7" unit="cm" x="@{[-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength]}"/>
963 <rotation name="rot7" unit="deg" x="90" y="90" z="0" />
966 <union name="FSunionSlim1">
967 <first ref="FieldShaperLongtubeSlim"/>
968 <second ref="FieldShaperCorner"/>
969 <position name="esquinapos1" unit="cm" x="@{[-$FieldShaperTorRad]}" y="0" z="@{[0.5*$FieldShaperLongTubeLength]}"/>
970 <rotation name="rot1" unit="deg" x="90" y="0" z="0" />
973 <union name="FSunionSlim2">
974 <first ref="FSunionSlim1"/>
975 <second ref="FieldShaperShorttube"/>
976 <position name="esquinapos2" unit="cm" x="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[+0.5*$FieldShaperLongTubeLength+$FieldShaperTorRad]}"/>
977 <rotation name="rot2" unit="deg" x="0" y="90" z="0" />
980 <union name="FSunionSlim3">
981 <first ref="FSunionSlim2"/>
982 <second ref="FieldShaperCorner"/>
983 <position name="esquinapos3" unit="cm" x="@{[-$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[0.5*$FieldShaperLongTubeLength]}"/>
984 <rotation name="rot3" unit="deg" x="90" y="270" z="0" />
987 <union name="FSunionSlim4">
988 <first ref="FSunionSlim3"/>
989 <second ref="FieldShaperLongtubeSlim"/>
990 <position name="esquinapos4" unit="cm" x="@{[-$FieldShaperShortTubeLength-2*$FieldShaperTorRad]}" y="0" z="0"/>
993 <union name="FSunionSlim5">
994 <first ref="FSunionSlim4"/>
995 <second ref="FieldShaperCorner"/>
996 <position name="esquinapos5" unit="cm" x="@{[-$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength]}"/>
997 <rotation name="rot5" unit="deg" x="90" y="180" z="0" />
1000 <union name="FSunionSlim6">
1001 <first ref="FSunionSlim5"/>
1002 <second ref="FieldShaperShorttube"/>
1003 <position name="esquinapos6" unit="cm" x="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength-$FieldShaperTorRad]}"/>
1004 <rotation name="rot6" unit="deg" x="0" y="90" z="0" />
1007 <union name="FieldShaperSolidSlim">
1008 <first ref="FSunionSlim6"/>
1009 <second ref="FieldShaperCorner"/>
1010 <position name="esquinapos7" unit="cm" x="@{[-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength]}"/>
1011 <rotation name="rot7" unit="deg" x="90" y="90" z="0" />
1018 print FieldCage <<EOF;
1021 <volume name="volFieldShaper">
1022 <materialref ref="Al2O3"/>
1023 <solidref ref="FieldShaperSolid"/>
1025 <volume name="volFieldShaperSlim">
1026 <materialref ref="Al2O3"/>
1027 <solidref ref="FieldShaperSolidSlim"/>
1034 print FieldCage <<EOF;
1043 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1044 #++++++++++++++++++++++++++++++++++++++ gen_Cryostat +++++++++++++++++++++++++++++++++++++
1045 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1050 # Create the cryostat fragment file name,
1051 # add file to list of output GDML fragments,
1053 $CRYO = $basename."_Cryostat" . $suffix . ".gdml";
1054 push (@gdmlFiles, $CRYO);
1055 $CRYO = ">" . $CRYO;
1056 open(CRYO) or die("Could not open file $CRYO for writing");
1059 # The standard XML prefix and starting the gdml
1061 <?xml version='1.0'?>
1065 # All the cryostat solids.
1066 # External active are two side volumes for generating light outside the field cage (no top or bottom buffers included)
1069 <box name="Cryostat" lunit="cm"
1074 <box name="ArgonInterior" lunit="cm"
1079 <box name="GaseousArgon" lunit="cm"
1080 x="$HeightGaseousAr"
1084 <box name="ExternalAuxOut" lunit="cm"
1085 x="$Argon_x - $xLArBuffer"
1086 y="$Argon_y - 2*$ArapucaOut_y - 2*$FrameToArapucaSpaceLat"
1089 <box name="ExternalAuxIn" lunit="cm"
1094 <subtraction name="ExternalActive">
1095 <first ref="ExternalAuxOut"/>
1096 <second ref="ExternalAuxIn"/>
1099 <subtraction name="SteelShell">
1100 <first ref="Cryostat"/>
1101 <second ref="ArgonInterior"/>
1108 #Double sided detectors should only be included when both top and bottom volumes become available
1109 #Optical sensitive volumes cannot be rotated because Larsoft cannot pick up the rotation when obtinaing the lengths needed for the semi-analytic model --> two acceptance windows for single sided lateral and cathode
1112 <box name="ArapucaOut" lunit="cm"
1113 x="@{[$ArapucaOut_x]}"
1114 y="@{[$ArapucaOut_y]}"
1115 z="@{[$ArapucaOut_z]}"/>
1117 <box name="ArapucaIn" lunit="cm"
1118 x="@{[$ArapucaIn_x]}"
1119 y="@{[$ArapucaOut_y]}"
1120 z="@{[$ArapucaIn_z]}"/>
1122 <subtraction name="ArapucaWalls">
1123 <first ref="ArapucaOut"/>
1124 <second ref="ArapucaIn"/>
1125 <position name="posArapucaSub" x="0" y="@{[$ArapucaOut_y/2.0]}" z="0." unit="cm"/>
1128 <box name="ArapucaAcceptanceWindow" lunit="cm"
1129 x="@{[$ArapucaAcceptanceWindow_x]}"
1130 y="@{[$ArapucaAcceptanceWindow_y]}"
1131 z="@{[$ArapucaAcceptanceWindow_z]}"/>
1133 <box name="ArapucaDoubleIn" lunit="cm"
1134 x="@{[$ArapucaIn_x]}"
1135 y="@{[$ArapucaOut_y+1.0]}"
1136 z="@{[$ArapucaIn_z]}"/>
1138 <subtraction name="ArapucaDoubleWalls">
1139 <first ref="ArapucaOut"/>
1140 <second ref="ArapucaDoubleIn"/>
1141 <position name="posArapucaDoubleSub" x="0" y="0" z="0" unit="cm"/>
1144 <box name="ArapucaDoubleAcceptanceWindow" lunit="cm"
1145 x="@{[$ArapucaOut_y-0.02]}"
1146 y="@{[$ArapucaAcceptanceWindow_x]}"
1147 z="@{[$ArapucaAcceptanceWindow_z]}"/>
1149 <box name="ArapucaCathodeAcceptanceWindow" lunit="cm"
1150 x="@{[$ArapucaAcceptanceWindow_y]}"
1151 y="@{[$ArapucaAcceptanceWindow_x]}"
1152 z="@{[$ArapucaAcceptanceWindow_z]}"/>
1157 # Cryostat structure
1160 <volume name="volSteelShell">
1161 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1162 <solidref ref="SteelShell" />
1164 <volume name="volGaseousArgon">
1165 <materialref ref="ArGas"/>
1166 <solidref ref="GaseousArgon"/>
1168 <volume name="volExternalActive">
1169 <materialref ref="LAr"/>
1170 <solidref ref="ExternalActive"/>
1171 <auxiliary auxtype="SensDet" auxvalue="SimEnergyDeposit"/>
1172 <auxiliary auxtype="StepLimit" auxunit="cm" auxvalue="0.5208*cm"/>
1173 <auxiliary auxtype="Efield" auxunit="V/cm" auxvalue="0*V/cm"/>
1174 <colorref ref="green"/>
1177 #including single sided arapucas over the cathode while there is only the top volume
1178 #if double sided, use
1179 # <volume name="volArapucaDouble_$i\-$j\-$p">
1180 # <materialref ref="G10" />
1181 # <solidref ref="ArapucaDoubleWalls" />
1183 # <volume name="volOpDetSensitive_ArapucaDouble_$i\-$j\-$p">
1184 # <materialref ref="LAr"/>
1185 # <solidref ref="ArapucaDoubleAcceptanceWindow"/>
1187 if ($pdsconfig == 0){ #4-pi PDS converage
1188 for($i=0 ; $i<$nCRM_x/2 ; $i++){ #arapucas over the cathode
1189 for($j=0 ; $j<$nCRM_z/2 ; $j++){
1190 for($p=0 ; $p<4 ; $p++){
1192 <volume name="volArapucaDouble_$i\-$j\-$p">
1193 <materialref ref="G10" />
1194 <solidref ref="ArapucaWalls" />
1196 <volume name="volOpDetSensitive_ArapucaDouble_$i\-$j\-$p">
1197 <materialref ref="LAr"/>
1198 <solidref ref="ArapucaCathodeAcceptanceWindow"/>
1206 if ($nCRM_x==8){ #arapucas on the laterals
1207 for($j=0 ; $j<$nCRM_z/2 ; $j++){
1208 for($p=0 ; $p<8 ; $p++){
1210 <volume name="volArapucaLat_$j\-$p">
1211 <materialref ref="G10" />
1212 <solidref ref="ArapucaWalls" />
1214 <volume name="volOpDetSensitive_ArapucaLat_$j\-$p">
1215 <materialref ref="LAr"/>
1216 <solidref ref="ArapucaAcceptanceWindow"/>
1223 if ($pdsconfig == 1){ #Membrane PDS converage
1224 if ($nCRM_x==8) { #arapucas on the laterals
1225 for($j=0 ; $j<$nCRM_z/2 ; $j++){
1226 for($p=8 ; $p<18 ; $p++){
1228 <volume name="volArapucaLat_$j\-$p">
1229 <materialref ref="G10" />
1230 <solidref ref="ArapucaWalls" />
1232 <volume name="volOpDetSensitive_ArapucaLat_$j\-$p">
1233 <materialref ref="LAr"/>
1234 <solidref ref="ArapucaAcceptanceWindow"/>
1244 <volume name="volCryostat">
1245 <materialref ref="LAr" />
1246 <solidref ref="Cryostat" />
1248 <volumeref ref="volGaseousArgon"/>
1249 <position name="posGaseousArgon" unit="cm" x="@{[$Argon_x/2-$HeightGaseousAr/2]}" y="0" z="0"/>
1252 <volumeref ref="volSteelShell"/>
1253 <position name="posSteelShell" unit="cm" x="0" y="0" z="0"/>
1256 <volumeref ref="volExternalActive"/>
1257 <position name="posExternalActive" unit="cm" x="-$xLArBuffer/2" y="0" z="0"/>
1261 if ($tpc_on==1) # place TPC inside croysotat offsetting each pair of CRMs by borderCRP
1263 $posX = $Argon_x/2 - $HeightGaseousAr - 0.5*($driftTPCActive + $ReadoutPlane);
1265 my $posZ = -0.5*$Argon_z + $zLArBuffer + 0.5*$lengthCRM;
1266 for(my $ii=0;$ii<$nCRM_z;$ii++)
1269 $posZ += $borderCRP;
1271 $posZ += $borderCRP;
1274 my $posY = -0.5*$Argon_y + $yLArBuffer + 0.5*$widthCRM;
1275 for(my $jj=0;$jj<$nCRM_x;$jj++)
1278 $posY += $borderCRP;
1280 $posY += $borderCRP;
1285 <volumeref ref="volTPC"/>
1286 <position name="posTPC\-$idx" unit="cm"
1287 x="$posX" y="$posY" z="$posZ"/>
1294 $posZ += $lengthCRM;
1298 #The +50 in the x positions must depend on some other parameter
1299 if ( $FieldCage_switch eq "on" ) {
1300 for ( $i=0; $i<$NFieldShapers; $i=$i+1 ) {
1301 $dist=$i*$FieldShaperSeparation;
1302 $posX = $Argon_x/2 - $HeightGaseousAr - 0.5*($driftTPCActive + $ReadoutPlane);
1307 <volumeref ref="volFieldShaperSlim"/>
1308 <position name="posFieldShaper$i" unit="cm" x="@{[-$OriginXSet+50+($i-$NFieldShapers*0.5)*$FieldShaperSeparation]}" y="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" z="0" />
1309 <rotation name="rotFS$i" unit="deg" x="0" y="0" z="90" />
1315 <volumeref ref="volFieldShaper"/>
1316 <position name="posFieldShaper$i" unit="cm" x="@{[-$OriginXSet+50+($i-$NFieldShapers*0.5)*$FieldShaperSeparation]}" y="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" z="0" />
1317 <rotation name="rotFS$i" unit="deg" x="0" y="0" z="90" />
1324 <volumeref ref="volFieldShaperSlim"/>
1325 <position name="posFieldShaper$i" unit="cm" x="@{[-$OriginXSet+50+($i-$NFieldShapers*0.5)*$FieldShaperSeparation]}" y="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" z="0" />
1326 <rotation name="rotFS$i" unit="deg" x="0" y="0" z="90" />
1334 $CathodePosX =-$OriginXSet+50+(-1-$NFieldShapers*0.5)*$FieldShaperSeparation;
1337 if ( $Cathode_switch eq "on" )
1341 <volumeref ref="volGroundGrid"/>
1342 <position name="posGroundGrid01" unit="cm" x="$CathodePosX" y="@{[-$CathodePosY]}" z="@{[$CathodePosZ]}"/>
1343 <rotation name="rotGG01" unit="deg" x="0" y="0" z="90" />
1349 $FrameLenght_x= 2.0*$widthCRM_active;
1350 $FrameLenght_z= 2.0*$lengthCRM_active;
1352 if ($pdsconfig == 0) { #4-pi PDS converage
1354 #for placing the Arapucas over the cathode
1355 $FrameCenter_x=-1.5*$FrameLenght_x+(4-$nCRM_x/2)/2*$FrameLenght_x;
1356 $FrameCenter_y=$CathodePosX;
1357 $FrameCenter_z=-9.5*$FrameLenght_z+(20-$nCRM_z/2)/2*$FrameLenght_z;
1358 for($i=0;$i<$nCRM_x/2;$i++){
1359 for($j=0;$j<$nCRM_z/2;$j++){
1360 place_OpDetsCathode($FrameCenter_x, $FrameCenter_y, $FrameCenter_z, $i, $j);
1361 $FrameCenter_z+=$FrameLenght_z;
1363 $FrameCenter_x+=$FrameLenght_x;
1364 $FrameCenter_z=-9.5*$FrameLenght_z+(20-$nCRM_z/2)/2*$FrameLenght_z;
1368 if ($pdsconfig == 0) { #4-pi PDS converage
1369 #for placing the Arapucas on laterals
1371 $FrameCenter_y=$posZplane[0]; #anode position
1372 $FrameCenter_z=-19*$FrameLenght_z/2+(40-$nCRM_z)/2*$FrameLenght_z/2;
1373 for($j=0;$j<$nCRM_z/2;$j++){#nCRM will give the collumn number (1 collumn per frame)
1374 place_OpDetsLateral($FrameCenter_y, $FrameCenter_z, $j);
1375 $FrameCenter_z+=$FrameLenght_z;
1379 } else { #membrane only PDS converage
1381 if($pdsconfig == 1){
1383 $FrameCenter_y=$posZplane[0]; #anode position
1384 $FrameCenter_z=-19*$FrameLenght_z/2+(40-$nCRM_z)/2*$FrameLenght_z/2;
1385 for($j=0;$j<$nCRM_z/2;$j++){#nCRM will give the collumn number (1 collumn per frame)
1386 place_OpDetsMembOnly($FrameCenter_y, $FrameCenter_z, $j);
1387 $FrameCenter_z+=$FrameLenght_z;
1403 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1404 #++++++++++++++++++++++++++++++++++++ place_OpDets +++++++++++++++++++++++++++++++++++++++
1405 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1407 sub place_OpDetsCathode()
1410 $FrameCenter_x = $_[0];
1411 $FrameCenter_y = $_[1];
1412 $FrameCenter_z = $_[2];
1416 #Placing Arapucas over the Cathode
1417 #If there are both top and bottom volumes --> use double-sided:
1419 # <volumeref ref="volOpDetSensitive_ArapucaDouble_$Frame_x\-$Frame_z\-$ara"/>
1420 # <position name="posOpArapucaDouble$ara-Frame\-$Frame_x\-$Frame_z" unit="cm"
1426 for ($ara = 0; $ara<4; $ara++)
1428 # All Arapuca centers will have the same Y coordinate
1429 # X and Z coordinates are defined with respect to the center of the current Frame
1431 $Ara_Y = $FrameCenter_x+$list_posx_bot[$ara]; #GEOMETRY IS ROTATED: X--> Y AND Y--> X
1432 $Ara_X = $FrameCenter_y + $FrameToArapucaSpace;
1433 $Ara_Z = $FrameCenter_z+$list_posz_bot[$ara];
1437 <volumeref ref="volArapucaDouble_$Frame_x\-$Frame_z\-$ara"/>
1438 <position name="posArapucaDouble$ara-Frame\-$Frame_x\-$Frame_z" unit="cm"
1442 <rotation name="rPlus90AboutXPlus90AboutZ" unit="deg" x="90" y="0" z="90"/>
1445 <volumeref ref="volOpDetSensitive_ArapucaDouble_$Frame_x\-$Frame_z\-$ara"/>
1446 <position name="posOpArapucaDouble$ara-Frame\-$Frame_x\-$Frame_z" unit="cm"
1447 x="@{[$Ara_X+0.5*$ArapucaOut_y-0.5*$ArapucaAcceptanceWindow_y-0.01]}"
1458 sub place_OpDetsLateral()
1461 $FrameCenter_y = $_[0];
1462 $FrameCenter_z = $_[1];
1465 #Placing Arapucas on the laterals if nCRM_x=8 -- Single Sided
1466 for ($ara = 0; $ara<8; $ara++)
1468 # Arapucas on laterals
1469 # All Arapuca centers on a given collumn will have the same Z coordinate
1470 # X coordinates are on the left and right laterals
1471 # Y coordinates are defined with respect to the cathode position
1472 # There are two collumns per frame on each side.
1474 if ($ara<4) {$Ara_Y = -0.5*$Argon_y + $FrameToArapucaSpaceLat;
1475 $Ara_YSens = ($Ara_Y+0.5*$ArapucaOut_y-0.5*$ArapucaAcceptanceWindow_y-0.01);
1476 $rot= "rIdentity"; }
1477 else {$Ara_Y = 0.5*$Argon_y - $FrameToArapucaSpaceLat;
1478 $Ara_YSens = ($Ara_Y-0.5*$ArapucaOut_y+0.5*$ArapucaAcceptanceWindow_y+0.01);
1479 $rot = "rPlus180AboutX";} #GEOMETRY IS ROTATED: X--> Y AND Y--> X
1480 if ($ara==0||$ara==4) {$Ara_X = $FrameCenter_y-40.0;} #first tile's center 40 cm bellow anode
1481 else {$Ara_X-=$VerticalPDdist;} #other tiles separated by VerticalPDdist
1482 $Ara_Z = $FrameCenter_z;
1484 # print "lateral arapucas: $Ara_X, $Ara_Y, $Ara_Z \n";
1488 <volumeref ref="volArapucaLat_$Lat_z\-$ara"/>
1489 <position name="posArapuca$ara-Lat\-$Lat_z" unit="cm"
1493 <rotationref ref="$rot"/>
1496 <volumeref ref="volOpDetSensitive_ArapucaLat_$Lat_z\-$ara"/>
1497 <position name="posOpArapuca$ara-Lat\-$Lat_z" unit="cm"
1509 sub place_OpDetsMembOnly()
1512 $FrameCenter_y = $_[0];
1513 $FrameCenter_z = $_[1];
1516 #Placing Arapucas on the laterals if nCRM_x=8 -- Single Sided
1517 for ($ara = 0; $ara<18; $ara++)
1519 # Arapucas on laterals
1520 # All Arapuca centers on a given collumn will have the same Z coordinate
1521 # X coordinates are on the left and right laterals
1522 # Y coordinates are defined with respect to the cathode position
1523 # There are two collumns per frame on each side.
1525 if($ara<9) {$Ara_Y = -0.5*$Argon_y + $FrameToArapucaSpaceLat;
1526 $Ara_YSens = ($Ara_Y+0.5*$ArapucaOut_y-0.5*$ArapucaAcceptanceWindow_y-0.01);
1527 $rot= "rIdentity"; }
1528 else {$Ara_Y = 0.5*$Argon_y - $FrameToArapucaSpaceLat;
1529 $Ara_YSens = ($Ara_Y-0.5*$ArapucaOut_y+0.5*$ArapucaAcceptanceWindow_y+0.01);
1530 $rot = "rPlus180AboutX";} #GEOMETRY IS ROTATED: X--> Y AND Y--> X
1531 if($ara==0||$ara==9) {$Ara_X = $FrameCenter_y-$ArapucaOut_x/2;} #first tile's center right below anode
1532 else {$Ara_X-=$ArapucaOut_x - $FrameToArapucaSpace;} #other tiles separated by minimal distance + buffer
1533 $Ara_Z = $FrameCenter_z;
1535 # print "lateral arapucas: $Ara_X, $Ara_Y, $Ara_Z \n";
1539 <volumeref ref="volArapucaLat_$Lat_z\-$ara"/>
1540 <position name="posArapuca$ara-Lat\-$Lat_z" unit="cm"
1544 <rotationref ref="$rot"/>
1547 <volumeref ref="volOpDetSensitive_ArapucaLat_$Lat_z\-$ara"/>
1548 <position name="posOpArapuca$ara-Lat\-$Lat_z" unit="cm"
1562 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1563 #+++++++++++++++++++++++++++++++++++++ gen_Enclosure +++++++++++++++++++++++++++++++++++++
1564 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1569 # Create the detector enclosure fragment file name,
1570 # add file to list of output GDML fragments,
1572 $ENCL = $basename."_DetEnclosure" . $suffix . ".gdml";
1573 push (@gdmlFiles, $ENCL);
1574 $ENCL = ">" . $ENCL;
1575 open(ENCL) or die("Could not open file $ENCL for writing");
1578 # The standard XML prefix and starting the gdml
1580 <?xml version='1.0'?>
1585 # All the detector enclosure solids.
1589 <box name="FoamPadBlock" lunit="cm"
1590 x="@{[$Cryostat_x + 2*$FoamPadding]}"
1591 y="@{[$Cryostat_y + 2*$FoamPadding]}"
1592 z="@{[$Cryostat_z + 2*$FoamPadding]}" />
1594 <subtraction name="FoamPadding">
1595 <first ref="FoamPadBlock"/>
1596 <second ref="Cryostat"/>
1597 <positionref ref="posCenter"/>
1600 <box name="SteelSupportBlock" lunit="cm"
1601 x="@{[$Cryostat_x + 2*$FoamPadding + 2*$SteelSupport_x]}"
1602 y="@{[$Cryostat_y + 2*$FoamPadding + 2*$SteelSupport_y]}"
1603 z="@{[$Cryostat_z + 2*$FoamPadding + 2*$SteelSupport_z]}" />
1605 <subtraction name="SteelSupport">
1606 <first ref="SteelSupportBlock"/>
1607 <second ref="FoamPadBlock"/>
1608 <positionref ref="posCenter"/>
1611 <box name="DetEnclosure" lunit="cm"
1620 # Detector enclosure structure
1623 <volume name="volFoamPadding">
1624 <materialref ref="fibrous_glass"/>
1625 <solidref ref="FoamPadding"/>
1628 <volume name="volSteelSupport">
1629 <materialref ref="AirSteelMixture"/>
1630 <solidref ref="SteelSupport"/>
1633 <volume name="volDetEnclosure">
1634 <materialref ref="Air"/>
1635 <solidref ref="DetEnclosure"/>
1638 <volumeref ref="volFoamPadding"/>
1639 <positionref ref="posCryoInDetEnc"/>
1642 <volumeref ref="volSteelSupport"/>
1643 <positionref ref="posCryoInDetEnc"/>
1646 <volumeref ref="volCryostat"/>
1647 <positionref ref="posCryoInDetEnc"/>
1666 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1667 #+++++++++++++++++++++++++++++++++++++++ gen_World +++++++++++++++++++++++++++++++++++++++
1668 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1673 # Create the WORLD fragment file name,
1674 # add file to list of output GDML fragments,
1676 $WORLD = $basename."_World" . $suffix . ".gdml";
1677 push (@gdmlFiles, $WORLD);
1678 $WORLD = ">" . $WORLD;
1679 open(WORLD) or die("Could not open file $WORLD for writing");
1682 # The standard XML prefix and starting the gdml
1684 <?xml version='1.0'?>
1689 # All the World solids.
1692 <box name="World" lunit="cm"
1693 x="@{[$DetEncX+2*$RockThickness]}"
1694 y="@{[$DetEncY+2*$RockThickness]}"
1695 z="@{[$DetEncZ+2*$RockThickness]}"/>
1702 <volume name="volWorld" >
1703 <materialref ref="DUSEL_Rock"/>
1704 <solidref ref="World"/>
1707 <volumeref ref="volDetEnclosure"/>
1708 <position name="posDetEnclosure" unit="cm" x="$OriginXSet" y="$OriginYSet" z="$OriginZSet"/>
1716 # make_gdml.pl will take care of <setup/>
1723 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1724 #++++++++++++++++++++++++++++++++++++ write_fragments ++++++++++++++++++++++++++++++++++++
1725 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1727 sub write_fragments()
1729 # This subroutine creates an XML file that summarizes the the subfiles output
1730 # by the other sub routines - it is the input file for make_gdml.pl which will
1731 # give the final desired GDML file. Specify its name with the output option.
1732 # (you can change the name when running make_gdml)
1734 # This code is taken straigh from the similar MicroBooNE generate script, Thank you.
1736 if ( ! defined $output )
1738 $output = "-"; # write to STDOUT
1741 # Set up the output file.
1742 $OUTPUT = ">" . $output;
1743 open(OUTPUT) or die("Could not open file $OUTPUT");
1746 <?xml version='1.0'?>
1748 <!-- Input to Geometry/gdml/make_gdml.pl; define the GDML fragments
1749 that will be zipped together to create a detector description.
1756 <!-- These files contain GDML <constant></constant>
1757 blocks. They are read in separately, so they can be
1758 interpreted into the remaining GDML. See make_gdml.pl for
1764 foreach $filename (@defFiles)
1767 <filename> $filename </filename>
1777 <!-- The GDML file fragments to be zipped together. -->
1781 foreach $filename (@gdmlFiles)
1784 <filename> $filename </filename>
1799 print "Some of the principal parameters for this TPC geometry (unit cm unless noted otherwise)\n";
1800 print " CRM active area : $widthCRM_active x $lengthCRM_active\n";
1801 print " CRM total area : $widthCRM x $lengthCRM\n";
1802 print " Wire pitch in U, Y, Z : $wirePitchU, $wirePitchY, $wirePitchZ\n";
1803 print " TPC active volume : $driftTPCActive x $widthTPCActive x $lengthTPCActive\n";
1804 print " Argon volume : ($Argon_x, $Argon_y, $Argon_z) \n";
1805 print " Argon buffer : ($xLArBuffer, $yLArBuffer, $zLArBuffer) \n";
1806 print " Detector enclosure : $DetEncX x $DetEncY x $DetEncZ\n";
1807 print " TPC Origin : ($OriginXSet, $OriginYSet, $OriginZSet) \n";
1808 print " Field Cage : $FieldCage_switch \n";
1809 print " Cathode : $Cathode_switch \n";
1810 print " Workspace : $workspace \n";
1811 print " Wires : $wires_on \n";
1813 # run the sub routines that generate the fragments
1814 if ( $FieldCage_switch eq "on" ) { gen_FieldCage(); }
1815 #if ( $Cathode_switch eq "on" ) { gen_Cathode(); } #Cathode for now has the same geometry as the Ground Grid
1817 gen_Extend(); # generates the GDML color extension for the refactored geometry
1818 gen_Define(); # generates definitions at beginning of GDML
1819 gen_Materials(); # generates materials to be used
1820 gen_TPC(); # generate TPC for a given unit CRM
1823 gen_World(); # places the enclosure among DUSEL Rock
1824 write_fragments(); # writes the XML input for make_gdml.pl
1825 # which zips together the final GDML
1826 print "--- done\n\n\n";