3 # contact tylerdalion@gmail.com for any GDML/generate questions
4 # I would love to help!
6 # Each subroutine generates a fragment GDML file, and the last subroutine
7 # creates an XML file that make_gdml.pl will use to appropriately arrange
8 # the fragment GDML files to create the final desired DUNE GDML file,
9 # to be named by make_gdml output command
11 # If you are playing with different geometries, you can use the
12 # suffix command to help organize your work.
19 Math::BigFloat->precision(-16);
21 open(my $wout, '>', 'gdmlWireCenters.txt');
23 GetOptions( "help|h" => \$help,
24 "suffix|s:s" => \$suffix,
25 "workspace|k:s" => \$workspace,
26 "output|o:s" => \$output,
27 "wires|w:s" => \$wires,
28 "protoDune|p:s" => \$protoDune);
32 # If the user requested help, print the usage notes and exit.
37 if ( ! defined $suffix )
39 # The user didn't supply a suffix, so append nothing to the file
45 # Otherwise, stick a "-" before the suffix, so that a suffix of
46 # "test" applied to filename.gdml becomes "filename-test.gdml".
47 $suffix = "-" . $suffix;
50 if ( ! defined $workspace )
53 if ( ! defined $protoDune )
56 print "\t\tCreating full geometry.\n";
58 elsif ( $protoDune == 1 )
60 print "\t\tCreating rough version of protoDUNE.\n";
63 elsif ( $workspace == 1)
65 print "\t\tCreating smaller (1x2x2-APA) workspace geometry.\n";
67 elsif ( $workspace == 2)
69 print "\t\tCreating 1x2x6-APA geometry.\n";
72 # set wires on to be the default, unless given an input by the user
73 $wires_on = 1; # 1=on, 0=off
83 # options for different parameters
89 #++++++++++++++++++++++++ Begin defining variables +++++++++++++++++++++++++
91 ## The GDML is build from the inside out to avoid overlaps, but that means
92 ## that the larger dimensions (such as the cryostat dimensions) are calculated
93 ## to be slightly different than the parameters calculated and reported by
94 ## engineers. All of this error is within reason and for the better, since
95 ## we don't want this Geometry to be overly complex or long.
100 ##################################################################
101 ##################### Wire Plane Parameters ######################
104 $UWirePitch = 0.4667;
105 $VWirePitch = 0.4667;
109 $nZChannelsPerAPA = 960;
111 # dune10kt 3mm version
112 if($Pitch3mmVersion==1){
116 $nZChannelsPerAPA = 2*(229.44/0.3 + 1);
119 # dune10kt ~45 deg UV wires version
120 if($UVAngle45Option==1){
135 $SinUAngle = sin( deg2rad($UAngle) );
136 $CosUAngle = cos( deg2rad($UAngle) );
137 $TanUAngle = tan( deg2rad($UAngle) );
139 $SinVAngle = sin( deg2rad($VAngle) );
140 $CosVAngle = cos( deg2rad($VAngle) );
141 $TanVAngle = tan( deg2rad($VAngle) );
143 $UWire_yint = $UWirePitch/$SinUAngle;
144 $UWire_zint = $UWirePitch/$CosUAngle;
146 $VWire_yint = $VWirePitch/$SinVAngle;
147 $VWire_zint = $VWirePitch/$CosVAngle;
149 $TPCWireThickness = 0.015;
151 $TPCWirePlaneThickness = $TPCWireThickness;
152 #height and length defined lower
156 ##################################################################
157 ################### Cryostat/APA parameters ######################
163 elsif($workspace==2){
168 $nAPAs = $nAPAWide*$nAPAHigh*$nAPALong;
171 $G10thickness = $inch/8;
172 $WrapCover = $inch/16;
174 $SpaceAPAToCryoWall = 15;
175 $SpaceAPAToFloor = 59.4 - 10.2; # 10.2cm just adjusts for how spaces are reported
176 $SpaceAPAToTopLAr = 50.9 - 10.2;
177 $UpstreamLArPadding = 311.4 - 10.2;
178 $DownstreamLArPadding = 59.4 - 10.2;
181 $SpaceAPAToCryoWall = 20;
182 $SpaceAPAToFloor = 45;
183 $SpaceAPAToTopLAr = 45;
184 $UpstreamLArPadding = 80;
185 $DownstreamLArPadding = 80;
188 #InnerDrift is the max distance form the edge of the CPA to the edge of the first wire plane
190 $OuterDrift = $SpaceAPAToCryoWall;
191 $APAFrame_x = 5.0661; # ~2in -- this does not include the wire spacing
193 $TPCWireThickness = 0.015;
194 $TPCWirePlaneThickness = $TPCWireThickness;
195 #$APAWirePlaneSpacing = 0.4730488 + $TPCWirePlaneThickness; # center to center spacing between all of the wire planes (g, u, v, and x)
197 if($Pitch3mmVersion==1){
198 $APAWirePlaneSpacing = 0.3;
200 $APAWirePlaneSpacing = 0.476;
203 # At creation of the plane volumes, the y and z boundaries will be increased
204 # by this much at each of the 4 edges. this is so the corners of the wire
205 # tubes don't extrude. For all other purposes, the plane dimensions stay as originally defined
206 $UVPlaneBoundNudge = $TPCWireThickness;
210 # The following are all widths about the z center of an APA
211 $Zactive_z = ($nZChannelsPerAPA/2-1)*$XWirePitch + $TPCWireThickness;
212 $APAFrame_z = 231.59 - 2*(2*$G10thickness+$WrapCover);
213 $Vactive_z = $APAFrame_z;
214 $Uactive_z = $APAFrame_z + 2*$G10thickness;
219 $ReadoutBoardOverlap = 7.61; #board overlaps wires, chop this off of their active height
221 $Zactive_y = $APAFrame_y + 0*$G10thickness - $ReadoutBoardOverlap;
222 $Vactive_y = $APAFrame_y + 1*$G10thickness - $ReadoutBoardOverlap;
223 $Uactive_y = $APAFrame_y + 2*$G10thickness - $ReadoutBoardOverlap;
224 # the last G10 board for the grid, then a cover. This is not "covered" by the board
225 $APAphys_y = $APAFrame_y + 4*$G10thickness + $WrapCover;
227 $APAGap_y = 0.4; #separation between APAs (cover to cover) along the incident beam axis
228 $APAGap_z = 0.8; #separation between APAs (cover to cover) along the vertical axis
231 # include APA spacing in y and z so volTPCs touch in y and z directions with correct APA
232 # spacing - this makes for smoother event generation.
234 $APA_UtoU_x = $APAFrame_x + 6*$APAWirePlaneSpacing + $TPCWirePlaneThickness; # thickness of APA between its
235 # outer wire planes (center to center)
236 $TPCInner_x = $InnerDrift + 3*$APAWirePlaneSpacing + $TPCWirePlaneThickness;
237 $TPCOuter_x = $OuterDrift + 3*$APAWirePlaneSpacing + $TPCWirePlaneThickness;
239 $TPC_z = $APAphys_z + $APAGap_z;
240 $TPC_y = $APAphys_y + $APAGap_y;
243 #$CPATube_ID = 4.747;
246 $Cathode_y = $APAphys_y - $CPATube_OD;
247 $Cathode_z = $APAphys_z - $CPATube_OD;
250 $APAToAPA = $APAFrame_x
252 + $Cathode_x; # center to center
254 $CPAToAPA = $APAFrame_x/2
256 + $Cathode_x/2; # center to center
258 $SteelThickness = 0.5*$inch; #half inch
259 $HeightGaseousAr = 50;
261 $Argon_x = ($nAPAWide-1)*$APAToAPA
262 + $APA_UtoU_x + $TPCWirePlaneThickness
263 + 2*$SpaceAPAToCryoWall;
267 $FC_x = ($nAPAWide-1)*$APAToAPA
268 + $APA_UtoU_x + $TPCWirePlaneThickness;
270 if($workspace==1||$workspace==2){ # this is arbitrary for the workspace, but size down a little
271 $Argon_x = 2*$CPAToAPA + $Cathode_x + 2*$SpaceAPAToCryoWall;
272 $FC_x = 2*$CPAToAPA + $Cathode_x;
276 $LArgon_y = $nAPAHigh*$APAphys_y
277 + ($nAPAHigh-1)*$APAGap_y
278 + $SpaceAPAToFloor + $SpaceAPAToTopLAr;
282 $Argon_z = $nAPALong*$APAphys_z
283 + ($nAPALong-1)*$APAGap_z
284 + $UpstreamLArPadding + $DownstreamLArPadding;
286 $FCI_y = $nAPAHigh*$TPC_y+$FC_b; #The +FC_b is an arbitrary +2cm to make sure the FC doesn't contact the APA or CPAs.
287 $FCO_y = $FCI_y+(0.1*$inch)*2; #The outer boundary of the Fied Cage
288 $FCI_z = $nAPALong*$TPC_z
289 + $FC_b; #the plus FC_b is +2 cm arbitrarily. This makes sure the FC doesn't contact the APAs.
290 $FCO_z = $FCI_z+(0.1*$inch)*2;
292 $FC_b = 2; #2 cm buffer for FC
294 $Cryostat_x = $Argon_x + 2*$SteelThickness;
295 $Cryostat_y = $Argon_y + 2*$SteelThickness;
296 $Cryostat_z = $Argon_z + 2*$SteelThickness;
300 ##################################################################
301 ############## DetEnc and World relevant parameters #############
304 $SteelSupport_x = 100;
305 $SteelSupport_y = 50;
306 $SteelSupport_z = 100;
308 $FracMassOfSteel = 0.998; #The steel support is not a solid block, but a mixture of air and steel
309 $FracMassOfAir = 1-$FracMassOfSteel;
311 $SpaceSteelSupportToWall = 100;
312 $SpaceSteelSupportToCeiling = 100;
314 $DetEncWidth = $Cryostat_x
315 + 2*($SteelSupport_x + $FoamPadding) + $SpaceSteelSupportToCeiling;
316 $DetEncHeight = $Cryostat_y
317 + 2*($SteelSupport_y + $FoamPadding) + 2*$SpaceSteelSupportToWall;
318 $DetEncLength = $Cryostat_z
319 + 2*($SteelSupport_z + $FoamPadding) + 2*$SpaceSteelSupportToWall;
321 $posCryoInDetEnc_y = - $DetEncHeight/2 + $SteelSupport_y + $FoamPadding + $Cryostat_y/2;
323 $RockThickness = 3000;
324 if ($workspace == 0){
325 # Initially, the world dimensions and the OriginZSet
326 # left only ~222cm to the world boundary from the
327 # +z boundary of volDetEnclosure. Bump that up to
328 # at least 10m for good measure.
329 # This is in an if statement so that it does not affect
330 # the workspace geometries, which are already being used
331 $RockThickness += 800
334 # We want the world origin to be at the very front of the fiducial volume.
335 # move it to the front of the enclosure, then back it up through the concrete/foam,
336 # then through the Cryostat shell, then through the upstream dead LAr (including the
337 # dead LAr on the edge of the TPC, but this is covered in $UpstreamLArPadding).
338 # This is to be added to the z position of every volume in volWorld
340 $OriginZSet = $DetEncLength/2
341 - $SpaceSteelSupportToWall
345 - $UpstreamLArPadding
346 - ($APAphys_z - $Uactive_z)/2;
348 # We want the world origin to be vertically centered between the stacked APAs.
349 # This is to be added to the y position of every volume in volWorld
351 $OriginYSet = $DetEncHeight/2
359 if($protoDune==1){ # bring the origin to the bottom of the APAs for protoDUNE
360 $OriginYSet = $OriginYSet + $APAphys_y + $APAGap_y/2;
363 $OriginXSet = 0; # centered for now
370 ####################################################################
371 ######################## Paddle Dimensions ########################
373 $APAFrameZSide_y = 4*$inch;
374 $APAFrameYSide_z = 4*$inch;
375 $LightPaddle_x = 0.476;
376 $LightPaddle_y = 4*$inch;
377 $LightPaddle_z = $APAFrame_z - 2*$APAFrameYSide_z;
378 $nLightPaddlesPerAPA = 10; # 10, or 20 for double coverage (for now)
379 $PaddleYInterval = (2*$APAphys_y+$APAGap_y-$LightPaddle_y-2*$APAFrameZSide_y)
380 /(2*$nLightPaddlesPerAPA-1);
381 $FrameToPaddleSpace = ($PaddleYInterval-$APAGap_y)/2;
385 # $PaddleYInterval is defined so that the center-to-center distance in the
386 # y direction between paddles is uniform between vertically stacked APAs.
387 # $FrameToPaddleSpace is from the BOTTOM of the APA frame (4" in y direction)
388 # to the CENTER of a paddle, including the 4" part of the frame. This variable's
389 # primary purpose is to position the lowest paddle in each APA.
394 #+++++++++++++++++++++++++ End defining variables ++++++++++++++++++++++++++
397 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
398 #+++++++++++++++++++++++++++++++++++++++++ usage +++++++++++++++++++++++++++++++++++++++++
399 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
403 print "Usage: $0 [-h|--help] [-o|--output <fragments-file>] [-s|--suffix <string>]\n";
404 print " if -o is omitted, output goes to STDOUT; <fragments-file> is input to make_gdml.pl\n";
405 print " -s <string> appends the string to the file names; useful for multiple detector versions\n";
406 print " -h prints this message, then quits\n";
411 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
412 #++++++++++++++++++++++++++++++++++++++ gen_Define +++++++++++++++++++++++++++++++++++++++
413 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
418 # Create the <define> fragment file name,
419 # add file to list of fragments,
421 $DEF = "dune10kt_v2_Def" . $suffix . ".gdml";
422 push (@gdmlFiles, $DEF);
424 open(DEF) or die("Could not open file $DEF for writing");
428 <?xml version='1.0'?>
438 <position name="posCryoInDetEnc" unit="cm" x="0" y="@{[$posCryoInDetEnc_y]}" z="0"/>
439 <position name="posCenter" unit="cm" x="0" y="0" z="0"/>
440 <rotation name="rPlus90AboutX" unit="deg" x="90" y="0" z="0"/>
441 <rotation name="rMinus90AboutY" unit="deg" x="0" y="270" z="0"/>
442 <rotation name="rMinus90AboutYMinus90AboutX" unit="deg" x="270" y="270" z="0"/>
443 <rotation name="rPlusUAngleAboutX" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
444 <rotation name="rPlusVAngleAboutX" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
445 <rotation name="rPlus180AboutX" unit="deg" x="180" y="0" z="0"/>
446 <rotation name="rPlus180AboutY" unit="deg" x="0" y="180" z="0"/>
447 <rotation name="rPlus180AboutXPlus180AboutY" unit="deg" x="180" y="180" z="0"/>
448 <rotation name="rIdentity" unit="deg" x="0" y="0" z="0"/>
455 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
456 #+++++++++++++++++++++++++++++++++++++ gen_Materials +++++++++++++++++++++++++++++++++++++
457 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
462 # Create the <materials> fragment file name,
463 # add file to list of output GDML fragments,
465 $MAT = "dune10kt_v2_Materials" . $suffix . ".gdml";
466 push (@gdmlFiles, $MAT);
469 open(MAT) or die("Could not open file $MAT for writing");
471 # Add any materials special to this geometry by defining a mulitline string
472 # and passing it to the gdmlMaterials::gen_Materials() function.
474 $DensityAirSteel = 1/(0.001205/$FracMassOfAir + 7.9300/$FracMassOfSteel);
477 <!-- preliminary values -->
478 <material name="AirSteelMixture" formula="AirSteelMixture">
479 <D value="$DensityAirSteel" unit="g/cm3"/>
480 <fraction n="$FracMassOfSteel" ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
481 <fraction n="$FracMassOfAir" ref="Air"/>
485 # add the general materials used anywere
486 print MAT gdmlMaterials::gen_Materials( $asmix );
491 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
492 #++++++++++++++++++++++++++++++++++++++++ gen_TPC ++++++++++++++++++++++++++++++++++++++++
493 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
504 my $TPCActive_x = $_[0]-(3*$APAWirePlaneSpacing);
505 my $TPCActive_y = $_[1] - $APAGap_y/2 - $ReadoutBoardOverlap ; #TODO: make the Active height more accurate
506 my $TPCActive_z = $_[2];
509 #constructs everything inside volTPC, namely
510 # (moving from left to right, or from +x to -x)
512 # -volTPCPlaneU: with wires angled from vertical slightly different than in V
513 # -volTPCPlaneV: with wires angled from vertical slightly differently than in U
514 # -volTPCPlaneX: with vertical wires
517 # Create the TPC fragment file name,
518 # add file to list of output GDML fragments,
520 $TPC = "dune10kt_v2_TPC_${_[3]}" . $suffix . ".gdml";
521 push (@gdmlFiles, $TPC);
523 open(TPC) or die("Could not open file $TPC for writing");
526 print $wout "\n\n\n----- Wires for $_[3] -----\n\n\n";
529 # The standard XML prefix and starting the gdml
531 <?xml version='1.0'?>
536 # All the TPC solids save the wires.
539 <box name="$_[3]" lunit="cm"
543 <box name="${_[3]}UPlane" lunit="cm"
544 x="@{[$TPCWirePlaneThickness]}"
545 y="@{[$Uactive_y + $UVPlaneBoundNudge]}"
546 z="@{[$Uactive_z + $UVPlaneBoundNudge]}"/>
547 <box name="${_[3]}VPlane" lunit="cm"
548 x="@{[$TPCWirePlaneThickness]}"
549 y="@{[$Vactive_y + $UVPlaneBoundNudge]}"
550 z="@{[$Vactive_z + $UVPlaneBoundNudge]}"/>
551 <box name="${_[3]}ZPlane" lunit="cm"
552 x="@{[$TPCWirePlaneThickness]}"
554 z="@{[$Zactive_z]}"/>
555 <box name="${_[3]}Active" lunit="cm"
556 x="@{[$TPCActive_x]}"
557 y="@{[$TPCActive_y]}"
558 z="@{[$TPCActive_z]}"/>
562 #++++++++++++++++++++++++++++ Wire Solids ++++++++++++++++++++++++++++++
566 <tube name="${_[3]}WireVert"
567 rmax="@{[0.5*$TPCWireThickness]}"
574 # Set number of wires to default to zero, when $wires_on = 0, for a low memory
575 # version. But if $wires_on = 1, calculate the number of wires on each side of each
576 # plane to be used in the for loops
578 my $NumberCornerUWires = 0;
579 my $NumberSideUWires = 0;
580 my $NumberCommonUWires = 0;
581 my $NumberCornerVWires = 0;
582 my $NumberSideVWires = 0;
583 my $NumberCommonVWires = 0;
584 my $NumberVerticalWires = 0;
588 # Number of wires in one corner
589 $NumberCornerUWires = int( $APAFrame_z/($UWirePitch/$CosUAngle) );
591 $NumberCornerVWires = int( $APAFrame_z/($VWirePitch/$CosVAngle) );
594 # Total number of wires touching one vertical (longer) side
595 # Note that the total number of wires per plane is this + another set of corner wires
596 $NumberSideUWires = int( $Uactive_y/$UWire_yint );
597 if($Pitch3mmVersion==1){ $NumberSideUWires = $NumberSideUWires-1; }
599 $NumberSideVWires = int( $Vactive_y/$VWire_yint );
601 # Number of wires per side that aren't cut off by the corner
602 $NumberCommonUWires = $NumberSideUWires - $NumberCornerUWires;
604 $NumberCommonVWires = $NumberSideVWires - $NumberCornerVWires;
606 # Number of wires on the vertical plane
607 # Since APA Active z is defined in docdb 3383 to be distance
608 # between outer vertical wires, + 1 since the floor of this
609 # division will be one under, giving the amt of spaces, not wires
610 $NumberVerticalWires = int( $Zactive_z/$XWirePitch ) + 1;
611 #$NumberVerticalWires = 960;
614 $nUchans = 2*$NumberCornerUWires;
615 $nVchans = 2*$NumberCornerVWires;
617 print $wout "$nUchans U channels\n";
618 print $wout "$nVchans V channels\n";
619 print $wout "$NumberVerticalWires Z channels per side\n";
621 print $wout "$NumberCornerUWires U corner wires\n";
622 print $wout "$NumberCommonUWires U common wires\n";
623 print $wout "$NumberCornerVWires V corner wires\n";
624 print $wout "$NumberCommonVWires V common wires\n";
628 # hard codeed number will be a factor determined from engineering spreadsheets on wire endpoints,
629 # but since that won't exist for a while, use this number to avoid overlaps
630 my $FirstUWireOffset = .55 + $G10thickness + 2*$G10thickness*$TanUAngle - $UWire_zint;
631 my $FirstVWireOffset = .5; # doesnt include a G10 board in width
633 if($Pitch3mmVersion==1){
634 my $FirstUWireOffset = .15 + $G10thickness + 2*$G10thickness*$TanUAngle - $UWire_zint;
635 my $FirstVWireOffset = .15; # doesnt include a G10 board in width
638 if($UVAngle45Option==1){$FirstVWireOffset = .7;}
641 my $FirstTopUWire_yspan =
644 + $FirstUWireOffset/$TanUAngle # walk us up to the first wire
645 + $UWire_yint*($NumberSideUWires-1) # up to the top of the top common wire
646 - $Uactive_z/$TanUAngle # back to the bottom of the top common wire
647 + $UWire_yint); # nudge up to bottom of the first top corner wire
649 my $FirstTopVWire_yspan =
652 + $FirstVWireOffset/$TanVAngle # walk us up to the first wire
653 + $VWire_yint*($NumberSideVWires-1) # up to the top of the top common wire
654 - $Vactive_z/$TanVAngle # back to the bottom of the top common wire
655 + $VWire_yint); # nudge up to bottom of the first top corner wire
658 # The corner wires for the U plane
661 for ($i = 0; $i < $NumberCornerUWires; $i++)
663 $CornerUWireLength[$i] = ($FirstUWireOffset + $i*$UWire_zint)/$SinUAngle;
666 <tube name="${_[3]}WireU$i"
667 rmax="@{[0.5*$TPCWireThickness]}"
668 z="@{[$CornerUWireLength[$i]]}"
676 $CommonUWireLength = $Uactive_z/$SinUAngle;
679 <tube name="${_[3]}WireUCommon"
680 rmax="@{[0.5*$TPCWireThickness]}"
681 z="@{[$CommonUWireLength]}"
687 for ($i = 0; $i < $NumberCornerUWires; $i++)
690 $TopCornerUWireLength[$i] = ($FirstTopUWire_yspan - $i*$UWire_yint)/$CosUAngle;
692 $j = $i + $NumberSideUWires;
695 <tube name="${_[3]}WireU$j"
696 rmax="@{[0.5*$TPCWireThickness]}"
697 z="@{[$TopCornerUWireLength[$i]]}"
708 # The corner wires for the V plane
711 for ($i = 0; $i < $NumberCornerVWires; ++$i)
713 $CornerVWireLength[$i] = ($FirstVWireOffset + $i*$VWire_zint)/$SinVAngle;
717 <tube name="${_[3]}WireV$i"
718 rmax="@{[0.5*$TPCWireThickness]}"
719 z="@{[$CornerVWireLength[$i]]}"
728 # The wire used many times in the middle of the V plane
729 # Same subtraction as U common
731 $CommonVWireLength = $Vactive_z/$SinVAngle;
734 <tube name="${_[3]}WireVCommon"
735 rmax="@{[0.5*$TPCWireThickness]}"
736 z="@{[$CommonVWireLength]}"
742 for ($i = 0; $i < $NumberCornerVWires; $i++)
745 $TopCornerVWireLength[$i] = ($FirstTopVWire_yspan - $i*$VWire_yint)/$CosVAngle;
747 $j = $i + $NumberSideVWires;
750 <tube name="${_[3]}WireV$j"
751 rmax="@{[0.5*$TPCWireThickness]}"
752 z="@{[$TopCornerVWireLength[$i]]}"
763 # Begin structure and create the vertical wire logical volume
767 <volume name="volTPCActive${_[3]}">
768 <materialref ref="LAr"/>
769 <solidref ref="${_[3]}Active"/>
778 <volume name="volTPCWireVert${_[3]}">
779 <materialref ref="Copper_Beryllium_alloy25"/>
780 <solidref ref="${_[3]}WireVert"/>
784 # Corner U wires logical volumes
785 for ($i = 0; $i < $NumberCornerUWires; ++$i)
788 <volume name="volTPCWireU$i${_[3]}">
789 <materialref ref="Copper_Beryllium_alloy25"/>
790 <solidref ref="${_[3]}WireU$i"/>
796 # Top Corner U wires logical volumes
797 for ($j = $NumberSideUWires; $j < $NumberSideUWires + $NumberCornerUWires; ++$j)
800 <volume name="volTPCWireU$j${_[3]}">
801 <materialref ref="Copper_Beryllium_alloy25"/>
802 <solidref ref="${_[3]}WireU$j"/>
808 # Common U wire logical volume, referenced many times
810 <volume name="volTPCWireUCommon${_[3]}">
811 <materialref ref="Copper_Beryllium_alloy25"/>
812 <solidref ref="${_[3]}WireUCommon"/>
817 # Corner V wires logical volumes
818 for ($i = 0; $i < $NumberCornerVWires; ++$i)
821 <volume name="volTPCWireV$i${_[3]}">
822 <materialref ref="Copper_Beryllium_alloy25"/>
823 <solidref ref="${_[3]}WireV$i"/>
829 # Top Corner V wires logical volumes
830 for ($j = $NumberSideVWires; $j < $NumberSideVWires + $NumberCornerVWires; ++$j)
833 <volume name="volTPCWireV$j${_[3]}">
834 <materialref ref="Copper_Beryllium_alloy25"/>
835 <solidref ref="${_[3]}WireV$j"/>
840 # Common V wire logical volume, referenced many times
842 <volume name="volTPCWireVCommon${_[3]}">
843 <materialref ref="Copper_Beryllium_alloy25"/>
844 <solidref ref="${_[3]}WireVCommon"/>
855 #+++++++++++++++++++++++++ Position physical wires ++++++++++++++++++++++++++
857 # ++++++++++++++++++++++ U Plane +++++++++++++++++++++++
859 # Create U plane logical volume
861 <volume name="volTPCPlaneU${_[3]}">
862 <materialref ref="LAr"/>
863 <solidref ref="${_[3]}UPlane"/>
867 print $wout "\n- Wires for U plane -\n\n";
868 print $wout " Uplane_y: $Uactive_y\n";
869 print $wout " Uplane_z: $Uactive_z\n";
875 # Starting with the bottom left corner wires:
876 # x=0 to center the wires in the plane
877 # y positioning: (-0.5*$TPCWirePlaneHeight) starts the incremental increase
878 # from the bottom of the plane, and trigonometry gives the increment
879 # z positioning: Looking at the plane from the positive x direction,
880 # (0.5*$TPCWirePlaneLength) starts the incremental increase from
881 # the lower left corner.
882 # rotation: same as common wire in code below
884 $FirstU_ypos = - $Uactive_y/2 + $FirstUWireOffset/$TanUAngle/2;
885 $FirstU_zpos = + $Uactive_z/2 - $FirstUWireOffset/2;
887 for ($i = 0; $i < $NumberCornerUWires; ++$i)
890 my $ypos = $FirstU_ypos + ($i)*0.5*$UWire_yint;
891 my $zpos = $FirstU_zpos - ($i)*0.5*$UWire_zint;
893 $pitch = ($ypos - $lastYpos) * $SinUAngle
894 - ($zpos - $lastZpos) * $CosUAngle;
898 <volumeref ref="volTPCWireU$i${_[3]}"/>
899 <position name="pos${_[3]}WireU$i" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
900 <rotation name="rUAngle$i" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
904 $topY = $ypos + ($CosUAngle*$CornerUWireLength[$i]/2);
905 $bottomY = $ypos - ($CosUAngle*$CornerUWireLength[$i]/2);
906 $edgeZ_p = $zpos + ($SinUAngle*$CornerUWireLength[$i]/2);
907 $edgeZ_m = $zpos - ($SinUAngle*$CornerUWireLength[$i]/2);
908 print $wout "U$i: ( $ypos , $zpos ) (pitch = $pitch)\n";
909 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
917 # Moving upwards to the common wires:
918 # x and z are zero to center the wires along a vertical axis
919 # y positioning: The trick is positioning the lowest common wire so that the pitch
920 # is consistent, then the increment is double the increment of
921 # the corner wires since there is no z incriment.
922 # rotation: wires in \\\\ direction, so +90deg to bring them to vertical and
923 # +UAngle counterclockwise to arrive at proper orientation
924 # Note that the counter maintains wire number (in pos. name) counting bottom to top
927 my $StartCommonUWires_ypos = $lastYpos + $UWire_yint - abs( $lastZpos )/$TanUAngle;
929 for ($i = $NumberCornerUWires; $i < $NumberSideUWires; ++$i)
932 $j = $i - $NumberCornerUWires;
933 my $ypos = $StartCommonUWires_ypos + $UWire_yint*($j);
936 if ( $ypos < $lastYpos ){ print "WARNING: y position dropped from $lastYpos (wire U$lastWnum) to $ypos (wire U$i)\n"; }
937 if ( $ypos == $lastYpos ){ print "WARNING: y position between wire U$lastWnum and U$lastWnum did not move: $ypos\n"; }
940 $pitch = ($ypos - $lastYpos) * $SinUAngle - ($zpos - $lastZpos) * $CosUAngle ;
944 <volumeref ref="volTPCWireUCommon${_[3]}"/>
945 <position name="pos${_[3]}WireU$i" unit="cm" x="0" y="@{[$ypos ]}" z="0"/>
946 <rotation name="rUAngle$i" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
950 $topY = $ypos + ($CosUAngle*$CommonUWireLength/2);
951 $bottomY = $ypos - ($CosUAngle*$CommonUWireLength/2);
952 $edgeZ_p = + ($SinUAngle*$CommonUWireLength/2);
953 $edgeZ_m = - ($SinUAngle*$CommonUWireLength/2);
954 print $wout "U$i: ( $ypos , 0 ) (pitch = $pitch)\n";
955 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
964 my $FirstTopUWire_zspan = $FirstTopUWire_yspan*$TanUAngle;
965 my $StartTopUWires_ypos = + $Uactive_y/2 - $FirstTopUWire_yspan/2;
966 my $StartTopUWires_zpos = - $Uactive_z/2 + $FirstTopUWire_zspan/2;
968 # Finally moving to the corner wires on the top right:
969 # x=0 to center the wires in the plane
970 # y positioning: plug wire number into same equation
971 # z positioning: start at z=0 and go negatively at the same z increment
972 # rotation: same as common wire in code above
973 # note that the counter maintains wire number shown in the position name
975 for ($j = $NumberSideUWires; $j < $NumberSideUWires+$NumberCornerUWires; ++$j)
978 $i = $j - $NumberSideUWires;
980 my $ypos = $StartTopUWires_ypos + ($i)*0.5*$UWire_yint;
981 my $zpos = $StartTopUWires_zpos - ($i)*0.5*$UWire_zint;
984 if ( $ypos < $lastYpos ){ print "WARNING: y position dropped from $lastYpos (wire U$lastWnum) to $ypos (wire U$j)\n"; }
985 if ( $ypos == $lastYpos ){ print "WARNING: y position between wire U$lastWnum and U$j did not move: $ypos\n"; }
987 $pitch = ($ypos - $lastYpos) * $SinUAngle - ($zpos - $lastZpos) * $CosUAngle ;
991 <volumeref ref="volTPCWireU$j${_[3]}"/>
992 <position name="pos${_[3]}WireU$j" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
993 <rotation name="rUAngle$j" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
997 $topY = $ypos + ($CosUAngle*$TopCornerUWireLength[$i]/2);
998 $bottomY = $ypos - ($CosUAngle*$TopCornerUWireLength[$i]/2);
999 $edgeZ_p = $zpos + ($SinUAngle*$TopCornerUWireLength[$i]/2);
1000 $edgeZ_m = $zpos - ($SinUAngle*$TopCornerUWireLength[$i]/2);
1001 print $wout "U$j: ( $ypos , $zpos ) (pitch = $pitch)\n";
1002 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1012 # ++++++++++++++++++++++ V Plane +++++++++++++++++++++++
1014 # End U plane and create V plane logical volume
1018 <volume name="volTPCPlaneV${_[3]}">
1019 <materialref ref="LAr"/>
1020 <solidref ref="${_[3]}VPlane"/>
1023 print $wout "\n- Wires for V plane -\n\n";
1024 print $wout " Vplane_y: $Vactive_y\n";
1025 print $wout " Vplane_z: $Vactive_z\n";
1031 # Starting with the bottom right corner wires:
1032 # x=0 to center the wires in the plane
1033 # y positioning: (-0.5*$TPCWirePlaneHeight) starts the incremental increase
1034 # from the bottom of the plane, and trigonometry gives the increment
1035 # z positioning: Looking at the plane from the positive x direction,
1036 # (-0.5*$TPCWirePlaneLength) starts the incremental increase from
1037 # the lower right corner.
1038 # rotation: same as common wire in code below
1040 $FirstV_ypos = - $Vactive_y/2 + $FirstVWireOffset/$TanVAngle/2;
1041 $FirstV_zpos = - $Vactive_z/2 + $FirstVWireOffset/2;
1043 for ($i = 0; $i < $NumberCornerVWires; ++$i)
1046 my $ypos = $FirstV_ypos + ($i)*0.5*$VWire_yint;
1047 my $zpos = $FirstV_zpos + ($i)*0.5*$VWire_zint;
1051 <volumeref ref="volTPCWireV$i${_[3]}"/>
1052 <position name="pos${_[3]}WireV$i" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
1053 <rotation name="rVAngle$i" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1057 $topY = $ypos + ($CosVAngle*$CornerVWireLength[$i]/2);
1058 $bottomY = $ypos - ($CosVAngle*$CornerVWireLength[$i]/2);
1059 $edgeZ_p = $zpos + ($SinVAngle*$CornerVWireLength[$i]/2);
1060 $edgeZ_m = $zpos - ($SinVAngle*$CornerVWireLength[$i]/2);
1061 print $wout "V$i: ( $ypos , $zpos ) \n";
1062 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1070 # Moving upwards to the common wires:
1071 # x and z are zero to center the wires along a vertical axis
1072 # y positioning: Plug wire number into the same corner ypos equation
1073 # rotation: wires in //// direction, so +90deg to bring them to vertical and
1074 # --VAngle counterclockwise to arrive at proper orientation
1075 # Note that the counter maintains wire number in the position name
1077 my $StartCommonVWires_ypos = $lastYpos + $VWire_yint - abs( $lastZpos )/$TanVAngle;
1079 for ($i = $NumberCornerVWires; $i < $NumberSideVWires; ++$i)
1082 $j = $i - $NumberCornerVWires;
1083 my $ypos = $StartCommonVWires_ypos + $VWire_yint*($j);
1087 <volumeref ref="volTPCWireVCommon${_[3]}"/>
1088 <position name="pos${_[3]}WireV$i" unit="cm" x="0" y="@{[$ypos ]}" z="0"/>
1089 <rotation name="rVAngle$i" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1093 $topY = $ypos + ($CosVAngle*$CommonVWireLength/2);
1094 $bottomY = $ypos - ($CosVAngle*$CommonVWireLength/2);
1095 $edgeZ_p = + ($SinVAngle*$CommonVWireLength/2);
1096 $edgeZ_m = - ($SinVAngle*$CommonVWireLength/2);
1097 print $wout "V$i: ( $ypos , 0 ) \n";
1098 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1101 #$lastZpos = $zpos; always 0
1106 my $FirstTopVWire_zspan = $FirstTopVWire_yspan*$TanVAngle;
1107 my $StartTopVWires_ypos = + $Vactive_y/2 - $FirstTopVWire_yspan/2;
1108 my $StartTopVWires_zpos = + $Vactive_z/2 - $FirstTopVWire_zspan/2;
1110 # Finally moving to the corner wires on the top right:
1111 # x=0 to center the wires in the plane
1112 # y positioning: plug wire number into same equation
1113 # z positioning: start at z=0 and go positively at the same z increment
1114 # rotation: same as common wire in code above
1115 # note that the counter maintains wire number shown in the position name
1117 for ($j = $NumberSideVWires; $j < $NumberSideVWires+$NumberCornerVWires; ++$j)
1120 $i = $j - $NumberSideVWires;
1122 my $ypos = $StartTopVWires_ypos + ($i)*0.5*$VWire_yint;
1123 my $zpos = $StartTopVWires_zpos + ($i)*0.5*$VWire_zint;
1127 <volumeref ref="volTPCWireV$j${_[3]}"/>
1128 <position name="pos${_[3]}WireV$j" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
1129 <rotation name="rVAngle$j" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1133 $topY = $ypos + ($CosVAngle*$TopCornerVWireLength[$i]/2);
1134 $bottomY = $ypos - ($CosVAngle*$TopCornerVWireLength[$i]/2);
1135 $edgeZ_p = $zpos + ($SinVAngle*$TopCornerVWireLength[$i]/2);
1136 $edgeZ_m = $zpos - ($SinVAngle*$TopCornerVWireLength[$i]/2);
1137 print $wout "V$j: ( $ypos , $zpos ) \n";
1138 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1151 # ++++++++++++++++++++++ Z Plane +++++++++++++++++++++++
1153 # End V plane and create Z plane logical volume
1157 <volume name="volTPCPlaneZ${_[3]}">
1158 <materialref ref="LAr"/>
1159 <solidref ref="${_[3]}ZPlane"/>
1165 # This is the simplest plane, one loop creates all of the wires
1166 # x and y position at zero to center the wires
1167 # z position: moving from front of detector to back, in the positive z direction,
1168 # starting at (-0.5*$TPCWirePlaneLength), the right side looking from
1171 for ($i=0; $i<$NumberVerticalWires; ++$i)
1173 my $zpos = (-0.5*$Zactive_z) + $i*$XWirePitch + $TPCWireThickness/2;
1177 <volumeref ref="volTPCWireVert${_[3]}"/>
1178 <position name="pos${_[3]}WireZ$i" unit="cm" x="0" y="0 " z="@{[$zpos]}"/>
1179 <rotationref ref="rPlus90AboutX"/>
1191 #+++++++++++++++++++++ ^^ Position physical wires Above ^^ +++++++++++++++++++++
1193 ## make the TPC active volume extend down to the G10 for the grid
1195 my $BottomOfAPA = - $TPC_y/2 + $APAGap_y/2;
1198 $posZplane[0] = -$_[0]/2 + $APAWirePlaneSpacing - $TPCWirePlaneThickness/2;
1199 $posZplane[1] = $BottomOfAPA + $WrapCover + 4*$G10thickness + $Zactive_y/2;
1202 $posVplane[0] = $posZplane[0] + $APAWirePlaneSpacing;
1203 $posVplane[1] = $BottomOfAPA + $WrapCover + 3*$G10thickness + $Vactive_y/2;
1204 $posVplane[2] = $posZplane[2];
1206 $posUplane[0] = $posVplane[0] + $APAWirePlaneSpacing;
1207 $posUplane[1] = $BottomOfAPA + $WrapCover + 2*$G10thickness + $Uactive_y/2;
1208 $posUplane[2] = $posZplane[2];
1210 $posTPCActive[0] = $posUplane[0] + ($TPCWirePlaneThickness/2 + $TPCActive_x/2);
1211 $posTPCActive[1] = -$_[1]/2 + $TPCActive_y/2;
1212 $posTPCActive[2] = 0;
1214 #wrap up the TPC file
1216 <volume name="volTPC${_[3]}">
1217 <materialref ref="LAr"/>
1218 <solidref ref="${_[3]}"/>
1220 <volumeref ref="volTPCPlaneZ${_[3]}"/>
1221 <position name="pos${_[3]}PlaneZ" unit="cm"
1222 x="@{[$posZplane[0]]}" y="@{[$posZplane[1]]}" z="@{[$posZplane[2]]}"/>
1223 <rotationref ref="rIdentity"/>
1226 <volumeref ref="volTPCPlaneV${_[3]}"/>
1227 <position name="pos${_[3]}PlaneV" unit="cm"
1228 x="@{[$posVplane[0]]}" y="@{[$posVplane[1]]}" z="@{[$posVplane[2]]}"/>
1229 <rotationref ref="rIdentity"/>
1232 <volumeref ref="volTPCPlaneU${_[3]}"/>
1233 <position name="pos${_[3]}PlaneU" unit="cm"
1234 x="@{[$posUplane[0]]}" y="@{[$posUplane[1]]}" z="@{[$posUplane[2]]}"/>
1235 <rotationref ref="rIdentity"/>
1239 # Option to omit the active volume on the outside for the prototype.
1240 if( !($killOuterActive==1 && $_[3] eq 'Outer') ){
1243 <volumeref ref="volTPCActive${_[3]}"/>
1244 <position name="pos${_[3]}Active" unit="cm"
1245 x="@{[$posTPCActive[0]]}" y="@{[$posTPCActive[1]]}" z="@{[$posTPCActive[2]]}"/>
1246 <rotationref ref="rIdentity"/>
1259 } #end of sub gen_TPC
1263 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1264 #++++++++++++++++++++++++++++++++++++++ gen_Cryostat +++++++++++++++++++++++++++++++++++++
1265 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1270 # Create the cryostat fragment file name,
1271 # add file to list of output GDML fragments,
1273 $CRYO = "dune10kt_v2_Cryostat" . $suffix . ".gdml";
1274 push (@gdmlFiles, $CRYO);
1275 $CRYO = ">" . $CRYO;
1276 open(CRYO) or die("Could not open file $CRYO for writing");
1279 # The standard XML prefix and starting the gdml
1281 <?xml version='1.0'?>
1285 $APAFrameZSide_x = $APAFrame_x;
1286 $APAFrameZSide_y = 4*$inch;
1287 $APAFrameZSide_z = $APAFrame_z;
1289 $APAFrameYSide_x = $APAFrame_x;
1290 $APAFrameYSide_y = $APAFrame_y-2*$APAFrameZSide_y;
1291 $APAFrameYSide_z = 4*$inch;
1293 # Two outer Y supports will sandwich the light paddles
1294 $APAFrameYOuterSupport_x = ($APAFrame_x-$LightPaddle_x)/2;
1295 $APAFrameYOuterSupport_y = $APAFrame_y-2*$APAFrameZSide_y;
1296 $APAFrameYOuterSupport_z = 4*$inch;
1298 $EdgeFrameSteelThickness = 0.12*$inch;
1299 $InnerFrameSteelThickness = 0.062*$inch;
1302 $G10BoardYSide_x = $APAFrame_x;
1303 $G10BoardYSide_y = $APAFrame_y;
1304 $G10BoardYSide_z = $G10thickness;
1306 $G10BoardZSide_x = $APAFrame_x;
1307 $G10BoardZSide_y = $G10thickness;
1308 $G10BoardZSide_z = $APAFrame_z;
1310 ##################################################################
1311 ################### Field Cage Y and Z centers ###################
1316 for($k=0 ; $k<$nAPALong ; $k++) #TODO!!! Factor out these loops so that the calculation of each APA center for placing APAs (happens later) will always agree with placing the center of the Field Cage.
1318 $tmp_APACenter_z = - $Argon_z/2
1319 + $UpstreamLArPadding
1321 + $k*($APAphys_z+$APAGap_z);
1322 $FC_z_center = $FC_z_center + $tmp_APACenter_z;
1324 $FC_z_center = $FC_z_center / $nAPALong;
1326 for($j=0 ; $j<$nAPAHigh ; $j++) # nAPAHigh always going to be 2
1328 $tmp_APACenter_y = - $Argon_y/2 + $SpaceAPAToFloor
1330 + $j*($APAphys_y+$APAGap_y);
1331 $FC_y_center = $FC_y_center + $tmp_APACenter_y;
1333 $FC_y_center = $FC_y_center / $nAPAHigh;
1335 # All the cryostat solids.
1338 <box name="Cryostat" lunit="cm"
1339 x="@{[$Cryostat_x]}"
1340 y="@{[$Cryostat_y]}"
1341 z="@{[$Cryostat_z]}"/>
1342 <box name="ArgonInterior" lunit="cm"
1346 <box name="FieldCageOut" lunit="cm"
1350 <box name="FieldCageIn" lunit="cm"
1354 <subtraction name="FieldCage">
1355 <first ref="FieldCageOut"/>
1356 <second ref="FieldCageIn"/>
1358 <box name="GaseousArgon" lunit="cm"
1360 y="@{[$HeightGaseousAr]}"
1362 <subtraction name="SteelShell">
1363 <first ref="Cryostat"/>
1364 <second ref="ArgonInterior"/>
1366 <box name="Cathode" lunit="cm"
1369 z="@{[$Cathode_z]}"/>
1371 <box name="LightPaddle" lunit="cm"
1372 x="@{[$LightPaddle_x]}"
1373 y="@{[$LightPaddle_y]}"
1374 z="@{[$LightPaddle_z + $SiPM_z]}"/>
1376 <box name="APAFrameYSideHollow" lunit="cm"
1377 x="@{[$APAFrameYSide_x-2*$EdgeFrameSteelThickness]}"
1378 y="@{[$APAFrameYSide_y-2*$EdgeFrameSteelThickness]}"
1379 z="@{[$APAFrameYSide_z]}"/>
1380 <box name="APAFrameYSideShell" lunit="cm"
1381 x="@{[$APAFrameYSide_x]}"
1382 y="@{[$APAFrameYSide_y]}"
1383 z="@{[$APAFrameYSide_z]}"/>
1384 <subtraction name="APAFrameYSide">
1385 <first ref="APAFrameYSideShell"/>
1386 <second ref="APAFrameYSideHollow"/>
1387 <positionref ref="posCenter"/>
1388 <rotationref ref="rIdentity"/>
1391 <box name="APAFrameZSideHollow" lunit="cm"
1392 x="@{[$APAFrameZSide_x-2*$EdgeFrameSteelThickness]}"
1393 y="@{[$APAFrameZSide_y-2*$EdgeFrameSteelThickness]}"
1394 z="@{[$APAFrameZSide_z]}"/>
1395 <box name="APAFrameZSideShell" lunit="cm"
1396 x="@{[$APAFrameZSide_x]}"
1397 y="@{[$APAFrameZSide_y]}"
1398 z="@{[$APAFrameZSide_z]}"/>
1399 <subtraction name="APAFrameZSide">
1400 <first ref="APAFrameZSideShell"/>
1401 <second ref="APAFrameZSideHollow"/>
1402 <positionref ref="posCenter"/>
1403 <rotationref ref="rIdentity"/>
1406 <box name="APAFrameYOuterSupport" lunit="cm"
1407 x="@{[$EdgeFrameSteelThickness]}"
1408 y="@{[$APAFrameYOuterSupport_y]}"
1409 z="@{[$APAFrameYOuterSupport_z]}"/>
1412 <box name="G10BoardYSideCenterSeg" lunit="cm"
1413 x="@{[$G10BoardYSide_x]}"
1414 y="@{[$G10BoardYSide_y]}"
1415 z="@{[$G10BoardYSide_z]}"/>
1417 <box name="G10BoardZSideCenterSeg" lunit="cm"
1418 x="@{[$G10BoardZSide_x]}"
1419 y="@{[$G10BoardZSide_y]}"
1420 z="@{[$G10BoardZSide_z]}"/>
1425 # Cryostat structure
1428 <volume name="volSteelShell">
1429 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1430 <solidref ref="SteelShell" />
1432 <volume name="volFieldCage">
1433 <materialref ref="ALUMINUM_Al"/>
1434 <solidref ref="FieldCage"/>
1436 <volume name="volGaseousArgon">
1437 <materialref ref="ArGas"/>
1438 <solidref ref="GaseousArgon"/>
1440 <volume name="volCathode">
1441 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1442 <solidref ref="Cathode" />
1446 for($i=0 ; $i<$nAPAs ; $i++){
1447 for($p=0 ; $p<10 ; $p++){
1449 <volume name="volOpDetSensitive_$i\-$p">
1450 <materialref ref="Acrylic"/>
1451 <solidref ref="LightPaddle"/>
1460 <volume name="volAPAFrameYSide">
1461 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1462 <solidref ref="APAFrameYSide"/>
1465 <volume name="volAPAFrameZSide">
1466 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1467 <solidref ref="APAFrameZSide"/>
1470 <volume name="volAPAFrameYOuterSupport">
1471 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1472 <solidref ref="APAFrameYOuterSupport"/>
1475 <volume name="volG10BoardYSideCenterSeg">
1476 <materialref ref="G10"/>
1477 <solidref ref="G10BoardYSideCenterSeg"/>
1480 <volume name="volG10BoardZSideCenterSeg">
1481 <materialref ref="G10"/>
1482 <solidref ref="G10BoardZSideCenterSeg"/>
1485 <volume name="volCryostat">
1486 <materialref ref="LAr" />
1487 <solidref ref="Cryostat" />
1489 <volumeref ref="volGaseousArgon"/>
1490 <position name="posGaseousArgon" unit="cm" x="0" y="@{[$Argon_y/2-$HeightGaseousAr/2]}" z="0"/>
1493 <volumeref ref="volFieldCage"/>
1494 <position name="posFieldCage" unit="cm"
1496 y="@{[$FC_y_center]}"
1497 z="@{[$FC_z_center]}"/>
1500 <volumeref ref="volSteelShell"/>
1501 <position name="posSteelShell" unit="cm" x="0" y="0" z="0"/>
1505 # nested for loops to place the non-rotated AND rotated volTPC
1506 # x loop rotation: There are six drift volumes. Looking into the
1507 # detector from incident direction, and counting from right (-x) to
1508 # left (+x), odd number volumes need to be rotated 180deg about Y in
1509 # order for the cathode to be on the right of the APA.
1516 for($k=0 ; $k<$nAPALong ; $k++)
1518 $APACenter_z = - $Argon_z/2
1519 + $UpstreamLArPadding
1521 + $k*($APAphys_z+$APAGap_z);
1524 for($j=0 ; $j<$nAPAHigh ; $j++) # nAPAHigh always going to be 2
1525 { # $j=0 for bottom APAs
1527 $APACenter_y = - $Argon_y/2 + $SpaceAPAToFloor
1529 + $j*($APAphys_y+$APAGap_y);
1532 if( $workspace == 0 )
1535 for($i=0 ; $i<$nAPAWide ; $i++)
1539 $APACenter_x = - $Argon_x/2
1540 + $SpaceAPAToCryoWall + $APA_UtoU_x/2 + $TPCWirePlaneThickness/2
1543 $CPA_x = $APACenter_x + $CPAToAPA;
1546 place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, $j);
1547 place_OpDets($APACenter_x, $APACenter_y, $APACenter_z, $apa_i);
1548 $tpc_0 = 2*$apa_i+0;
1549 $tpc_1 = 2*$apa_i+1;
1552 $SelectTPC_0 = "Inner";
1553 $SelectTPC_1 = "Inner";
1554 $TPC_0_x = $TPCInner_x;
1555 $TPC_1_x = $TPCInner_x;
1556 $rot_0 = "rPlus180AboutY";
1557 $rot_1 = "rIdentity";
1558 if($i == 0) { $SelectTPC_0 = "Outer"; $TPC_0_x = $TPCOuter_x; }
1559 if($i == $nAPAWide-1) { $SelectTPC_1 = "Outer"; $TPC_1_x = $TPCOuter_x; }
1560 if($j == 0) { $rot_0 = "rPlus180AboutXPlus180AboutY";
1561 $rot_1 = "rPlus180AboutX"; } #put the readout end at the bottom for bottom APAs
1568 <volumeref ref="volTPC$SelectTPC_0"/>
1569 <position name="posTPC\-$tpc_0" unit="cm"
1570 x="@{[$APACenter_x - $APAFrame_x/2 - $TPC_0_x/2]}"
1571 y="@{[$APACenter_y]}"
1572 z="@{[$APACenter_z]}"/>
1573 <rotationref ref="$rot_0"/>
1576 <volumeref ref="volTPC$SelectTPC_1"/>
1577 <position name="posTPC\-$tpc_1" unit="cm"
1578 x="@{[$APACenter_x + $APAFrame_x/2 + $TPC_1_x/2]}"
1579 y="@{[$APACenter_y]}"
1580 z="@{[$APACenter_z]}"/>
1581 <rotationref ref="$rot_1"/>
1587 if( $i < $nAPAWide - 1 ){ # avoid placeing the last row of CPAs since the APAs are on the outside
1592 <volumeref ref="volCathode"/>
1593 <position name="posCathode\-$cpa_i" unit="cm"
1595 y="@{[$APACenter_y]}"
1596 z="@{[$APACenter_z]}"/>
1597 <rotationref ref="rIdentity"/>
1607 } # end if not the smaller workspace
1610 # Make the workspace have only one center APA with CPAs and the full drift on either side
1611 elsif( $workspace == 1 || $workspace==2 ){
1614 $CPA_0_x = $APACenter_x - $CPAToAPA;
1615 $CPA_1_x = $APACenter_x + $CPAToAPA;
1618 place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, $j);
1619 place_OpDets($APACenter_x, $APACenter_y, $APACenter_z, $apa_i);
1621 $tpc_0 = 2*$apa_i+0;
1622 $tpc_1 = 2*$apa_i+1;
1625 $rot_0 = "rPlus180AboutY";
1626 $rot_1 = "rIdentity";
1627 if($j == 0) { $rot_0 = "rPlus180AboutXPlus180AboutY";
1628 $rot_1 = "rPlus180AboutX"; } #put the readout end at the bottom for bottom APAs
1633 <volumeref ref="volTPCInner"/>
1634 <position name="posTPC\-$tpc_0" unit="cm"
1635 x="@{[$APACenter_x - $APAFrame_x/2 - $TPCInner_x/2]}"
1636 y="@{[$APACenter_y]}"
1637 z="@{[$APACenter_z]}"/>
1638 <rotationref ref="$rot_0"/>
1641 <volumeref ref="volTPCInner"/>
1642 <position name="posTPC\-$tpc_1" unit="cm"
1643 x="@{[$APACenter_x + $APAFrame_x/2 + $TPCInner_x/2]}"
1644 y="@{[$APACenter_y]}"
1645 z="@{[$APACenter_z]}"/>
1646 <rotationref ref="$rot_1"/>
1650 <volumeref ref="volCathode"/>
1651 <position name="posCathode\-$apa_i-0" unit="cm"
1653 y="@{[$APACenter_y]}"
1654 z="@{[$APACenter_z]}"/>
1655 <rotationref ref="rIdentity"/>
1658 <volumeref ref="volCathode"/>
1659 <position name="posCathode\-$apa_i-1" unit="cm"
1661 y="@{[$APACenter_y]}"
1662 z="@{[$APACenter_z]}"/>
1663 <rotationref ref="rIdentity"/>
1668 } # if the smaller workspace
1687 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1688 #++++++++++++++++++++++++++++++++++++ place_OpDets +++++++++++++++++++++++++++++++++++++++
1689 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1694 $APACenter_x = $_[0];
1695 $APACenter_y = $_[1];
1696 $APACenter_z = $_[2];
1699 for ($paddle = 0; $paddle<$nLightPaddlesPerAPA; $paddle++)
1702 # All Light Paddle centers will have the same
1703 # X coordinate as the center of the current APA
1704 # Z coordinate as the current TPC pair
1705 # The Y coordinate must be looped over:
1707 #the multiplication by j here is a temporary dirty trick to get around some strange behavior
1709 $Paddle_Y = $APACenter_y
1711 + $j*$FrameToPaddleSpace
1712 + (1-$j)*($LightPaddle_y/2 + $APAFrameZSide_y)
1713 + $PaddleYInterval*$paddle;
1715 # Alternate the paddle orientations
1716 if ( $paddle % 2 == 0 ) { $rot = "rIdentity"; }
1717 else { $rot = "rPlus180AboutY"; }
1722 <volumeref ref="volOpDetSensitive_$apa_i\-$paddle"/>
1723 <position name="posPaddle\-$paddle\-TPC\-$i\-$j\-$k" unit="cm"
1724 x="@{[$APACenter_x]}"
1726 z="@{[$APACenter_z + $SiPM_z/2]}"/>
1727 <rotationref ref="$rot"/>
1731 }#end Paddle for-loop
1737 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1738 #++++++++++++++++++++++++++++++++++++++ place_APA ++++++++++++++++++++++++++++++++++++++++
1739 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1742 # Must be called only within gen_Cryostat(),
1745 # $_[0] = x APA physical center
1746 # $_[1] = y APA physical center
1747 # $_[2] = z APA physical center
1748 # $_[3] = APA number
1749 # $_[4] = 0 for APA with readout on bottom
1750 # 1 for APA with readout on top
1757 ####################################################################
1758 ################# APA Frame and Paddle Dimensions ##################
1760 # The center passed to this function is the physical APA center,
1761 # which is not quite the frame's center, since there are more boards
1762 # at the bottom. Transform them:
1764 $APAFrameCenter_x = $_[0];
1765 $APAFrameCenter_z = $_[2];
1767 # The bottom APAs are upside down relative to how the TPC is initially generated,
1768 # and the center needs to be slightly shifted since there is extra G10 on the
1769 # end that doesn't read out.
1771 if($_[4]==1) # top APAs
1773 $APAFrameCenter_y = $_[1] - $APAphys_y/2
1774 + $WrapCover + 4*$G10thickness
1777 elsif($_[4]==0) # bottom APAs
1779 $APAFrameCenter_y = $_[1] + $APAphys_y/2
1780 - $WrapCover - 4*$G10thickness
1783 else{ print "APA not labeled as top or bottom"; }
1785 $APAFrameZSide_x = $APAFrame_x;
1786 $APAFrameZSide_y = 4*$inch;
1787 $APAFrameZSide_z = $APAFrame_z;
1789 $APAFrameYSide_x = $APAFrame_x;
1790 $APAFrameYSide_y = $APAFrame_y-2*$APAFrameZSide_y;
1791 $APAFrameYSide_z = 4*$inch;
1793 # Two outer Y supports will sandwich the light paddles
1794 $APAFrameYOuterSupport_x = ($APAFrame_x-$LightPaddle_x)/2;
1795 $APAFrameYOuterSupport_y = $APAFrame_y-2*$APAFrameZSide_y;
1796 $APAFrameYOuterSupport_z = 4*$inch;
1798 # if there were an inner support to fill the hole
1799 $APAFrameYInnerSupport_x = $LightPaddle_x;
1801 $EdgeFrameSteelThickness = 0.12*$inch;
1802 $InnerFrameSteelThickness = 0.062*$inch;
1805 $G10BoardYSide_x = $APAFrame_x;
1806 $G10BoardYSide_y = $APAFrame_y;
1807 $G10BoardYSide_z = $G10thickness;
1809 $G10BoardZSide_x = $APAFrame_x;
1810 $G10BoardZSide_y = $G10thickness;
1811 $G10BoardZSide_z = $APAFrame_z;
1813 if($_[4]==1) # top APAs
1815 $posG10ZSideZ_y = $APAFrameCenter_y - $APAFrame_y/2 - (0+.5)*($G10BoardZSide_y);
1816 $posG10ZSideV_y = $APAFrameCenter_y - $APAFrame_y/2 - (1+.5)*($G10BoardZSide_y);
1817 $posG10ZSideU_y = $APAFrameCenter_y - $APAFrame_y/2 - (2+.5)*($G10BoardZSide_y);
1818 $posG10ZSideGrid_y = $APAFrameCenter_y - $APAFrame_y/2 - (3+.5)*($G10BoardZSide_y);
1820 elsif($_[4]==0) # bottom APAs
1822 $posG10ZSideZ_y = $APAFrameCenter_y + $APAFrame_y/2 + (0+.5)*($G10BoardZSide_y);
1823 $posG10ZSideV_y = $APAFrameCenter_y + $APAFrame_y/2 + (1+.5)*($G10BoardZSide_y);
1824 $posG10ZSideU_y = $APAFrameCenter_y + $APAFrame_y/2 + (2+.5)*($G10BoardZSide_y);
1825 $posG10ZSideGrid_y = $APAFrameCenter_y + $APAFrame_y/2 + (3+.5)*($G10BoardZSide_y);
1827 else{ print "APA not labeled as top or bottom"; }
1829 # First put in the frame
1833 # <volumeref ref="volAPAFrameYOuterSupport\-$APA_i"/>
1834 # <position name="posAPAFrameYOuterSupportNeg\-$APA_i" unit="cm"
1835 # x="$APAFrameCenter_x - ($APAFrameYOuterSupport_x + $APAFrameYInnerSupport_x/2 - $EdgeFrameSteelThickness/2)"
1836 # y="$APAFrameCenter_y"
1837 # z="$APAFrameCenter_z"/>
1838 # <rotationref ref="rIdentity"/>
1841 # <volumeref ref="volAPAFrameYOuterSupport\-$APA_i"/>
1842 # <position name="posAPAFrameYOuterSupportPos\-$APA_i" unit="cm"
1843 # x="$APAFrameCenter_x + ($APAFrameYOuterSupport_x + $APAFrameYInnerSupport_x/2 - $EdgeFrameSteelThickness/2)"
1844 # y="$APAFrameCenter_y"
1845 # z="$APAFrameCenter_z"/>
1846 # <rotationref ref="rIdentity"/>
1852 <volumeref ref="volAPAFrameYSide"/>
1853 <position name="posAPAFrameYSideNeg\-$APA_i" unit="cm"
1854 x="@{[$APAFrameCenter_x]}"
1855 y="@{[$APAFrameCenter_y]}"
1856 z="@{[$APAFrameCenter_z - $APAFrame_z/2 + $APAFrameYSide_z/2]}"/>
1857 <rotationref ref="rIdentity"/>
1860 <volumeref ref="volAPAFrameYSide"/>
1861 <position name="posAPAFrameYSidePos\-$APA_i" unit="cm"
1862 x="@{[$APAFrameCenter_x]}"
1863 y="@{[$APAFrameCenter_y]}"
1864 z="@{[$APAFrameCenter_z + $APAFrame_z/2 - $APAFrameYSide_z/2]}"/>
1865 <rotationref ref="rIdentity"/>
1868 <volumeref ref="volAPAFrameZSide"/>
1869 <position name="posAPAFrameZSidePos\-$APA_i" unit="cm"
1870 x="@{[$APAFrameCenter_x]}"
1871 y="@{[$APAFrameCenter_y + $APAFrame_y/2 - $APAFrameZSide_y/2]}"
1872 z="@{[$APAFrameCenter_z]}"/>
1873 <rotationref ref="rIdentity"/>
1876 <volumeref ref="volAPAFrameZSide"/>
1877 <position name="posAPAFrameZSideNeg\-$APA_i" unit="cm"
1878 x="@{[$APAFrameCenter_x]}"
1879 y="@{[$APAFrameCenter_y - $APAFrame_y/2 + $APAFrameZSide_y/2]}"
1880 z="@{[$APAFrameCenter_z]}"/>
1881 <rotationref ref="rIdentity"/>
1885 <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1886 - Add the *parts* of the G10 boards that exist directly in volCryostat.
1887 - There are two boards on each the up and downstream end,
1888 one each to wrap the U and V views around the APA frame
1889 - There are 4 on the bottom which anchor the U V and Z wires and the grid plane
1890 - The rest of the parts of the G10 boards must be placed directly in volTPC -->
1893 <volumeref ref="volG10BoardYSideCenterSeg"/>
1894 <position name="posG10BoardYSideCenterSeg\-Vup\-$APA_i" unit="cm"
1895 x="@{[$APAFrameCenter_x]}"
1896 y="@{[$APAFrameCenter_y]}"
1897 z="@{[$APAFrameCenter_z - $APAFrame_z/2 - (0+.5)*($G10BoardYSide_z)]}"/>
1898 <rotationref ref="rIdentity"/>
1901 <volumeref ref="volG10BoardYSideCenterSeg"/>
1902 <position name="posG10BoardYSideCenterSeg\-Uup\-$APA_i" unit="cm"
1903 x="@{[$APAFrameCenter_x]}"
1904 y="@{[$APAFrameCenter_y]}"
1905 z="@{[$APAFrameCenter_z - $APAFrame_z/2 - (1+.5)*($G10BoardYSide_z)]}"/>
1906 <rotationref ref="rIdentity"/>
1910 <volumeref ref="volG10BoardYSideCenterSeg"/>
1911 <position name="posG10BoardYSideCenterSeg\-Vdown\-$APA_i" unit="cm"
1912 x="@{[$APAFrameCenter_x]}"
1913 y="@{[$APAFrameCenter_y]}"
1914 z="@{[$APAFrameCenter_z + $APAFrame_z/2 + (0+.5)*($G10BoardYSide_z)]}"/>
1915 <rotationref ref="rIdentity"/>
1918 <volumeref ref="volG10BoardYSideCenterSeg"/>
1919 <position name="posG10BoardYSideCenterSeg\-Udown\-$APA_i" unit="cm"
1920 x="@{[$APAFrameCenter_x]}"
1921 y="@{[$APAFrameCenter_y]}"
1922 z="@{[$APAFrameCenter_z + $APAFrame_z/2 + (1+.5)*($G10BoardYSide_z)]}"/>
1923 <rotationref ref="rIdentity"/>
1927 <volumeref ref="volG10BoardZSideCenterSeg"/>
1928 <position name="posG10BoardZSideCenterSeg\-Z\-$APA_i" unit="cm"
1929 x="@{[$APAFrameCenter_x]}"
1930 y="@{[$posG10ZSideZ_y]}"
1931 z="@{[$APAFrameCenter_z]}"/>
1932 <rotationref ref="rIdentity"/>
1935 <volumeref ref="volG10BoardZSideCenterSeg"/>
1936 <position name="posG10BoardZSideCenterSeg\-V\-$APA_i" unit="cm"
1937 x="@{[$APAFrameCenter_x]}"
1938 y="@{[$posG10ZSideV_y]}"
1939 z="@{[$APAFrameCenter_z]}"/>
1940 <rotationref ref="rIdentity"/>
1943 <volumeref ref="volG10BoardZSideCenterSeg"/>
1944 <position name="posG10BoardZSideCenterSeg\-U\-$APA_i" unit="cm"
1945 x="@{[$APAFrameCenter_x]}"
1946 y="@{[$posG10ZSideU_y]}"
1947 z="@{[$APAFrameCenter_z]}"/>
1948 <rotationref ref="rIdentity"/>
1951 <volumeref ref="volG10BoardZSideCenterSeg"/>
1952 <position name="posG10BoardZSideCenterSeg\-Grid\-$APA_i" unit="cm"
1953 x="@{[$APAFrameCenter_x]}"
1954 y="@{[$posG10ZSideGrid_y]}"
1955 z="@{[$APAFrameCenter_z]}"/>
1956 <rotationref ref="rIdentity"/>
1967 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1968 #+++++++++++++++++++++++++++++++++++++ gen_Enclosure +++++++++++++++++++++++++++++++++++++
1969 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1974 # Create the detector enclosure fragment file name,
1975 # add file to list of output GDML fragments,
1977 $ENCL = "dune10kt_v2_DetEnclosure" . $suffix . ".gdml";
1978 push (@gdmlFiles, $ENCL);
1979 $ENCL = ">" . $ENCL;
1980 open(ENCL) or die("Could not open file $ENCL for writing");
1983 # The standard XML prefix and starting the gdml
1985 <?xml version='1.0'?>
1990 # All the detector enclosure solids.
1994 <box name="FoamPadBlock" lunit="cm"
1995 x="@{[$Cryostat_x + 2*$FoamPadding]}"
1996 y="@{[$Cryostat_y + 2*$FoamPadding]}"
1997 z="@{[$Cryostat_z + 2*$FoamPadding]}" />
1999 <box name="FoamPadInner" lunit="cm"
2000 x="@{[$Cryostat_x + 0.01]}"
2001 y="@{[$Cryostat_y + 0.01]}"
2002 z="@{[$Cryostat_z + 0.01]}" />
2004 <subtraction name="FoamPadding">
2005 <first ref="FoamPadBlock"/>
2006 <second ref="FoamPadInner"/>
2007 <positionref ref="posCenter"/>
2010 <box name="SteelSupportBlock" lunit="cm"
2011 x="@{[$Cryostat_x + 2*$FoamPadding + 2*$SteelSupport_x]}"
2012 y="@{[$Cryostat_y + 2*$FoamPadding + 2*$SteelSupport_y]}"
2013 z="@{[$Cryostat_z + 2*$FoamPadding + 2*$SteelSupport_z]}" />
2015 <box name="SteelSupportInner" lunit="cm"
2016 x="@{[$Cryostat_x + 2*$FoamPadding + 0.01]}"
2017 y="@{[$Cryostat_y + 2*$FoamPadding + 0.01]}"
2018 z="@{[$Cryostat_z + 2*$FoamPadding + 0.01]}" />
2020 <subtraction name="SteelSupport">
2021 <first ref="SteelSupportBlock"/>
2022 <second ref="SteelSupportInner"/>
2023 <positionref ref="posCenter"/>
2026 <box name="DetEnclosure" lunit="cm"
2027 x="@{[$DetEncWidth]}"
2028 y="@{[$DetEncHeight]}"
2029 z="@{[$DetEncLength]}"/>
2036 # Detector enclosure structure
2039 <volume name="volFoamPadding">
2040 <materialref ref="FD_foam"/>
2041 <solidref ref="FoamPadding"/>
2044 <volume name="volSteelSupport">
2045 <materialref ref="AirSteelMixture"/>
2046 <solidref ref="SteelSupport"/>
2049 <volume name="volDetEnclosure">
2050 <materialref ref="Air"/>
2051 <solidref ref="DetEnclosure"/>
2054 <volumeref ref="volFoamPadding"/>
2055 <positionref ref="posCryoInDetEnc"/>
2058 <volumeref ref="volSteelSupport"/>
2059 <positionref ref="posCryoInDetEnc"/>
2062 <volumeref ref="volCryostat"/>
2063 <positionref ref="posCryoInDetEnc"/>
2082 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2083 #+++++++++++++++++++++++++++++++++++++++ gen_World +++++++++++++++++++++++++++++++++++++++
2084 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2089 # Create the WORLD fragment file name,
2090 # add file to list of output GDML fragments,
2092 $WORLD = "dune10kt_v2_World" . $suffix . ".gdml";
2093 push (@gdmlFiles, $WORLD);
2094 $WORLD = ">" . $WORLD;
2095 open(WORLD) or die("Could not open file $WORLD for writing");
2098 # The standard XML prefix and starting the gdml
2100 <?xml version='1.0'?>
2105 # All the World solids.
2108 <box name="World" lunit="cm"
2109 x="@{[$DetEncWidth+2*$RockThickness]}"
2110 y="@{[$DetEncHeight+2*$RockThickness]}"
2111 z="@{[$DetEncLength+2*$RockThickness]}"/>
2118 <volume name="volWorld" >
2119 <materialref ref="DUSEL_Rock"/>
2120 <solidref ref="World"/>
2123 <volumeref ref="volDetEnclosure"/>
2124 <position name="posDetEnclosure" unit="cm" x="@{[$OriginXSet]}" y="@{[$OriginYSet]}" z="@{[$OriginZSet]}"/>
2132 # make_gdml.pl will take care of <setup/>
2139 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2140 #++++++++++++++++++++++++++++++++++++ write_fragments ++++++++++++++++++++++++++++++++++++
2141 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2143 sub write_fragments()
2145 # This subroutine creates an XML file that summarizes the the subfiles output
2146 # by the other sub routines - it is the input file for make_gdml.pl which will
2147 # give the final desired GDML file. Specify its name with the output option.
2148 # (you can change the name when running make_gdml)
2150 # This code is taken straigh from the similar MicroBooNE generate script, Thank you.
2152 if ( ! defined $output )
2154 $output = "-"; # write to STDOUT
2157 # Set up the output file.
2158 $OUTPUT = ">" . $output;
2159 open(OUTPUT) or die("Could not open file $OUTPUT");
2162 <?xml version='1.0'?>
2164 <!-- Input to Geometry/gdml/make_gdml.pl; define the GDML fragments
2165 that will be zipped together to create a detector description.
2172 <!-- These files contain GDML <constant></constant>
2173 blocks. They are read in separately, so they can be
2174 interpreted into the remaining GDML. See make_gdml.pl for
2180 foreach $filename (@defFiles)
2183 <filename> $filename </filename>
2193 <!-- The GDML file fragments to be zipped together. -->
2197 foreach $filename (@gdmlFiles)
2200 <filename> $filename </filename>
2216 # run the sub routines that generate the fragments
2218 gen_Define(); # generates definitions at beginning of GDML
2219 gen_Materials(); # generates materials to be used
2222 gen_TPC( $TPCInner_x, $TPC_y, $TPC_z, 'Inner');
2223 gen_TPC( $TPCOuter_x, $TPC_y, $TPC_z, 'Outer');
2227 gen_Cryostat(); # places (2*nAPAWide x nAPAHigh x nAPALong) volTPC,
2228 # half rotated 180 about Y
2229 gen_Enclosure(); # places two cryostats and concrete volumes
2231 gen_World(); # places the enclosure among DUSEL Rock
2234 write_fragments(); # writes the XML input for make_gdml.pl
2235 # which zips together the final GDML