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
22 #################################################################################
24 # Each subroutine generates a fragment GDML file, and the last subroutine
25 # creates an XML file that make_gdml.pl will use to appropriately arrange
26 # the fragment GDML files to create the final desired DUNE GDML file,
27 # to be named by make_gdml output command
29 ##################################################################################
37 Math::BigFloat->precision(-16);
40 GetOptions( "help|h" => \$help,
41 "suffix|s:s" => \$suffix,
42 "output|o:s" => \$output,
43 "wires|w:s" => \$wires,
44 "workspace|k:s" => \$wkspc);
46 my $FieldCage_switch="off";
47 my $Cathode_switch="off";
51 # If the user requested help, print the usage notes and exit.
56 if ( ! defined $suffix )
58 # The user didn't supply a suffix, so append nothing to the file
64 # Otherwise, stick a "-" before the suffix, so that a suffix of
65 # "test" applied to filename.gdml becomes "filename-test.gdml".
66 $suffix = "-" . $suffix;
75 elsif ( $workspace != 0 )
77 print "\t\tCreating smaller workspace geometry.\n";
80 # set wires on to be the default, unless given an input by the user
81 $wires_on = 1; # 1=on, 0=off
91 ##################################################################
92 ############## Parameters for One Readout Panel ##################
94 # parameters for 1.5 x 1.7 sub-unit Charge Readout Module / Unit
95 #$widthPCBActive = 169.0; # cm
96 #$lengthPCBActive = 150.0; # cm
98 # views and channel counts
99 %nChans = ('Ind1', 256, 'Ind1Bot', 128, 'Ind2', 320, 'Col', 288);
100 $nViews = keys %nChans;
101 #print "$nViews %nChans\n";
103 # first induction view
104 $wirePitchU = 0.8695; # cm
105 $wireAngleU = 131.63; #-48.37; # deg
107 # second induction view
109 $widthPCBActive = 168.00; #$wirePitchY * $nChans{'Ind2'};
111 # last collection view
113 $lengthPCBActive = 148.9009; #$wirePitchZ * $nChans{'Col'};
116 $borderCRM = 0.0; # border space aroud each CRM
118 $widthCRM_active = $widthPCBActive;
119 $lengthCRM_active = $lengthPCBActive;
121 $widthCRM = $widthPCBActive + 2 * $borderCRM;
122 $lengthCRM = $lengthPCBActive + 2 * $borderCRM;
124 $borderCRP = 0.5; # cm
126 # number of CRMs in y and z
130 # create a smaller geometry
131 if( $workspace == 1 )
137 # calculate tpc area based on number of CRMs and their dimensions
138 # each CRP should have a 2x2 CRMs
139 $widthTPCActive = $nCRM_x * $widthCRM + $nCRM_x * $borderCRP; # around 1200 for full module
140 $lengthTPCActive = $nCRM_z * $lengthCRM + $nCRM_z * $borderCRP; # around 6000 for full module
142 # active volume dimensions
143 $driftTPCActive = 30.0;
145 # model anode strips as wires of some diameter
147 $ReadoutPlane = $nViews * $padWidth; # 3 readout planes (no space b/w)!
149 ##################################################################
150 ############## Parameters for TPC and inner volume ###############
152 # inner volume dimensions of the cryostat
154 # width of gas argon layer on top
155 $HeightGaseousAr = 40;
157 #if( $workspace != 0 )
159 #active tpc + some buffer on each side
160 $Argon_x = 100.0; #$driftTPCActive + $HeightGaseousAr + $ReadoutPlane + 30; #~1 m
161 $Argon_y = $widthTPCActive + 52;
162 $Argon_z = $lengthTPCActive + 92;
166 # size of liquid argon buffer
167 $xLArBuffer = $Argon_x - $driftTPCActive - $HeightGaseousAr - $ReadoutPlane - $LArOverhead;
168 $yLArBuffer = 0.5 * ($Argon_y - $widthTPCActive);
169 $zLArBuffer = 0.5 * ($Argon_z - $lengthTPCActive);
172 $SteelThickness = 0.12; # membrane
174 $Cryostat_x = $Argon_x + 2*$SteelThickness;
175 $Cryostat_y = $Argon_y + 2*$SteelThickness;
176 $Cryostat_z = $Argon_z + 2*$SteelThickness;
178 ##################################################################
179 ############## DetEnc and World relevant parameters #############
181 $SteelSupport_x = 50;
182 $SteelSupport_y = 50;
183 $SteelSupport_z = 50;
185 $FracMassOfSteel = 0.5; #The steel support is not a solid block, but a mixture of air and steel
186 $FracMassOfAir = 1 - $FracMassOfSteel;
189 $SpaceSteelSupportToWall = 100;
190 $SpaceSteelSupportToCeiling = 100;
192 $DetEncX = $Cryostat_x
193 + 2*($SteelSupport_x + $FoamPadding) + $SpaceSteelSupportToCeiling;
195 $DetEncY = $Cryostat_y
196 + 2*($SteelSupport_y + $FoamPadding) + 2*$SpaceSteelSupportToWall;
198 $DetEncZ = $Cryostat_z
199 + 2*($SteelSupport_z + $FoamPadding) + 2*$SpaceSteelSupportToWall;
201 $posCryoInDetEnc_x = - $DetEncX/2 + $SteelSupport_x + $FoamPadding + $Cryostat_x/2;
204 $RockThickness = 4000;
206 # We want the world origin to be vertically centered on active TPC
207 # This is to be added to the x and y position of every volume in volWorld
209 $OriginXSet = $DetEncX/2.0
214 - $driftTPCActive/2.0;
216 $OriginYSet = $DetEncY/2.0
217 - $SpaceSteelSupportToWall
222 - $widthTPCActive/2.0;
224 # We want the world origin to be at the very front of the fiducial volume.
225 # move it to the front of the enclosure, then back it up through the concrete/foam,
226 # then through the Cryostat shell, then through the upstream dead LAr (including the
227 # dead LAr on the edge of the TPC)
228 # This is to be added to the z position of every volume in volWorld
230 $OriginZSet = $DetEncZ/2.0
231 - $SpaceSteelSupportToWall
238 ##################################################################
239 ############## Field Cage Parameters ###############
240 $FieldShaperLongTubeLength = $lengthTPCActive;
241 $FieldShaperShortTubeLength = $widthTPCActive;
242 $FieldShaperInnerRadius = 1.485;
243 $FieldShaperOuterRadius = 1.685;
244 $FieldShaperTorRad = 1.69;
246 $FieldShaperLength = $FieldShaperLongTubeLength + 2*$FieldShaperOuterRadius+ 2*$FieldShaperTorRad;
247 $FieldShaperWidth = $FieldShaperShortTubeLength + 2*$FieldShaperOuterRadius+ 2*$FieldShaperTorRad;
249 $FieldShaperSeparation = 5.0;
250 $NFieldShapers = ($driftTPCActive/$FieldShaperSeparation) - 1;
252 $FieldCageSizeX = $FieldShaperSeparation*$NFieldShapers+2;
253 $FieldCageSizeY = $FieldShaperWidth+2;
254 $FieldCageSizeZ = $FieldShaperLength+2;
257 #+++++++++++++++++++++++++ End defining variables ++++++++++++++++++++++++++
260 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
261 #+++++++++++++++++++++++++++++++++++++++++ usage +++++++++++++++++++++++++++++++++++++++++
262 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
266 print "Usage: $0 [-h|--help] [-o|--output <fragments-file>] [-s|--suffix <string>]\n";
267 print " if -o is omitted, output goes to STDOUT; <fragments-file> is input to make_gdml.pl\n";
268 print " -s <string> appends the string to the file names; useful for multiple detector versions\n";
269 print " -h prints this message, then quits\n";
276 # Create the <define> fragment file name,
277 # add file to list of fragments,
279 $DEF = $basename."_Ext" . $suffix . ".gdml";
280 push (@gdmlFiles, $DEF);
282 open(DEF) or die("Could not open file $DEF for writing");
285 <?xml version='1.0'?>
288 <color name="magenta" R="0.0" G="1.0" B="0.0" A="1.0" />
289 <color name="green" R="0.0" G="1.0" B="0.0" A="1.0" />
290 <color name="red" R="1.0" G="0.0" B="0.0" A="1.0" />
291 <color name="blue" R="0.0" G="0.0" B="1.0" A="1.0" />
292 <color name="yellow" R="1.0" G="1.0" B="0.0" A="1.0" />
299 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
300 #++++++++++++++++++++++++++++++++++++++ gen_Define +++++++++++++++++++++++++++++++++++++++
301 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
306 # Create the <define> fragment file name,
307 # add file to list of fragments,
309 $DEF = $basename."_Def" . $suffix . ".gdml";
310 push (@gdmlFiles, $DEF);
312 open(DEF) or die("Could not open file $DEF for writing");
316 <?xml version='1.0'?>
326 <position name="posCryoInDetEnc" unit="cm" x="$posCryoInDetEnc_x" y="0" z="0"/>
327 <position name="posCenter" unit="cm" x="0" y="0" z="0"/>
328 <rotation name="rUWireAboutX" unit="deg" x="$wireAngleU" y="0" z="0"/>
329 <rotation name="rPlus90AboutX" unit="deg" x="90" y="0" z="0"/>
330 <rotation name="rPlus90AboutY" unit="deg" x="0" y="90" z="0"/>
331 <rotation name="rPlus90AboutXPlus90AboutY" unit="deg" x="90" y="90" z="0"/>
332 <rotation name="rMinus90AboutX" unit="deg" x="270" y="0" z="0"/>
333 <rotation name="rMinus90AboutY" unit="deg" x="0" y="270" z="0"/>
334 <rotation name="rMinus90AboutYMinus90AboutX" unit="deg" x="270" y="270" z="0"/>
335 <rotation name="rPlus180AboutX" unit="deg" x="180" y="0" z="0"/>
336 <rotation name="rPlus180AboutY" unit="deg" x="0" y="180" z="0"/>
337 <rotation name="rPlus180AboutXPlus180AboutY" unit="deg" x="180" y="180" z="0"/>
338 <rotation name="rIdentity" unit="deg" x="0" y="0" z="0"/>
345 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
346 #+++++++++++++++++++++++++++++++++++++ gen_Materials +++++++++++++++++++++++++++++++++++++
347 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
352 # Create the <materials> fragment file name,
353 # add file to list of output GDML fragments,
355 $MAT = $basename."_Materials" . $suffix . ".gdml";
356 push (@gdmlFiles, $MAT);
359 open(MAT) or die("Could not open file $MAT for writing");
361 # Add any materials special to this geometry by defining a mulitline string
362 # and passing it to the gdmlMaterials::gen_Materials() function.
364 <!-- preliminary values -->
365 <material name="AirSteelMixture" formula="AirSteelMixture">
366 <D value=" 0.001205*(1-$FracMassOfSteel) + 7.9300*$FracMassOfSteel " unit="g/cm3"/>
367 <fraction n="$FracMassOfSteel" ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
368 <fraction n="$FracMassOfAir" ref="Air"/>
370 <material name="vm2000" formula="vm2000">
371 <D value="1.2" unit="g/cm3"/>
372 <composite n="2" ref="carbon"/>
373 <composite n="4" ref="hydrogen"/>
377 # add the general materials used anywere
378 print MAT gdmlMaterials::gen_Materials( $asmix );
384 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
385 #++++++++++++++++++++++++++++++++++++++++ gen_TPC ++++++++++++++++++++++++++++++++++++++++
386 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
387 # line clip on the rectangle boundary
398 if( abs( nx ) < tol ){
399 push( @endpts, ($x0, 0) );
400 push( @endpts, ($x0, $rcw) );
403 if( abs( ny ) < tol ){
404 push( @endpts, (0, $y0) );
405 push( @endpts, ($rcl, $y0) );
409 # left border at x = 0
410 my $y = $y0 - $x0 * $ny/$nx;
411 if( $y >= 0 && $y <= $rcw ){
412 push( @endpts, (0, $y) );
415 # right border at x = l
416 $y = $y0 + ($rcl-$x0) * $ny/$nx;
417 if( $y >= 0 && $y <= $rcw ){
418 push( @endpts, ($rcl, $y) );
419 if( scalar(@endpts) == 4 ){
424 # bottom border at y = 0
425 my $x = $x0 - $y0 * $nx/$ny;
426 if( $x >= 0 && $x <= $rcl ){
427 push( @endpts, ($x, 0) );
428 if( scalar(@endpts) == 4 ){
433 # top border at y = w
434 $x = $x0 + ($rcw-$y0)* $nx/$ny;
435 if( $x >= 0 && $x <= $rcl ){
436 push( @endpts, ($x, $rcw) );
444 my $length = $_[0]; #
447 my $nchb = $_[3]; # nch per bottom side
449 my $theta = $_[5]; # deg
452 $theta = $theta * pi()/180.0;
453 my @dirw = (cos($theta), sin($theta));
454 my @dirp = (cos($theta - pi()/2), sin($theta - pi()/2));
458 if( $alpha > pi()/2 ){
459 $alpha = pi() - $alpha;
461 my $dX = $pitch / sin( $alpha );
462 my $dY = $pitch / sin( pi()/2 - $alpha );
464 $length = $dX * $nchb;
467 $width = $dY * ($nch - $nchb);
478 #print "origin : @orig\n";
479 #print "pitch dir : @dirp\n";
480 #print "wire dir : @dirw\n";
481 #print "$length x $width cm2\n";
485 my $offset = $pitch/2;
486 foreach my $ch (0..$nch-1){
487 #print "Processing $ch\n";
489 # calculate reference point for this strip
491 $wcn[0] = $orig[0] + $offset * $dirp[0];
492 $wcn[1] = $orig[1] + $offset * $dirp[1];
494 # line clip on the rectangle boundary
495 @endpts = lineClip( $wcn[0], $wcn[1], $dirw[0], $dirw[1], $length, $width );
497 if( scalar(@endpts) != 4 ){
498 print "Could not find end points for wire $ch : @endpts\n";
499 $offset = $offset + $pitch;
503 # re-center on the mid-point
504 $endpts[0] -= $length/2;
505 $endpts[2] -= $length/2;
506 $endpts[1] -= $width/2;
507 $endpts[3] -= $width/2;
509 # calculate the strip center in the rectangle of CRU
510 $wcn[0] = ($endpts[0] + $endpts[2])/2;
511 $wcn[1] = ($endpts[1] + $endpts[3])/2;
513 # calculate the length
514 my $dx = $endpts[0] - $endpts[2];
515 my $dy = $endpts[1] - $endpts[3];
516 my $wlen = sqrt($dx**2 + $dy**2);
518 # put all info together
519 my @wire = ($ch, $wcn[0], $wcn[1], $wlen);
520 push( @wire, @endpts );
521 push( @winfo, \@wire);
522 $offset = $offset + $pitch;
532 my $TPCActive_x = $driftTPCActive;
533 my $TPCActive_y = $widthCRM_active;
534 my $TPCActive_z = $lengthCRM_active;
537 my $TPC_x = $TPCActive_x + $ReadoutPlane;
538 my $TPC_y = $widthCRM;
539 my $TPC_z = $lengthCRM;
541 print " TPC dimensions : $TPC_x x $TPC_y x $TPC_z\n";
543 $TPC = $basename."_TPC" . $suffix . ".gdml";
544 push (@gdmlFiles, $TPC);
546 open(TPC) or die("Could not open file $TPC for writing");
548 # The standard XML prefix and starting the gdml
550 <?xml version='1.0'?>
554 # compute wires for 1st induction
556 if( $wires_on == 1 ){
557 @winfo = gen_Wires( 0, 0, # $TPCActive_y,
558 $nChans{'Ind1'}, $nChans{'Ind1Bot'},
559 $wirePitchU, $wireAngleU, $padWidth );
562 # All the TPC solids save the wires.
573 <box name="CRMUPlane"
578 <box name="CRMYPlane"
583 <box name="CRMZPlane"
588 <box name="CRMActive"
595 #++++++++++++++++++++++++++++ Wire Solids ++++++++++++++++++++++++++++++
598 foreach my $wire (@winfo) {
599 my $wid = $wire->[0];
600 my $wln = $wire->[3];
602 <tube name="CRMWireU$wid"
606 aunit="deg" lunit="cm"/>
611 <tube name="CRMWireY"
615 aunit="deg" lunit="cm"/>
616 <tube name="CRMWireZ"
620 aunit="deg" lunit="cm"/>
628 # Begin structure and create wire logical volumes
631 <volume name="volTPCActive">
632 <materialref ref="LAr"/>
633 <solidref ref="CRMActive"/>
634 <auxiliary auxtype="SensDet" auxvalue="SimEnergyDeposit"/>
635 <auxiliary auxtype="StepLimit" auxunit="cm" auxvalue="0.5208*cm"/>
636 <auxiliary auxtype="Efield" auxunit="V/cm" auxvalue="500*V/cm"/>
637 <colorref ref="blue"/>
643 foreach my $wire (@winfo)
645 my $wid = $wire->[0];
647 <volume name="volTPCWireU$wid">
648 <materialref ref="Copper_Beryllium_alloy25"/>
649 <solidref ref="CRMWireU$wid"/>
655 <volume name="volTPCWireY">
656 <materialref ref="Copper_Beryllium_alloy25"/>
657 <solidref ref="CRMWireY"/>
659 <volume name="volTPCWireZ">
660 <materialref ref="Copper_Beryllium_alloy25"/>
661 <solidref ref="CRMWireZ"/>
665 # 1st induction plane
667 <volume name="volTPCPlaneU">
668 <materialref ref="LAr"/>
669 <solidref ref="CRMUPlane"/>
671 if ($wires_on==1) # add wires to U plane
673 # the coordinates were computed with a corner at (0,0)
674 # so we need to move to plane coordinates
675 my $offsetZ = 0; #-0.5 * $TPCActive_z;
676 my $offsetY = 0; #-0.5 * $TPCActive_y;
678 foreach my $wire (@winfo) {
679 my $wid = $wire->[0];
680 my $zpos = $wire->[1] + $offsetZ;
681 my $ypos = $wire->[2] + $offsetY;
684 <volumeref ref="volTPCWireU$wid"/>
685 <position name="posWireU$wid" unit="cm" x="0" y="$ypos" z="$zpos"/>
686 <rotationref ref="rUWireAboutX"/>
695 # 2nd induction plane
697 <volume name="volTPCPlaneY">
698 <materialref ref="LAr"/>
699 <solidref ref="CRMYPlane"/>
702 if ($wires_on==1) # add wires to Y plane (plane with wires reading y position)
704 for(my $i=0;$i<$nChans{'Ind2'};++$i)
706 #my $ypos = -0.5 * $TPCActive_y + ($i+0.5)*$wirePitchY + 0.5*$padWidth;
707 my $ypos = ($i + 0.5 - $nChans{'Ind2'}/2)*$wirePitchY;
708 if( (0.5 * $TPCActive_y - abs($ypos)) < 0 ){
709 die "Cannot place wire $i in view Y, as plane is too small\n";
713 <volumeref ref="volTPCWireY"/>
714 <position name="posWireY$i" unit="cm" x="0" y="$ypos" z="0"/>
715 <rotationref ref="rIdentity"/>
726 <volume name="volTPCPlaneZ">
727 <materialref ref="LAr"/>
728 <solidref ref="CRMZPlane"/>
730 if ($wires_on==1) # add wires to Z plane (plane with wires reading z position)
732 for(my $i=0;$i<$nChans{'Col'};++$i)
734 #my $zpos = -0.5 * $TPCActive_z + ($i+0.5)*$wirePitchZ + 0.5*$padWidth;
735 my $zpos = ($i + 0.5 - $nChans{'Col'}/2)*$wirePitchZ;
736 if( (0.5 * $TPCActive_z - abs($zpos)) < 0 ){
737 die "Cannot place wire $i in view Z, as plane is too small\n";
741 <volumeref ref="volTPCWireZ"/>
742 <position name="posWireZ$i" unit="cm" x="0" y="0" z="$zpos"/>
743 <rotationref ref="rPlus90AboutX"/>
753 $posUplane[0] = 0.5*$TPC_x - 2.5*$padWidth;
757 $posYplane[0] = 0.5*$TPC_x - 1.5*$padWidth;
761 $posZplane[0] = 0.5*$TPC_x - 0.5*$padWidth;
765 $posTPCActive[0] = -$ReadoutPlane/2;
766 $posTPCActive[1] = 0;
767 $posTPCActive[2] = 0;
770 #wrap up the TPC file
772 <volume name="volTPC">
773 <materialref ref="LAr"/>
774 <solidref ref="CRM"/>
776 <volumeref ref="volTPCPlaneU"/>
777 <position name="posPlaneU" unit="cm"
778 x="$posUplane[0]" y="$posUplane[1]" z="$posUplane[2]"/>
779 <rotationref ref="rIdentity"/>
782 <volumeref ref="volTPCPlaneY"/>
783 <position name="posPlaneY" unit="cm"
784 x="$posYplane[0]" y="$posYplane[1]" z="$posYplane[2]"/>
785 <rotationref ref="rIdentity"/>
788 <volumeref ref="volTPCPlaneZ"/>
789 <position name="posPlaneZ" unit="cm"
790 x="$posZplane[0]" y="$posZplane[1]" z="$posZplane[2]"/>
791 <rotationref ref="rIdentity"/>
794 <volumeref ref="volTPCActive"/>
795 <position name="posActive" unit="cm"
796 x="$posTPCActive[0]" y="$posTPCAtive[1]" z="$posTPCActive[2]"/>
797 <rotationref ref="rIdentity"/>
801 ## x="@{[$posTPCActive[0]+$padWidth]}" y="$posTPCActive[1]" z="$posTPCActive[2]"/>
811 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
812 #++++++++++++++++++++++++++++++++++++++ gen_FieldCage ++++++++++++++++++++++++++++++++++++
813 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
817 $FieldCage = $basename."_FieldCage" . $suffix . ".gdml";
818 push (@gdmlFiles, $FieldCage);
819 $FieldCage = ">" . $FieldCage;
820 open(FieldCage) or die("Could not open file $FieldCage for writing");
822 # The standard XML prefix and starting the gdml
823 print FieldCage <<EOF;
824 <?xml version='1.0'?>
827 # The printing solids used in the Field Cage
828 #print "lengthTPCActive : $lengthTPCActive \n";
829 #print "widthTPCActive : $widthTPCActive \n";
832 print FieldCage <<EOF;
834 <torus name="FieldShaperCorner" rmin="$FieldShaperInnerRadius" rmax="$FieldShaperOuterRadius" rtor="$FieldShaperTorRad" deltaphi="90" startphi="0" aunit="deg" lunit="cm"/>
835 <tube name="FieldShaperLongtube" rmin="$FieldShaperInnerRadius" rmax="$FieldShaperOuterRadius" z="$FieldShaperLongTubeLength" deltaphi="360" startphi="0" aunit="deg" lunit="cm"/>
836 <tube name="FieldShaperShorttube" rmin="$FieldShaperInnerRadius" rmax="$FieldShaperOuterRadius" z="$FieldShaperShortTubeLength" deltaphi="360" startphi="0" aunit="deg" lunit="cm"/>
838 <union name="FSunion1">
839 <first ref="FieldShaperLongtube"/>
840 <second ref="FieldShaperCorner"/>
841 <position name="esquinapos1" unit="cm" x="@{[-$FieldShaperTorRad]}" y="0" z="@{[0.5*$FieldShaperLongTubeLength]}"/>
842 <rotation name="rot1" unit="deg" x="90" y="0" z="0" />
845 <union name="FSunion2">
846 <first ref="FSunion1"/>
847 <second ref="FieldShaperShorttube"/>
848 <position name="esquinapos2" unit="cm" x="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[+0.5*$FieldShaperLongTubeLength+$FieldShaperTorRad]}"/>
849 <rotation name="rot2" unit="deg" x="0" y="90" z="0" />
852 <union name="FSunion3">
853 <first ref="FSunion2"/>
854 <second ref="FieldShaperCorner"/>
855 <position name="esquinapos3" unit="cm" x="@{[-$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[0.5*$FieldShaperLongTubeLength]}"/>
856 <rotation name="rot3" unit="deg" x="90" y="270" z="0" />
859 <union name="FSunion4">
860 <first ref="FSunion3"/>
861 <second ref="FieldShaperLongtube"/>
862 <position name="esquinapos4" unit="cm" x="@{[-$FieldShaperShortTubeLength-2*$FieldShaperTorRad]}" y="0" z="0"/>
865 <union name="FSunion5">
866 <first ref="FSunion4"/>
867 <second ref="FieldShaperCorner"/>
868 <position name="esquinapos5" unit="cm" x="@{[-$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength]}"/>
869 <rotation name="rot5" unit="deg" x="90" y="180" z="0" />
872 <union name="FSunion6">
873 <first ref="FSunion5"/>
874 <second ref="FieldShaperShorttube"/>
875 <position name="esquinapos6" unit="cm" x="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength-$FieldShaperTorRad]}"/>
876 <rotation name="rot6" unit="deg" x="0" y="90" z="0" />
879 <union name="FieldShaperSolid">
880 <first ref="FSunion6"/>
881 <second ref="FieldShaperCorner"/>
882 <position name="esquinapos7" unit="cm" x="@{[-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength]}"/>
883 <rotation name="rot7" unit="deg" x="90" y="90" z="0" />
889 print FieldCage <<EOF;
892 <volume name="volFieldShaper">
893 <materialref ref="Al2O3"/>
894 <solidref ref="FieldShaperSolid"/>
900 print FieldCage <<EOF;
909 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
910 #++++++++++++++++++++++++++++++++++++++ gen_Cryostat +++++++++++++++++++++++++++++++++++++
911 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
916 # Create the cryostat fragment file name,
917 # add file to list of output GDML fragments,
919 $CRYO = $basename."_Cryostat" . $suffix . ".gdml";
920 push (@gdmlFiles, $CRYO);
922 open(CRYO) or die("Could not open file $CRYO for writing");
925 # The standard XML prefix and starting the gdml
927 <?xml version='1.0'?>
931 # All the cryostat solids.
934 <box name="Cryostat" lunit="cm"
939 <box name="ArgonInterior" lunit="cm"
944 <box name="GaseousArgon" lunit="cm"
949 <subtraction name="SteelShell">
950 <first ref="Cryostat"/>
951 <second ref="ArgonInterior"/>
960 <volume name="volSteelShell">
961 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
962 <solidref ref="SteelShell" />
964 <volume name="volGaseousArgon">
965 <materialref ref="ArGas"/>
966 <solidref ref="GaseousArgon"/>
972 <volume name="volCryostat">
973 <materialref ref="LAr" />
974 <solidref ref="Cryostat" />
976 <volumeref ref="volGaseousArgon"/>
977 <position name="posGaseousArgon" unit="cm" x="@{[$Argon_x/2-$HeightGaseousAr/2]}" y="0" z="0"/>
980 <volumeref ref="volSteelShell"/>
981 <position name="posSteelShell" unit="cm" x="0" y="0" z="0"/>
986 if ($tpc_on==1) # place TPC inside croysotat offsetting each pair of CRMs by borderCRP
988 $posX = $Argon_x/2 - $HeightGaseousAr - 0.5*($driftTPCActive + $ReadoutPlane) - $LArOverhead; #20 cm overhead lar
989 #$posX = 10 - 0.5*($driftTPCActive + $ReadoutPlane);
991 my $posZ = -0.5*$Argon_z + $zLArBuffer + 0.5*$lengthCRM;
992 for(my $ii=0;$ii<$nCRM_z;$ii++)
1000 my $posY = -0.5*$Argon_y + $yLArBuffer + 0.5*$widthCRM;
1001 for(my $jj=0;$jj<$nCRM_x;$jj++)
1004 $posY += $borderCRP;
1006 $posY += $borderCRP;
1011 <volumeref ref="volTPC"/>
1012 <position name="posTPC\-$idx" unit="cm"
1013 x="$posX" y="$posY" z="$posZ"/>
1020 $posZ += $lengthCRM;
1025 #The +50 in the x positions must depend on some other parameter
1026 if ( $FieldCage_switch eq "on" ) {
1027 for ( $i=0; $i<$NFieldShapers; $i=$i+1 ) { # pmts with coating
1028 $posX = $Argon_x/2 - $HeightGaseousAr - 0.5*($driftTPCActive + $ReadoutPlane);
1031 <volumeref ref="volFieldShaper"/>
1032 <position name="posFieldShaper$i" unit="cm" x="@{[-$OriginXSet+50+($i-$NFieldShapers*0.5)*$FieldShaperSeparation]}" y="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" z="0" />
1033 <rotation name="rotFS$i" unit="deg" x="0" y="0" z="90" />
1040 $CathodePosX =-$OriginXSet+50+(-1-$NFieldShapers*0.5)*$FieldShaperSeparation;
1043 if ( $Cathode_switch eq "on" )
1047 <volumeref ref="volGroundGrid"/>
1048 <position name="posGroundGrid01" unit="cm" x="$CathodePosX" y="@{[-$CathodePosY]}" z="@{[$CathodePosZ]}"/>
1049 <rotation name="rotGG01" unit="deg" x="0" y="0" z="90" />
1067 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1068 #+++++++++++++++++++++++++++++++++++++ gen_Enclosure +++++++++++++++++++++++++++++++++++++
1069 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1074 # Create the detector enclosure fragment file name,
1075 # add file to list of output GDML fragments,
1077 $ENCL = $basename."_DetEnclosure" . $suffix . ".gdml";
1078 push (@gdmlFiles, $ENCL);
1079 $ENCL = ">" . $ENCL;
1080 open(ENCL) or die("Could not open file $ENCL for writing");
1083 # The standard XML prefix and starting the gdml
1085 <?xml version='1.0'?>
1090 # All the detector enclosure solids.
1094 <box name="FoamPadBlock" lunit="cm"
1095 x="@{[$Cryostat_x + 2*$FoamPadding]}"
1096 y="@{[$Cryostat_y + 2*$FoamPadding]}"
1097 z="@{[$Cryostat_z + 2*$FoamPadding]}" />
1099 <subtraction name="FoamPadding">
1100 <first ref="FoamPadBlock"/>
1101 <second ref="Cryostat"/>
1102 <positionref ref="posCenter"/>
1105 <box name="SteelSupportBlock" lunit="cm"
1106 x="@{[$Cryostat_x + 2*$FoamPadding + 2*$SteelSupport_x]}"
1107 y="@{[$Cryostat_y + 2*$FoamPadding + 2*$SteelSupport_y]}"
1108 z="@{[$Cryostat_z + 2*$FoamPadding + 2*$SteelSupport_z]}" />
1110 <subtraction name="SteelSupport">
1111 <first ref="SteelSupportBlock"/>
1112 <second ref="FoamPadBlock"/>
1113 <positionref ref="posCenter"/>
1116 <box name="DetEnclosure" lunit="cm"
1125 # Detector enclosure structure
1128 <volume name="volFoamPadding">
1129 <materialref ref="fibrous_glass"/>
1130 <solidref ref="FoamPadding"/>
1133 <volume name="volSteelSupport">
1134 <materialref ref="AirSteelMixture"/>
1135 <solidref ref="SteelSupport"/>
1138 <volume name="volDetEnclosure">
1139 <materialref ref="Air"/>
1140 <solidref ref="DetEnclosure"/>
1143 <volumeref ref="volFoamPadding"/>
1144 <positionref ref="posCryoInDetEnc"/>
1147 <volumeref ref="volSteelSupport"/>
1148 <positionref ref="posCryoInDetEnc"/>
1151 <volumeref ref="volCryostat"/>
1152 <positionref ref="posCryoInDetEnc"/>
1171 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1172 #+++++++++++++++++++++++++++++++++++++++ gen_World +++++++++++++++++++++++++++++++++++++++
1173 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1178 # Create the WORLD fragment file name,
1179 # add file to list of output GDML fragments,
1181 $WORLD = $basename."_World" . $suffix . ".gdml";
1182 push (@gdmlFiles, $WORLD);
1183 $WORLD = ">" . $WORLD;
1184 open(WORLD) or die("Could not open file $WORLD for writing");
1187 # The standard XML prefix and starting the gdml
1189 <?xml version='1.0'?>
1194 # All the World solids.
1197 <box name="World" lunit="cm"
1198 x="@{[$DetEncX+2*$RockThickness]}"
1199 y="@{[$DetEncY+2*$RockThickness]}"
1200 z="@{[$DetEncZ+2*$RockThickness]}"/>
1207 <volume name="volWorld" >
1208 <materialref ref="DUSEL_Rock"/>
1209 <solidref ref="World"/>
1212 <volumeref ref="volDetEnclosure"/>
1213 <position name="posDetEnclosure" unit="cm" x="$OriginXSet" y="$OriginYSet" z="$OriginZSet"/>
1221 # make_gdml.pl will take care of <setup/>
1228 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1229 #++++++++++++++++++++++++++++++++++++ write_fragments ++++++++++++++++++++++++++++++++++++
1230 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1232 sub write_fragments()
1234 # This subroutine creates an XML file that summarizes the the subfiles output
1235 # by the other sub routines - it is the input file for make_gdml.pl which will
1236 # give the final desired GDML file. Specify its name with the output option.
1237 # (you can change the name when running make_gdml)
1239 # This code is taken straigh from the similar MicroBooNE generate script, Thank you.
1241 if ( ! defined $output )
1243 $output = "-"; # write to STDOUT
1246 # Set up the output file.
1247 $OUTPUT = ">" . $output;
1248 open(OUTPUT) or die("Could not open file $OUTPUT");
1251 <?xml version='1.0'?>
1253 <!-- Input to Geometry/gdml/make_gdml.pl; define the GDML fragments
1254 that will be zipped together to create a detector description.
1261 <!-- These files contain GDML <constant></constant>
1262 blocks. They are read in separately, so they can be
1263 interpreted into the remaining GDML. See make_gdml.pl for
1269 foreach $filename (@defFiles)
1272 <filename> $filename </filename>
1282 <!-- The GDML file fragments to be zipped together. -->
1286 foreach $filename (@gdmlFiles)
1289 <filename> $filename </filename>
1304 print "Some of the principal parameters for this TPC geometry (unit cm unless noted otherwise)\n";
1305 print " CRM active area : $widthCRM_active x $lengthCRM_active\n";
1306 print " CRM total area : $widthCRM x $lengthCRM\n";
1307 print " Wire pitch in U, Y, Z : $wirePitchU, $wirePitchY, $wirePitchZ\n";
1308 print " TPC active volume : $driftTPCActive x $widthTPCActive x $lengthTPCActive\n";
1309 print " Argon volume : ($Argon_x, $Argon_y, $Argon_z) \n";
1310 print " Argon buffer : ($xLArBuffer, $yLArBuffer, $zLArBuffer) \n";
1311 print " Detector enclosure : $DetEncX x $DetEncY x $DetEncZ\n";
1312 print " TPC Origin : ($OriginXSet, $OriginYSet, $OriginZSet) \n";
1313 print " Field Cage : $FieldCage_switch \n";
1314 print " Cathode : $Cathode_switch \n";
1315 print " Workspace : $workspace \n";
1316 print " Wires : $wires_on \n";
1318 # run the sub routines that generate the fragments
1319 if ( $FieldCage_switch eq "on" ) { gen_FieldCage(); }
1320 #if ( $Cathode_switch eq "on" ) { gen_Cathode(); } #Cathode for now has the same geometry as the Ground Grid
1322 gen_Extend(); # generates the GDML color extension for the refactored geometry
1323 gen_Define(); # generates definitions at beginning of GDML
1324 gen_Materials(); # generates materials to be used
1325 gen_TPC(); # generate TPC for a given unit CRM
1328 gen_World(); # places the enclosure among DUSEL Rock
1329 write_fragments(); # writes the XML input for make_gdml.pl
1330 # which zips together the final GDML
1331 print "--- done\n\n\n";