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.
15 #use lib "gdmlMaterials";
18 #use gdmlMaterials::gen_Materials;
22 Math::BigFloat->precision(-16);
24 open(my $wout, '>', 'gdmlWireCenters.txt');
26 GetOptions( "help|h" => \$help,
27 "suffix|s:s" => \$suffix,
28 "output|o:s" => \$output,
29 "wires|w:s" => \$wires,
30 "protoDune|p:s" => \$protoDune,
31 "workspace|k:s" => \$workspace);
35 # If the user requested help, print the usage notes and exit.
40 if ( ! defined $suffix )
42 # The user didn't supply a suffix, so append nothing to the file
48 # Otherwise, stick a "-" before the suffix, so that a suffix of
49 # "test" applied to filename.gdml becomes "filename-test.gdml".
50 $suffix = "-" . $suffix;
53 if ( ! defined $workspace )
56 if ( ! defined $protoDune )
59 print "\t\tCreating full geometry.\n";
61 elsif ( $protoDune == 1 )
63 print "\t\tCreating rough version of protoDUNE.\n";
66 elsif ( $workspace == 1)
68 print "\t\tCreating smaller (1x2x2-APA) workspace geometry.\n";
70 elsif ( $workspace == 2)
72 print "\t\tCreating 1x2x6-APA geometry.\n";
75 # set wires on to be the default, unless given an input by the user
76 $wires_on = 1; # 1=on, 0=off
86 # options for different parameters
92 #++++++++++++++++++++++++ Begin defining variables +++++++++++++++++++++++++
94 ## The GDML is build from the inside out to avoid overlaps, but that means
95 ## that the larger dimensions (such as the cryostat dimensions) are calculated
96 ## to be slightly different than the parameters calculated and reported by
97 ## engineers. All of this error is within reason and for the better, since
98 ## we don't want this Geometry to be overly complex or long.
103 ##################################################################
104 ##################### Wire Plane Parameters ######################
107 $UWirePitch = 0.4667;
108 $VWirePitch = 0.4667;
112 $nZChannelsPerAPA = 960;
114 # dune10kt 3mm version
115 if($Pitch3mmVersion==1){
119 $nZChannelsPerAPA = 2*(229.44/0.3 + 1);
122 # dune10kt ~45 deg UV wires version
123 if($UVAngle45Option==1){
138 $SinUAngle = sin( deg2rad($UAngle) );
139 $CosUAngle = cos( deg2rad($UAngle) );
140 $TanUAngle = tan( deg2rad($UAngle) );
142 $SinVAngle = sin( deg2rad($VAngle) );
143 $CosVAngle = cos( deg2rad($VAngle) );
144 $TanVAngle = tan( deg2rad($VAngle) );
146 $UWire_yint = $UWirePitch/$SinUAngle;
147 $UWire_zint = $UWirePitch/$CosUAngle;
149 $VWire_yint = $VWirePitch/$SinVAngle;
150 $VWire_zint = $VWirePitch/$CosVAngle;
152 $TPCWireThickness = 0.015;
154 $TPCWirePlaneThickness = $TPCWireThickness;
155 #height and length defined lower
159 ##################################################################
160 ################### Cryostat/APA parameters ######################
166 elsif($workspace==2){
171 $nAPAs = $nAPAWide*$nAPAHigh*$nAPALong;
174 $G10thickness = $inch/8;
175 $WrapCover = $inch/16;
177 $SpaceAPAToCryoWall = 15;
178 $SpaceAPAToFloor = 59.4 - 10.2; # 10.2cm just adjusts for how spaces are reported
179 $SpaceAPAToTopLAr = 50.9 - 10.2;
180 $UpstreamLArPadding = 311.4 - 10.2;
181 $DownstreamLArPadding = 59.4 - 10.2;
184 $SpaceAPAToCryoWall = 20;
185 $SpaceAPAToFloor = 45;
186 $SpaceAPAToTopLAr = 45;
187 $UpstreamLArPadding = 80;
188 $DownstreamLArPadding = 80;
191 #InnerDrift is the max distance form the edge of the CPA to the edge of the first wire plane
193 $OuterDrift = $SpaceAPAToCryoWall;
194 $APAFrame_x = 5.0661; # ~2in -- this does not include the wire spacing
196 $TPCWireThickness = 0.015;
197 $TPCWirePlaneThickness = $TPCWireThickness;
198 #$APAWirePlaneSpacing = 0.4730488 + $TPCWirePlaneThickness; # center to center spacing between all of the wire planes (g, u, v, and x)
200 if($Pitch3mmVersion==1){
201 $APAWirePlaneSpacing = 0.3;
203 $APAWirePlaneSpacing = 0.476;
206 # At creation of the plane volumes, the y and z boundaries will be increased
207 # by this much at each of the 4 edges. this is so the corners of the wire
208 # tubes don't extrude. For all other purposes, the plane dimensions stay as originally defined
209 $UVPlaneBoundNudge = $TPCWireThickness;
213 # The following are all widths about the z center of an APA
214 $Zactive_z = ($nZChannelsPerAPA/2-1)*$XWirePitch + $TPCWireThickness;
215 $APAFrame_z = 231.59 - 2*(2*$G10thickness+$WrapCover);
216 $Vactive_z = $APAFrame_z;
217 $Uactive_z = $APAFrame_z + 2*$G10thickness;
222 $ReadoutBoardOverlap = 7.61; #board overlaps wires, chop this off of their active height
224 $Zactive_y = $APAFrame_y + 0*$G10thickness - $ReadoutBoardOverlap;
225 $Vactive_y = $APAFrame_y + 1*$G10thickness - $ReadoutBoardOverlap;
226 $Uactive_y = $APAFrame_y + 2*$G10thickness - $ReadoutBoardOverlap;
227 # the last G10 board for the grid, then a cover. This is not "covered" by the board
228 $APAphys_y = $APAFrame_y + 4*$G10thickness + $WrapCover;
230 $APAGap_y = 0.4; #separation between APAs (cover to cover) along the incident beam axis
231 $APAGap_z = 0.8; #separation between APAs (cover to cover) along the vertical axis
234 # include APA spacing in y and z so volTPCs touch in y and z directions with correct APA
235 # spacing - this makes for smoother event generation.
237 $APA_UtoU_x = $APAFrame_x + 6*$APAWirePlaneSpacing + $TPCWirePlaneThickness; # thickness of APA between its
238 # outer wire planes (center to center)
239 $TPCInner_x = $InnerDrift + 3*$APAWirePlaneSpacing + $TPCWirePlaneThickness;
240 $TPCOuter_x = $OuterDrift + 3*$APAWirePlaneSpacing + $TPCWirePlaneThickness;
242 $TPC_z = $APAphys_z + $APAGap_z;
243 $TPC_y = $APAphys_y + $APAGap_y;
246 #$CPATube_ID = 4.747;
249 $Cathode_y = $APAphys_y - $CPATube_OD;
250 $Cathode_z = $APAphys_z - $CPATube_OD;
253 $APAToAPA = $APAFrame_x
255 + $Cathode_x; # center to center
257 $CPAToAPA = $APAFrame_x/2
259 + $Cathode_x/2; # center to center
261 $SteelThickness = 0.5*$inch; #half inch
262 $HeightGaseousAr = 50;
264 $Argon_x = ($nAPAWide-1)*$APAToAPA
265 + $APA_UtoU_x + $TPCWirePlaneThickness
266 + 2*$SpaceAPAToCryoWall;
270 $FC_x = ($nAPAWide-1)*$APAToAPA
271 + $APA_UtoU_x + $TPCWirePlaneThickness;
273 if($workspace==1||$workspace==2){ # this is arbitrary for the workspace, but size down a little
274 $Argon_x = 2*$CPAToAPA + $Cathode_x + 2*$SpaceAPAToCryoWall;
275 $FC_x = 2*$CPAToAPA + $Cathode_x;
279 $LArgon_y = $nAPAHigh*$APAphys_y
280 + ($nAPAHigh-1)*$APAGap_y
281 + $SpaceAPAToFloor + $SpaceAPAToTopLAr;
285 $Argon_z = $nAPALong*$APAphys_z
286 + ($nAPALong-1)*$APAGap_z
287 + $UpstreamLArPadding + $DownstreamLArPadding;
289 $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.
290 $FCO_y = $FCI_y+(0.1*$inch)*2; #The outer boundary of the Fied Cage
291 $FCI_z = $nAPALong*$TPC_z
292 + $FC_b; #the plus FC_b is +2 cm arbitrarily. This makes sure the FC doesn't contact the APAs.
293 $FCO_z = $FCI_z+(0.1*$inch)*2;
295 $FC_b = 2; #2 cm buffer for FC
297 $Cryostat_x = $Argon_x + 2*$SteelThickness;
298 $Cryostat_y = $Argon_y + 2*$SteelThickness;
299 $Cryostat_z = $Argon_z + 2*$SteelThickness;
301 ### Add dimensions for the source cylinder.
302 $Source_x_center = $FC_x_center + 220; # 220 cm past the center plane of the TPCs.
303 $Source_y_center = $FC_y_center + 300 -20 ; # 300 cm above the center of the active volume (-20 unexplained correction taken from viewer.
304 $Source_z_center = $FC_z_center - ($FCO_z/2) - 40+ 130; # 40 cm outside the field cage in Z. (+130 unexplained correction from viewer.
305 $SourceModerator_d = 20; #20 cm diameter cylinder
306 $SourceModerator_z = 20; # 20 cm tall cylinder
309 #Make Source VolumeReference
310 #Make Source position reference.
311 #Make SourceModerator
312 #Make Source child of Source Moderator
314 ##################################################################
315 ############## DetEnc and World relevant parameters #############
318 $SteelSupport_x = 100;
319 $SteelSupport_y = 50;
320 $SteelSupport_z = 100;
322 $FracMassOfSteel = 0.998; #The steel support is not a solid block, but a mixture of air and steel
323 $FracMassOfAir = 1-$FracMassOfSteel;
325 $SpaceSteelSupportToWall = 100;
326 $SpaceSteelSupportToCeiling = 100;
328 $DetEncWidth = $Cryostat_x
329 + 2*($SteelSupport_x + $FoamPadding) + $SpaceSteelSupportToCeiling;
330 $DetEncHeight = $Cryostat_y
331 + 2*($SteelSupport_y + $FoamPadding) + 2*$SpaceSteelSupportToWall;
332 $DetEncLength = $Cryostat_z
333 + 2*($SteelSupport_z + $FoamPadding) + 2*$SpaceSteelSupportToWall;
335 $posCryoInDetEnc_y = - $DetEncHeight/2 + $SteelSupport_y + $FoamPadding + $Cryostat_y/2;
337 $RockThickness = 3000;
338 if ($workspace == 0){
339 # Initially, the world dimensions and the OriginZSet
340 # left only ~222cm to the world boundary from the
341 # +z boundary of volDetEnclosure. Bump that up to
342 # at least 10m for good measure.
343 # This is in an if statement so that it does not affect
344 # the workspace geometries, which are already being used
345 $RockThickness += 800
348 # We want the world origin to be at the very front of the fiducial volume.
349 # move it to the front of the enclosure, then back it up through the concrete/foam,
350 # then through the Cryostat shell, then through the upstream dead LAr (including the
351 # dead LAr on the edge of the TPC, but this is covered in $UpstreamLArPadding).
352 # This is to be added to the z position of every volume in volWorld
354 $OriginZSet = $DetEncLength/2
355 - $SpaceSteelSupportToWall
359 - $UpstreamLArPadding
360 - ($APAphys_z - $Uactive_z)/2;
362 # We want the world origin to be vertically centered between the stacked APAs.
363 # This is to be added to the y position of every volume in volWorld
365 $OriginYSet = $DetEncHeight/2
373 if($protoDune==1){ # bring the origin to the bottom of the APAs for protoDUNE
374 $OriginYSet = $OriginYSet + $APAphys_y + $APAGap_y/2;
377 $OriginXSet = 0; # centered for now
384 ####################################################################
385 ######################## Paddle Dimensions ########################
387 $APAFrameZSide_y = 4*$inch;
388 $APAFrameYSide_z = 4*$inch;
389 $LightPaddle_x = 0.476;
390 $LightPaddle_y = 4*$inch;
391 $LightPaddle_z = $APAFrame_z - 2*$APAFrameYSide_z;
392 $nLightPaddlesPerAPA = 10; # 10, or 20 for double coverage (for now)
393 $PaddleYInterval = (2*$APAphys_y+$APAGap_y-$LightPaddle_y-2*$APAFrameZSide_y)
394 /(2*$nLightPaddlesPerAPA-1);
395 $FrameToPaddleSpace = ($PaddleYInterval-$APAGap_y)/2;
399 # $PaddleYInterval is defined so that the center-to-center distance in the
400 # y direction between paddles is uniform between vertically stacked APAs.
401 # $FrameToPaddleSpace is from the BOTTOM of the APA frame (4" in y direction)
402 # to the CENTER of a paddle, including the 4" part of the frame. This variable's
403 # primary purpose is to position the lowest paddle in each APA.
408 #+++++++++++++++++++++++++ End defining variables ++++++++++++++++++++++++++
411 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
412 #+++++++++++++++++++++++++++++++++++++++++ usage +++++++++++++++++++++++++++++++++++++++++
413 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
417 print "Usage: $0 [-h|--help] [-o|--output <fragments-file>] [-s|--suffix <string>]\n";
418 print " if -o is omitted, output goes to STDOUT; <fragments-file> is input to make_gdml.pl\n";
419 print " -s <string> appends the string to the file names; useful for multiple detector versions\n";
420 print " -h prints this message, then quits\n";
425 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
426 #++++++++++++++++++++++++++++++++++++++ gen_Define +++++++++++++++++++++++++++++++++++++++
427 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
432 # Create the <define> fragment file name,
433 # add file to list of fragments,
435 $DEF = "dune10kt_v3_Def" . $suffix . ".gdml";
436 push (@gdmlFiles, $DEF);
438 open(DEF) or die("Could not open file $DEF for writing");
442 <?xml version='1.0'?>
452 <position name="posCryoInDetEnc" unit="cm" x="0" y="@{[$posCryoInDetEnc_y]}" z="0"/>
453 <position name="posCenter" unit="cm" x="0" y="0" z="0"/>
454 <rotation name="rPlus90AboutX" unit="deg" x="90" y="0" z="0"/>
455 <rotation name="rMinus90AboutY" unit="deg" x="0" y="270" z="0"/>
456 <rotation name="rMinus90AboutYMinus90AboutX" unit="deg" x="270" y="270" z="0"/>
457 <rotation name="rPlusUAngleAboutX" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
458 <rotation name="rPlusVAngleAboutX" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
459 <rotation name="rPlus180AboutX" unit="deg" x="180" y="0" z="0"/>
460 <rotation name="rPlus180AboutY" unit="deg" x="0" y="180" z="0"/>
461 <rotation name="rPlus180AboutXPlus180AboutY" unit="deg" x="180" y="180" z="0"/>
462 <rotation name="rIdentity" unit="deg" x="0" y="0" z="0"/>
469 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
470 #+++++++++++++++++++++++++++++++++++++ gen_Materials +++++++++++++++++++++++++++++++++++++
471 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
476 # Create the <materials> fragment file name,
477 # add file to list of output GDML fragments,
479 $MAT = "dune10kt_v3_Materials" . $suffix . ".gdml";
480 push (@gdmlFiles, $MAT);
483 open(MAT) or die("Could not open file $MAT for writing");
485 # Add any materials special to this geometry by defining a mulitline string
486 # and passing it to the gdmlMaterials::gen_Materials() function.
488 $DensityAirSteel = 1/(0.001205/$FracMassOfAir + 7.9300/$FracMassOfSteel);
491 <!-- preliminary values -->
492 <material name="AirSteelMixture" formula="AirSteelMixture">
493 <D value="$DensityAirSteel" unit="g/cm3"/>
494 <fraction n="$FracMassOfSteel" ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
495 <fraction n="$FracMassOfAir" ref="Air"/>
499 # add the general materials used anywere
500 print MAT gdmlMaterials::gen_Materials( $asmix );
505 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
506 #++++++++++++++++++++++++++++++++++++++++ gen_TPC ++++++++++++++++++++++++++++++++++++++++
507 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
518 my $TPCActive_x = $_[0]-(3*$APAWirePlaneSpacing);
519 my $TPCActive_y = $_[1] - $APAGap_y/2 - $ReadoutBoardOverlap ; #TODO: make the Active height more accurate
520 my $TPCActive_z = $_[2];
523 #constructs everything inside volTPC, namely
524 # (moving from left to right, or from +x to -x)
526 # -volTPCPlaneU: with wires angled from vertical slightly different than in V
527 # -volTPCPlaneV: with wires angled from vertical slightly differently than in U
528 # -volTPCPlaneX: with vertical wires
531 # Create the TPC fragment file name,
532 # add file to list of output GDML fragments,
534 $TPC = "dune10kt_v3_TPC_${_[3]}" . $suffix . ".gdml";
535 push (@gdmlFiles, $TPC);
537 open(TPC) or die("Could not open file $TPC for writing");
540 print $wout "\n\n\n----- Wires for $_[3] -----\n\n\n";
543 # The standard XML prefix and starting the gdml
545 <?xml version='1.0'?>
550 # All the TPC solids save the wires.
553 <box name="$_[3]" lunit="cm"
557 <box name="${_[3]}UPlane" lunit="cm"
558 x="@{[$TPCWirePlaneThickness]}"
559 y="@{[$Uactive_y + $UVPlaneBoundNudge]}"
560 z="@{[$Uactive_z + $UVPlaneBoundNudge]}"/>
561 <box name="${_[3]}VPlane" lunit="cm"
562 x="@{[$TPCWirePlaneThickness]}"
563 y="@{[$Vactive_y + $UVPlaneBoundNudge]}"
564 z="@{[$Vactive_z + $UVPlaneBoundNudge]}"/>
565 <box name="${_[3]}ZPlane" lunit="cm"
566 x="@{[$TPCWirePlaneThickness]}"
568 z="@{[$Zactive_z]}"/>
569 <box name="${_[3]}Active" lunit="cm"
570 x="@{[$TPCActive_x]}"
571 y="@{[$TPCActive_y]}"
572 z="@{[$TPCActive_z]}"/>
576 #++++++++++++++++++++++++++++ Wire Solids ++++++++++++++++++++++++++++++
580 <tube name="${_[3]}WireVert"
581 rmax="@{[0.5*$TPCWireThickness]}"
588 # Set number of wires to default to zero, when $wires_on = 0, for a low memory
589 # version. But if $wires_on = 1, calculate the number of wires on each side of each
590 # plane to be used in the for loops
592 my $NumberCornerUWires = 0;
593 my $NumberSideUWires = 0;
594 my $NumberCommonUWires = 0;
595 my $NumberCornerVWires = 0;
596 my $NumberSideVWires = 0;
597 my $NumberCommonVWires = 0;
598 my $NumberVerticalWires = 0;
602 # Number of wires in one corner
603 $NumberCornerUWires = int( $APAFrame_z/($UWirePitch/$CosUAngle) );
605 $NumberCornerVWires = int( $APAFrame_z/($VWirePitch/$CosVAngle) );
608 # Total number of wires touching one vertical (longer) side
609 # Note that the total number of wires per plane is this + another set of corner wires
610 $NumberSideUWires = int( $Uactive_y/$UWire_yint );
611 if($Pitch3mmVersion==1){ $NumberSideUWires = $NumberSideUWires-1; }
613 $NumberSideVWires = int( $Vactive_y/$VWire_yint );
615 # Number of wires per side that aren't cut off by the corner
616 $NumberCommonUWires = $NumberSideUWires - $NumberCornerUWires;
618 $NumberCommonVWires = $NumberSideVWires - $NumberCornerVWires;
620 # Number of wires on the vertical plane
621 # Since APA Active z is defined in docdb 3383 to be distance
622 # between outer vertical wires, + 1 since the floor of this
623 # division will be one under, giving the amt of spaces, not wires
624 $NumberVerticalWires = int( $Zactive_z/$XWirePitch ) + 1;
625 #$NumberVerticalWires = 960;
628 $nUchans = 2*$NumberCornerUWires;
629 $nVchans = 2*$NumberCornerVWires;
631 print $wout "$nUchans U channels\n";
632 print $wout "$nVchans V channels\n";
633 print $wout "$NumberVerticalWires Z channels per side\n";
635 print $wout "$NumberCornerUWires U corner wires\n";
636 print $wout "$NumberCommonUWires U common wires\n";
637 print $wout "$NumberCornerVWires V corner wires\n";
638 print $wout "$NumberCommonVWires V common wires\n";
642 # hard codeed number will be a factor determined from engineering spreadsheets on wire endpoints,
643 # but since that won't exist for a while, use this number to avoid overlaps
644 my $FirstUWireOffset = .55 + $G10thickness + 2*$G10thickness*$TanUAngle - $UWire_zint;
645 my $FirstVWireOffset = .5; # doesnt include a G10 board in width
647 if($Pitch3mmVersion==1){
648 my $FirstUWireOffset = .15 + $G10thickness + 2*$G10thickness*$TanUAngle - $UWire_zint;
649 my $FirstVWireOffset = .15; # doesnt include a G10 board in width
652 if($UVAngle45Option==1){$FirstVWireOffset = .7;}
655 my $FirstTopUWire_yspan =
658 + $FirstUWireOffset/$TanUAngle # walk us up to the first wire
659 + $UWire_yint*($NumberSideUWires-1) # up to the top of the top common wire
660 - $Uactive_z/$TanUAngle # back to the bottom of the top common wire
661 + $UWire_yint); # nudge up to bottom of the first top corner wire
663 my $FirstTopVWire_yspan =
666 + $FirstVWireOffset/$TanVAngle # walk us up to the first wire
667 + $VWire_yint*($NumberSideVWires-1) # up to the top of the top common wire
668 - $Vactive_z/$TanVAngle # back to the bottom of the top common wire
669 + $VWire_yint); # nudge up to bottom of the first top corner wire
672 # The corner wires for the U plane
675 for ($i = 0; $i < $NumberCornerUWires; $i++)
677 $CornerUWireLength[$i] = ($FirstUWireOffset + $i*$UWire_zint)/$SinUAngle;
680 <tube name="${_[3]}WireU$i"
681 rmax="@{[0.5*$TPCWireThickness]}"
682 z="@{[$CornerUWireLength[$i]]}"
690 $CommonUWireLength = $Uactive_z/$SinUAngle;
693 <tube name="${_[3]}WireUCommon"
694 rmax="@{[0.5*$TPCWireThickness]}"
695 z="@{[$CommonUWireLength]}"
701 for ($i = 0; $i < $NumberCornerUWires; $i++)
704 $TopCornerUWireLength[$i] = ($FirstTopUWire_yspan - $i*$UWire_yint)/$CosUAngle;
706 $j = $i + $NumberSideUWires;
709 <tube name="${_[3]}WireU$j"
710 rmax="@{[0.5*$TPCWireThickness]}"
711 z="@{[$TopCornerUWireLength[$i]]}"
722 # The corner wires for the V plane
725 for ($i = 0; $i < $NumberCornerVWires; ++$i)
727 $CornerVWireLength[$i] = ($FirstVWireOffset + $i*$VWire_zint)/$SinVAngle;
731 <tube name="${_[3]}WireV$i"
732 rmax="@{[0.5*$TPCWireThickness]}"
733 z="@{[$CornerVWireLength[$i]]}"
742 # The wire used many times in the middle of the V plane
743 # Same subtraction as U common
745 $CommonVWireLength = $Vactive_z/$SinVAngle;
748 <tube name="${_[3]}WireVCommon"
749 rmax="@{[0.5*$TPCWireThickness]}"
750 z="@{[$CommonVWireLength]}"
756 for ($i = 0; $i < $NumberCornerVWires; $i++)
759 $TopCornerVWireLength[$i] = ($FirstTopVWire_yspan - $i*$VWire_yint)/$CosVAngle;
761 $j = $i + $NumberSideVWires;
764 <tube name="${_[3]}WireV$j"
765 rmax="@{[0.5*$TPCWireThickness]}"
766 z="@{[$TopCornerVWireLength[$i]]}"
777 # Begin structure and create the vertical wire logical volume
781 <volume name="volTPCActive${_[3]}">
782 <materialref ref="LAr"/>
783 <solidref ref="${_[3]}Active"/>
792 <volume name="volTPCWireVert${_[3]}">
793 <materialref ref="Copper_Beryllium_alloy25"/>
794 <solidref ref="${_[3]}WireVert"/>
798 # Corner U wires logical volumes
799 for ($i = 0; $i < $NumberCornerUWires; ++$i)
802 <volume name="volTPCWireU$i${_[3]}">
803 <materialref ref="Copper_Beryllium_alloy25"/>
804 <solidref ref="${_[3]}WireU$i"/>
810 # Top Corner U wires logical volumes
811 for ($j = $NumberSideUWires; $j < $NumberSideUWires + $NumberCornerUWires; ++$j)
814 <volume name="volTPCWireU$j${_[3]}">
815 <materialref ref="Copper_Beryllium_alloy25"/>
816 <solidref ref="${_[3]}WireU$j"/>
822 # Common U wire logical volume, referenced many times
824 <volume name="volTPCWireUCommon${_[3]}">
825 <materialref ref="Copper_Beryllium_alloy25"/>
826 <solidref ref="${_[3]}WireUCommon"/>
831 # Corner V wires logical volumes
832 for ($i = 0; $i < $NumberCornerVWires; ++$i)
835 <volume name="volTPCWireV$i${_[3]}">
836 <materialref ref="Copper_Beryllium_alloy25"/>
837 <solidref ref="${_[3]}WireV$i"/>
843 # Top Corner V wires logical volumes
844 for ($j = $NumberSideVWires; $j < $NumberSideVWires + $NumberCornerVWires; ++$j)
847 <volume name="volTPCWireV$j${_[3]}">
848 <materialref ref="Copper_Beryllium_alloy25"/>
849 <solidref ref="${_[3]}WireV$j"/>
854 # Common V wire logical volume, referenced many times
856 <volume name="volTPCWireVCommon${_[3]}">
857 <materialref ref="Copper_Beryllium_alloy25"/>
858 <solidref ref="${_[3]}WireVCommon"/>
869 #+++++++++++++++++++++++++ Position physical wires ++++++++++++++++++++++++++
871 # ++++++++++++++++++++++ U Plane +++++++++++++++++++++++
873 # Create U plane logical volume
875 <volume name="volTPCPlaneU${_[3]}">
876 <materialref ref="LAr"/>
877 <solidref ref="${_[3]}UPlane"/>
881 print $wout "\n- Wires for U plane -\n\n";
882 print $wout " Uplane_y: $Uactive_y\n";
883 print $wout " Uplane_z: $Uactive_z\n";
889 # Starting with the bottom left corner wires:
890 # x=0 to center the wires in the plane
891 # y positioning: (-0.5*$TPCWirePlaneHeight) starts the incremental increase
892 # from the bottom of the plane, and trigonometry gives the increment
893 # z positioning: Looking at the plane from the positive x direction,
894 # (0.5*$TPCWirePlaneLength) starts the incremental increase from
895 # the lower left corner.
896 # rotation: same as common wire in code below
898 $FirstU_ypos = - $Uactive_y/2 + $FirstUWireOffset/$TanUAngle/2;
899 $FirstU_zpos = + $Uactive_z/2 - $FirstUWireOffset/2;
901 for ($i = 0; $i < $NumberCornerUWires; ++$i)
904 my $ypos = $FirstU_ypos + ($i)*0.5*$UWire_yint;
905 my $zpos = $FirstU_zpos - ($i)*0.5*$UWire_zint;
907 $pitch = ($ypos - $lastYpos) * $SinUAngle
908 - ($zpos - $lastZpos) * $CosUAngle;
912 <volumeref ref="volTPCWireU$i${_[3]}"/>
913 <position name="pos${_[3]}WireU$i" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
914 <rotation name="rUAngle$i" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
918 $topY = $ypos + ($CosUAngle*$CornerUWireLength[$i]/2);
919 $bottomY = $ypos - ($CosUAngle*$CornerUWireLength[$i]/2);
920 $edgeZ_p = $zpos + ($SinUAngle*$CornerUWireLength[$i]/2);
921 $edgeZ_m = $zpos - ($SinUAngle*$CornerUWireLength[$i]/2);
922 print $wout "U$i: ( $ypos , $zpos ) (pitch = $pitch)\n";
923 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
931 # Moving upwards to the common wires:
932 # x and z are zero to center the wires along a vertical axis
933 # y positioning: The trick is positioning the lowest common wire so that the pitch
934 # is consistent, then the increment is double the increment of
935 # the corner wires since there is no z incriment.
936 # rotation: wires in \\\\ direction, so +90deg to bring them to vertical and
937 # +UAngle counterclockwise to arrive at proper orientation
938 # Note that the counter maintains wire number (in pos. name) counting bottom to top
941 my $StartCommonUWires_ypos = $lastYpos + $UWire_yint - abs( $lastZpos )/$TanUAngle;
943 for ($i = $NumberCornerUWires; $i < $NumberSideUWires; ++$i)
946 $j = $i - $NumberCornerUWires;
947 my $ypos = $StartCommonUWires_ypos + $UWire_yint*($j);
950 if ( $ypos < $lastYpos ){ print "WARNING: y position dropped from $lastYpos (wire U$lastWnum) to $ypos (wire U$i)\n"; }
951 if ( $ypos == $lastYpos ){ print "WARNING: y position between wire U$lastWnum and U$lastWnum did not move: $ypos\n"; }
954 $pitch = ($ypos - $lastYpos) * $SinUAngle - ($zpos - $lastZpos) * $CosUAngle ;
958 <volumeref ref="volTPCWireUCommon${_[3]}"/>
959 <position name="pos${_[3]}WireU$i" unit="cm" x="0" y="@{[$ypos ]}" z="0"/>
960 <rotation name="rUAngle$i" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
964 $topY = $ypos + ($CosUAngle*$CommonUWireLength/2);
965 $bottomY = $ypos - ($CosUAngle*$CommonUWireLength/2);
966 $edgeZ_p = + ($SinUAngle*$CommonUWireLength/2);
967 $edgeZ_m = - ($SinUAngle*$CommonUWireLength/2);
968 print $wout "U$i: ( $ypos , 0 ) (pitch = $pitch)\n";
969 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
978 my $FirstTopUWire_zspan = $FirstTopUWire_yspan*$TanUAngle;
979 my $StartTopUWires_ypos = + $Uactive_y/2 - $FirstTopUWire_yspan/2;
980 my $StartTopUWires_zpos = - $Uactive_z/2 + $FirstTopUWire_zspan/2;
982 # Finally moving to the corner wires on the top right:
983 # x=0 to center the wires in the plane
984 # y positioning: plug wire number into same equation
985 # z positioning: start at z=0 and go negatively at the same z increment
986 # rotation: same as common wire in code above
987 # note that the counter maintains wire number shown in the position name
989 for ($j = $NumberSideUWires; $j < $NumberSideUWires+$NumberCornerUWires; ++$j)
992 $i = $j - $NumberSideUWires;
994 my $ypos = $StartTopUWires_ypos + ($i)*0.5*$UWire_yint;
995 my $zpos = $StartTopUWires_zpos - ($i)*0.5*$UWire_zint;
998 if ( $ypos < $lastYpos ){ print "WARNING: y position dropped from $lastYpos (wire U$lastWnum) to $ypos (wire U$j)\n"; }
999 if ( $ypos == $lastYpos ){ print "WARNING: y position between wire U$lastWnum and U$j did not move: $ypos\n"; }
1001 $pitch = ($ypos - $lastYpos) * $SinUAngle - ($zpos - $lastZpos) * $CosUAngle ;
1005 <volumeref ref="volTPCWireU$j${_[3]}"/>
1006 <position name="pos${_[3]}WireU$j" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
1007 <rotation name="rUAngle$j" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
1011 $topY = $ypos + ($CosUAngle*$TopCornerUWireLength[$i]/2);
1012 $bottomY = $ypos - ($CosUAngle*$TopCornerUWireLength[$i]/2);
1013 $edgeZ_p = $zpos + ($SinUAngle*$TopCornerUWireLength[$i]/2);
1014 $edgeZ_m = $zpos - ($SinUAngle*$TopCornerUWireLength[$i]/2);
1015 print $wout "U$j: ( $ypos , $zpos ) (pitch = $pitch)\n";
1016 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1026 # ++++++++++++++++++++++ V Plane +++++++++++++++++++++++
1028 # End U plane and create V plane logical volume
1032 <volume name="volTPCPlaneV${_[3]}">
1033 <materialref ref="LAr"/>
1034 <solidref ref="${_[3]}VPlane"/>
1037 print $wout "\n- Wires for V plane -\n\n";
1038 print $wout " Vplane_y: $Vactive_y\n";
1039 print $wout " Vplane_z: $Vactive_z\n";
1045 # Starting with the bottom right corner wires:
1046 # x=0 to center the wires in the plane
1047 # y positioning: (-0.5*$TPCWirePlaneHeight) starts the incremental increase
1048 # from the bottom of the plane, and trigonometry gives the increment
1049 # z positioning: Looking at the plane from the positive x direction,
1050 # (-0.5*$TPCWirePlaneLength) starts the incremental increase from
1051 # the lower right corner.
1052 # rotation: same as common wire in code below
1054 $FirstV_ypos = - $Vactive_y/2 + $FirstVWireOffset/$TanVAngle/2;
1055 $FirstV_zpos = - $Vactive_z/2 + $FirstVWireOffset/2;
1057 for ($i = 0; $i < $NumberCornerVWires; ++$i)
1060 my $ypos = $FirstV_ypos + ($i)*0.5*$VWire_yint;
1061 my $zpos = $FirstV_zpos + ($i)*0.5*$VWire_zint;
1065 <volumeref ref="volTPCWireV$i${_[3]}"/>
1066 <position name="pos${_[3]}WireV$i" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
1067 <rotation name="rVAngle$i" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1071 $topY = $ypos + ($CosVAngle*$CornerVWireLength[$i]/2);
1072 $bottomY = $ypos - ($CosVAngle*$CornerVWireLength[$i]/2);
1073 $edgeZ_p = $zpos + ($SinVAngle*$CornerVWireLength[$i]/2);
1074 $edgeZ_m = $zpos - ($SinVAngle*$CornerVWireLength[$i]/2);
1075 print $wout "V$i: ( $ypos , $zpos ) \n";
1076 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1084 # Moving upwards to the common wires:
1085 # x and z are zero to center the wires along a vertical axis
1086 # y positioning: Plug wire number into the same corner ypos equation
1087 # rotation: wires in //// direction, so +90deg to bring them to vertical and
1088 # --VAngle counterclockwise to arrive at proper orientation
1089 # Note that the counter maintains wire number in the position name
1091 my $StartCommonVWires_ypos = $lastYpos + $VWire_yint - abs( $lastZpos )/$TanVAngle;
1093 for ($i = $NumberCornerVWires; $i < $NumberSideVWires; ++$i)
1096 $j = $i - $NumberCornerVWires;
1097 my $ypos = $StartCommonVWires_ypos + $VWire_yint*($j);
1101 <volumeref ref="volTPCWireVCommon${_[3]}"/>
1102 <position name="pos${_[3]}WireV$i" unit="cm" x="0" y="@{[$ypos ]}" z="0"/>
1103 <rotation name="rVAngle$i" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1107 $topY = $ypos + ($CosVAngle*$CommonVWireLength/2);
1108 $bottomY = $ypos - ($CosVAngle*$CommonVWireLength/2);
1109 $edgeZ_p = + ($SinVAngle*$CommonVWireLength/2);
1110 $edgeZ_m = - ($SinVAngle*$CommonVWireLength/2);
1111 print $wout "V$i: ( $ypos , 0 ) \n";
1112 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1115 #$lastZpos = $zpos; always 0
1120 my $FirstTopVWire_zspan = $FirstTopVWire_yspan*$TanVAngle;
1121 my $StartTopVWires_ypos = + $Vactive_y/2 - $FirstTopVWire_yspan/2;
1122 my $StartTopVWires_zpos = + $Vactive_z/2 - $FirstTopVWire_zspan/2;
1124 # Finally moving to the corner wires on the top right:
1125 # x=0 to center the wires in the plane
1126 # y positioning: plug wire number into same equation
1127 # z positioning: start at z=0 and go positively at the same z increment
1128 # rotation: same as common wire in code above
1129 # note that the counter maintains wire number shown in the position name
1131 for ($j = $NumberSideVWires; $j < $NumberSideVWires+$NumberCornerVWires; ++$j)
1134 $i = $j - $NumberSideVWires;
1136 my $ypos = $StartTopVWires_ypos + ($i)*0.5*$VWire_yint;
1137 my $zpos = $StartTopVWires_zpos + ($i)*0.5*$VWire_zint;
1141 <volumeref ref="volTPCWireV$j${_[3]}"/>
1142 <position name="pos${_[3]}WireV$j" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
1143 <rotation name="rVAngle$j" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1147 $topY = $ypos + ($CosVAngle*$TopCornerVWireLength[$i]/2);
1148 $bottomY = $ypos - ($CosVAngle*$TopCornerVWireLength[$i]/2);
1149 $edgeZ_p = $zpos + ($SinVAngle*$TopCornerVWireLength[$i]/2);
1150 $edgeZ_m = $zpos - ($SinVAngle*$TopCornerVWireLength[$i]/2);
1151 print $wout "V$j: ( $ypos , $zpos ) \n";
1152 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1165 # ++++++++++++++++++++++ Z Plane +++++++++++++++++++++++
1167 # End V plane and create Z plane logical volume
1171 <volume name="volTPCPlaneZ${_[3]}">
1172 <materialref ref="LAr"/>
1173 <solidref ref="${_[3]}ZPlane"/>
1179 # This is the simplest plane, one loop creates all of the wires
1180 # x and y position at zero to center the wires
1181 # z position: moving from front of detector to back, in the positive z direction,
1182 # starting at (-0.5*$TPCWirePlaneLength), the right side looking from
1185 for ($i=0; $i<$NumberVerticalWires; ++$i)
1187 my $zpos = (-0.5*$Zactive_z) + $i*$XWirePitch + $TPCWireThickness/2;
1191 <volumeref ref="volTPCWireVert${_[3]}"/>
1192 <position name="pos${_[3]}WireZ$i" unit="cm" x="0" y="0 " z="@{[$zpos]}"/>
1193 <rotationref ref="rPlus90AboutX"/>
1205 #+++++++++++++++++++++ ^^ Position physical wires Above ^^ +++++++++++++++++++++
1207 ## make the TPC active volume extend down to the G10 for the grid
1209 my $BottomOfAPA = - $TPC_y/2 + $APAGap_y/2;
1212 $posZplane[0] = -$_[0]/2 + $APAWirePlaneSpacing - $TPCWirePlaneThickness/2;
1213 $posZplane[1] = $BottomOfAPA + $WrapCover + 4*$G10thickness + $Zactive_y/2;
1216 $posVplane[0] = $posZplane[0] + $APAWirePlaneSpacing;
1217 $posVplane[1] = $BottomOfAPA + $WrapCover + 3*$G10thickness + $Vactive_y/2;
1218 $posVplane[2] = $posZplane[2];
1220 $posUplane[0] = $posVplane[0] + $APAWirePlaneSpacing;
1221 $posUplane[1] = $BottomOfAPA + $WrapCover + 2*$G10thickness + $Uactive_y/2;
1222 $posUplane[2] = $posZplane[2];
1224 $posTPCActive[0] = $posUplane[0] + ($TPCWirePlaneThickness/2 + $TPCActive_x/2);
1225 $posTPCActive[1] = -$_[1]/2 + $TPCActive_y/2;
1226 $posTPCActive[2] = 0;
1228 #wrap up the TPC file
1230 <volume name="volTPC${_[3]}">
1231 <materialref ref="LAr"/>
1232 <solidref ref="${_[3]}"/>
1234 <volumeref ref="volTPCPlaneZ${_[3]}"/>
1235 <position name="pos${_[3]}PlaneZ" unit="cm"
1236 x="@{[$posZplane[0]]}" y="@{[$posZplane[1]]}" z="@{[$posZplane[2]]}"/>
1237 <rotationref ref="rIdentity"/>
1240 <volumeref ref="volTPCPlaneV${_[3]}"/>
1241 <position name="pos${_[3]}PlaneV" unit="cm"
1242 x="@{[$posVplane[0]]}" y="@{[$posVplane[1]]}" z="@{[$posVplane[2]]}"/>
1243 <rotationref ref="rIdentity"/>
1246 <volumeref ref="volTPCPlaneU${_[3]}"/>
1247 <position name="pos${_[3]}PlaneU" unit="cm"
1248 x="@{[$posUplane[0]]}" y="@{[$posUplane[1]]}" z="@{[$posUplane[2]]}"/>
1249 <rotationref ref="rIdentity"/>
1253 # Option to omit the active volume on the outside for the prototype.
1254 if( !($killOuterActive==1 && $_[3] eq 'Outer') ){
1257 <volumeref ref="volTPCActive${_[3]}"/>
1258 <position name="pos${_[3]}Active" unit="cm"
1259 x="@{[$posTPCActive[0]]}" y="@{[$posTPCActive[1]]}" z="@{[$posTPCActive[2]]}"/>
1260 <rotationref ref="rIdentity"/>
1273 } #end of sub gen_TPC
1277 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1278 #++++++++++++++++++++++++++++++++++++++ gen_Cryostat +++++++++++++++++++++++++++++++++++++
1279 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1284 # Create the cryostat fragment file name,
1285 # add file to list of output GDML fragments,
1287 $CRYO = "dune10kt_v3_Cryostat" . $suffix . ".gdml";
1288 push (@gdmlFiles, $CRYO);
1289 $CRYO = ">" . $CRYO;
1290 open(CRYO) or die("Could not open file $CRYO for writing");
1293 # The standard XML prefix and starting the gdml
1295 <?xml version='1.0'?>
1299 $APAFrameZSide_x = $APAFrame_x;
1300 $APAFrameZSide_y = 4*$inch;
1301 $APAFrameZSide_z = $APAFrame_z;
1303 $APAFrameYSide_x = $APAFrame_x;
1304 $APAFrameYSide_y = $APAFrame_y-2*$APAFrameZSide_y;
1305 $APAFrameYSide_z = 4*$inch;
1307 # Two outer Y supports will sandwich the light paddles
1308 $APAFrameYOuterSupport_x = ($APAFrame_x-$LightPaddle_x)/2;
1309 $APAFrameYOuterSupport_y = $APAFrame_y-2*$APAFrameZSide_y;
1310 $APAFrameYOuterSupport_z = 4*$inch;
1312 $EdgeFrameSteelThickness = 0.12*$inch;
1313 $InnerFrameSteelThickness = 0.062*$inch;
1316 $G10BoardYSide_x = $APAFrame_x;
1317 $G10BoardYSide_y = $APAFrame_y;
1318 $G10BoardYSide_z = $G10thickness;
1320 $G10BoardZSide_x = $APAFrame_x;
1321 $G10BoardZSide_y = $G10thickness;
1322 $G10BoardZSide_z = $APAFrame_z;
1324 ##################################################################
1325 ################### Field Cage Y and Z centers ###################
1331 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.
1333 $tmp_APACenter_z = - $Argon_z/2
1334 + $UpstreamLArPadding
1336 + $k*($APAphys_z+$APAGap_z);
1337 $FC_z_center = $FC_z_center + $tmp_APACenter_z;
1339 $FC_z_center = $FC_z_center / $nAPALong;
1341 for($j=0 ; $j<$nAPAHigh ; $j++) # nAPAHigh always going to be 2
1343 $tmp_APACenter_y = - $Argon_y/2 + $SpaceAPAToFloor
1345 + $j*($APAphys_y+$APAGap_y);
1346 $FC_y_center = $FC_y_center + $tmp_APACenter_y;
1348 $FC_y_center = $FC_y_center / $nAPAHigh;
1350 # All the cryostat solids.
1353 <tube name="SourceModerator"
1354 rmax="@{[0.5*$SourceModerator_d]}"
1355 z="@{[$SourceModerator_z]}"
1359 <box name="Cryostat" lunit="cm"
1360 x="@{[$Cryostat_x]}"
1361 y="@{[$Cryostat_y]}"
1362 z="@{[$Cryostat_z]}"/>
1363 <box name="ArgonInterior" lunit="cm"
1367 <box name="FieldCageOut" lunit="cm"
1371 <box name="FieldCageIn" lunit="cm"
1375 <subtraction name="FieldCage">
1376 <first ref="FieldCageOut"/>
1377 <second ref="FieldCageIn"/>
1379 <box name="GaseousArgon" lunit="cm"
1381 y="@{[$HeightGaseousAr]}"
1383 <subtraction name="SteelShell">
1384 <first ref="Cryostat"/>
1385 <second ref="ArgonInterior"/>
1387 <box name="Cathode" lunit="cm"
1390 z="@{[$Cathode_z]}"/>
1392 <box name="LightPaddle" lunit="cm"
1393 x="@{[$LightPaddle_x]}"
1394 y="@{[$LightPaddle_y]}"
1395 z="@{[$LightPaddle_z + $SiPM_z]}"/>
1397 <box name="APAFrameYSideHollow" lunit="cm"
1398 x="@{[$APAFrameYSide_x-2*$EdgeFrameSteelThickness]}"
1399 y="@{[$APAFrameYSide_y-2*$EdgeFrameSteelThickness]}"
1400 z="@{[$APAFrameYSide_z]}"/>
1401 <box name="APAFrameYSideShell" lunit="cm"
1402 x="@{[$APAFrameYSide_x]}"
1403 y="@{[$APAFrameYSide_y]}"
1404 z="@{[$APAFrameYSide_z]}"/>
1405 <subtraction name="APAFrameYSide">
1406 <first ref="APAFrameYSideShell"/>
1407 <second ref="APAFrameYSideHollow"/>
1408 <positionref ref="posCenter"/>
1409 <rotationref ref="rIdentity"/>
1412 <box name="APAFrameZSideHollow" lunit="cm"
1413 x="@{[$APAFrameZSide_x-2*$EdgeFrameSteelThickness]}"
1414 y="@{[$APAFrameZSide_y-2*$EdgeFrameSteelThickness]}"
1415 z="@{[$APAFrameZSide_z]}"/>
1416 <box name="APAFrameZSideShell" lunit="cm"
1417 x="@{[$APAFrameZSide_x]}"
1418 y="@{[$APAFrameZSide_y]}"
1419 z="@{[$APAFrameZSide_z]}"/>
1420 <subtraction name="APAFrameZSide">
1421 <first ref="APAFrameZSideShell"/>
1422 <second ref="APAFrameZSideHollow"/>
1423 <positionref ref="posCenter"/>
1424 <rotationref ref="rIdentity"/>
1427 <box name="APAFrameYOuterSupport" lunit="cm"
1428 x="@{[$EdgeFrameSteelThickness]}"
1429 y="@{[$APAFrameYOuterSupport_y]}"
1430 z="@{[$APAFrameYOuterSupport_z]}"/>
1433 <box name="G10BoardYSideCenterSeg" lunit="cm"
1434 x="@{[$G10BoardYSide_x]}"
1435 y="@{[$G10BoardYSide_y]}"
1436 z="@{[$G10BoardYSide_z]}"/>
1438 <box name="G10BoardZSideCenterSeg" lunit="cm"
1439 x="@{[$G10BoardZSide_x]}"
1440 y="@{[$G10BoardZSide_y]}"
1441 z="@{[$G10BoardZSide_z]}"/>
1446 # Cryostat structure
1449 <volume name="volSteelShell">
1450 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1451 <solidref ref="SteelShell" />
1453 <volume name="volSourceModerator">
1454 <materialref ref="Delrin"/>
1455 <solidref ref="SourceModerator"/>
1457 <volume name="volFieldCage">
1458 <materialref ref="ALUMINUM_Al"/>
1459 <solidref ref="FieldCage"/>
1461 <volume name="volGaseousArgon">
1462 <materialref ref="ArGas"/>
1463 <solidref ref="GaseousArgon"/>
1465 <volume name="volCathode">
1466 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1467 <solidref ref="Cathode" />
1471 for($i=0 ; $i<$nAPAs ; $i++){
1472 for($p=0 ; $p<10 ; $p++){
1474 <volume name="volOpDetSensitive_$i\-$p">
1475 <materialref ref="Acrylic"/>
1476 <solidref ref="LightPaddle"/>
1485 <volume name="volAPAFrameYSide">
1486 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1487 <solidref ref="APAFrameYSide"/>
1490 <volume name="volAPAFrameZSide">
1491 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1492 <solidref ref="APAFrameZSide"/>
1495 <volume name="volAPAFrameYOuterSupport">
1496 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1497 <solidref ref="APAFrameYOuterSupport"/>
1500 <volume name="volG10BoardYSideCenterSeg">
1501 <materialref ref="G10"/>
1502 <solidref ref="G10BoardYSideCenterSeg"/>
1505 <volume name="volG10BoardZSideCenterSeg">
1506 <materialref ref="G10"/>
1507 <solidref ref="G10BoardZSideCenterSeg"/>
1510 <volume name="volCryostat">
1511 <materialref ref="LAr" />
1512 <solidref ref="Cryostat" />
1514 <volumeref ref="volGaseousArgon"/>
1515 <position name="posGaseousArgon" unit="cm" x="0" y="@{[$Argon_y/2-$HeightGaseousAr/2]}" z="0"/>
1518 <volumeref ref="volSourceModerator"/>
1519 <position name="posSourceModerator" unit="cm"
1520 x="@{[$Source_x_center]}"
1521 y="@{[$Source_y_center]}"
1522 z="@{[$Source_z_center]}"/>
1523 <rotationref ref="rPlus90AboutX"/>
1526 <volumeref ref="volFieldCage"/>
1527 <position name="posFieldCage" unit="cm"
1528 x="@{[$FC_x_center]}"
1529 y="@{[$FC_y_center]}"
1530 z="@{[$FC_z_center]}"/>
1533 <volumeref ref="volSteelShell"/>
1534 <position name="posSteelShell" unit="cm" x="0" y="0" z="0"/>
1538 # nested for loops to place the non-rotated AND rotated volTPC
1539 # x loop rotation: There are six drift volumes. Looking into the
1540 # detector from incident direction, and counting from right (-x) to
1541 # left (+x), odd number volumes need to be rotated 180deg about Y in
1542 # order for the cathode to be on the right of the APA.
1549 for($k=0 ; $k<$nAPALong ; $k++)
1551 $APACenter_z = - $Argon_z/2
1552 + $UpstreamLArPadding
1554 + $k*($APAphys_z+$APAGap_z);
1557 for($j=0 ; $j<$nAPAHigh ; $j++) # nAPAHigh always going to be 2
1558 { # $j=0 for bottom APAs
1560 $APACenter_y = - $Argon_y/2 + $SpaceAPAToFloor
1562 + $j*($APAphys_y+$APAGap_y);
1565 if( $workspace == 0 )
1568 for($i=0 ; $i<$nAPAWide ; $i++)
1572 $APACenter_x = - $Argon_x/2
1573 + $SpaceAPAToCryoWall + $APA_UtoU_x/2 + $TPCWirePlaneThickness/2
1576 $CPA_x = $APACenter_x + $CPAToAPA;
1579 place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, $j);
1580 place_OpDets($APACenter_x, $APACenter_y, $APACenter_z, $apa_i);
1581 $tpc_0 = 2*$apa_i+0;
1582 $tpc_1 = 2*$apa_i+1;
1585 $SelectTPC_0 = "Inner";
1586 $SelectTPC_1 = "Inner";
1587 $TPC_0_x = $TPCInner_x;
1588 $TPC_1_x = $TPCInner_x;
1589 $rot_0 = "rPlus180AboutY";
1590 $rot_1 = "rIdentity";
1591 if($i == 0) { $SelectTPC_0 = "Outer"; $TPC_0_x = $TPCOuter_x; }
1592 if($i == $nAPAWide-1) { $SelectTPC_1 = "Outer"; $TPC_1_x = $TPCOuter_x; }
1593 if($j == 0) { $rot_0 = "rPlus180AboutXPlus180AboutY";
1594 $rot_1 = "rPlus180AboutX"; } #put the readout end at the bottom for bottom APAs
1601 <volumeref ref="volTPC$SelectTPC_0"/>
1602 <position name="posTPC\-$tpc_0" unit="cm"
1603 x="@{[$APACenter_x - $APAFrame_x/2 - $TPC_0_x/2]}"
1604 y="@{[$APACenter_y]}"
1605 z="@{[$APACenter_z]}"/>
1606 <rotationref ref="$rot_0"/>
1609 <volumeref ref="volTPC$SelectTPC_1"/>
1610 <position name="posTPC\-$tpc_1" unit="cm"
1611 x="@{[$APACenter_x + $APAFrame_x/2 + $TPC_1_x/2]}"
1612 y="@{[$APACenter_y]}"
1613 z="@{[$APACenter_z]}"/>
1614 <rotationref ref="$rot_1"/>
1620 if( $i < $nAPAWide - 1 ){ # avoid placeing the last row of CPAs since the APAs are on the outside
1625 <volumeref ref="volCathode"/>
1626 <position name="posCathode\-$cpa_i" unit="cm"
1628 y="@{[$APACenter_y]}"
1629 z="@{[$APACenter_z]}"/>
1630 <rotationref ref="rIdentity"/>
1640 } # end if not the smaller workspace
1643 # Make the workspace have only one center APA with CPAs and the full drift on either side
1644 elsif( $workspace == 1 || $workspace==2 ){
1647 $CPA_0_x = $APACenter_x - $CPAToAPA;
1648 $CPA_1_x = $APACenter_x + $CPAToAPA;
1651 place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, $j);
1652 place_OpDets($APACenter_x, $APACenter_y, $APACenter_z, $apa_i);
1654 $tpc_0 = 2*$apa_i+0;
1655 $tpc_1 = 2*$apa_i+1;
1658 $rot_0 = "rPlus180AboutY";
1659 $rot_1 = "rIdentity";
1660 if($j == 0) { $rot_0 = "rPlus180AboutXPlus180AboutY";
1661 $rot_1 = "rPlus180AboutX"; } #put the readout end at the bottom for bottom APAs
1666 <volumeref ref="volTPCInner"/>
1667 <position name="posTPC\-$tpc_0" unit="cm"
1668 x="@{[$APACenter_x - $APAFrame_x/2 - $TPCInner_x/2]}"
1669 y="@{[$APACenter_y]}"
1670 z="@{[$APACenter_z]}"/>
1671 <rotationref ref="$rot_0"/>
1674 <volumeref ref="volTPCInner"/>
1675 <position name="posTPC\-$tpc_1" unit="cm"
1676 x="@{[$APACenter_x + $APAFrame_x/2 + $TPCInner_x/2]}"
1677 y="@{[$APACenter_y]}"
1678 z="@{[$APACenter_z]}"/>
1679 <rotationref ref="$rot_1"/>
1683 <volumeref ref="volCathode"/>
1684 <position name="posCathode\-$apa_i-0" unit="cm"
1686 y="@{[$APACenter_y]}"
1687 z="@{[$APACenter_z]}"/>
1688 <rotationref ref="rIdentity"/>
1691 <volumeref ref="volCathode"/>
1692 <position name="posCathode\-$apa_i-1" unit="cm"
1694 y="@{[$APACenter_y]}"
1695 z="@{[$APACenter_z]}"/>
1696 <rotationref ref="rIdentity"/>
1701 } # if the smaller workspace
1720 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1721 #++++++++++++++++++++++++++++++++++++ place_OpDets +++++++++++++++++++++++++++++++++++++++
1722 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1727 $APACenter_x = $_[0];
1728 $APACenter_y = $_[1];
1729 $APACenter_z = $_[2];
1732 for ($paddle = 0; $paddle<$nLightPaddlesPerAPA; $paddle++)
1735 # All Light Paddle centers will have the same
1736 # X coordinate as the center of the current APA
1737 # Z coordinate as the current TPC pair
1738 # The Y coordinate must be looped over:
1740 #the multiplication by j here is a temporary dirty trick to get around some strange behavior
1742 $Paddle_Y = $APACenter_y
1744 + $j*$FrameToPaddleSpace
1745 + (1-$j)*($LightPaddle_y/2 + $APAFrameZSide_y)
1746 + $PaddleYInterval*$paddle;
1748 # Alternate the paddle orientations
1749 if ( $paddle % 2 == 0 ) { $rot = "rIdentity"; }
1750 else { $rot = "rPlus180AboutY"; }
1755 <volumeref ref="volOpDetSensitive_$apa_i\-$paddle"/>
1756 <position name="posPaddle\-$paddle\-TPC\-$i\-$j\-$k" unit="cm"
1757 x="@{[$APACenter_x]}"
1759 z="@{[$APACenter_z + $SiPM_z/2]}"/>
1760 <rotationref ref="$rot"/>
1764 }#end Paddle for-loop
1770 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1771 #++++++++++++++++++++++++++++++++++++++ place_APA ++++++++++++++++++++++++++++++++++++++++
1772 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1775 # Must be called only within gen_Cryostat(),
1778 # $_[0] = x APA physical center
1779 # $_[1] = y APA physical center
1780 # $_[2] = z APA physical center
1781 # $_[3] = APA number
1782 # $_[4] = 0 for APA with readout on bottom
1783 # 1 for APA with readout on top
1790 ####################################################################
1791 ################# APA Frame and Paddle Dimensions ##################
1793 # The center passed to this function is the physical APA center,
1794 # which is not quite the frame's center, since there are more boards
1795 # at the bottom. Transform them:
1797 $APAFrameCenter_x = $_[0];
1798 $APAFrameCenter_z = $_[2];
1800 # The bottom APAs are upside down relative to how the TPC is initially generated,
1801 # and the center needs to be slightly shifted since there is extra G10 on the
1802 # end that doesn't read out.
1804 if($_[4]==1) # top APAs
1806 $APAFrameCenter_y = $_[1] - $APAphys_y/2
1807 + $WrapCover + 4*$G10thickness
1810 elsif($_[4]==0) # bottom APAs
1812 $APAFrameCenter_y = $_[1] + $APAphys_y/2
1813 - $WrapCover - 4*$G10thickness
1816 else{ print "APA not labeled as top or bottom"; }
1818 $APAFrameZSide_x = $APAFrame_x;
1819 $APAFrameZSide_y = 4*$inch;
1820 $APAFrameZSide_z = $APAFrame_z;
1822 $APAFrameYSide_x = $APAFrame_x;
1823 $APAFrameYSide_y = $APAFrame_y-2*$APAFrameZSide_y;
1824 $APAFrameYSide_z = 4*$inch;
1826 # Two outer Y supports will sandwich the light paddles
1827 $APAFrameYOuterSupport_x = ($APAFrame_x-$LightPaddle_x)/2;
1828 $APAFrameYOuterSupport_y = $APAFrame_y-2*$APAFrameZSide_y;
1829 $APAFrameYOuterSupport_z = 4*$inch;
1831 # if there were an inner support to fill the hole
1832 $APAFrameYInnerSupport_x = $LightPaddle_x;
1834 $EdgeFrameSteelThickness = 0.12*$inch;
1835 $InnerFrameSteelThickness = 0.062*$inch;
1838 $G10BoardYSide_x = $APAFrame_x;
1839 $G10BoardYSide_y = $APAFrame_y;
1840 $G10BoardYSide_z = $G10thickness;
1842 $G10BoardZSide_x = $APAFrame_x;
1843 $G10BoardZSide_y = $G10thickness;
1844 $G10BoardZSide_z = $APAFrame_z;
1846 if($_[4]==1) # top APAs
1848 $posG10ZSideZ_y = $APAFrameCenter_y - $APAFrame_y/2 - (0+.5)*($G10BoardZSide_y);
1849 $posG10ZSideV_y = $APAFrameCenter_y - $APAFrame_y/2 - (1+.5)*($G10BoardZSide_y);
1850 $posG10ZSideU_y = $APAFrameCenter_y - $APAFrame_y/2 - (2+.5)*($G10BoardZSide_y);
1851 $posG10ZSideGrid_y = $APAFrameCenter_y - $APAFrame_y/2 - (3+.5)*($G10BoardZSide_y);
1853 elsif($_[4]==0) # bottom APAs
1855 $posG10ZSideZ_y = $APAFrameCenter_y + $APAFrame_y/2 + (0+.5)*($G10BoardZSide_y);
1856 $posG10ZSideV_y = $APAFrameCenter_y + $APAFrame_y/2 + (1+.5)*($G10BoardZSide_y);
1857 $posG10ZSideU_y = $APAFrameCenter_y + $APAFrame_y/2 + (2+.5)*($G10BoardZSide_y);
1858 $posG10ZSideGrid_y = $APAFrameCenter_y + $APAFrame_y/2 + (3+.5)*($G10BoardZSide_y);
1860 else{ print "APA not labeled as top or bottom"; }
1862 # First put in the frame
1866 # <volumeref ref="volAPAFrameYOuterSupport\-$APA_i"/>
1867 # <position name="posAPAFrameYOuterSupportNeg\-$APA_i" unit="cm"
1868 # x="$APAFrameCenter_x - ($APAFrameYOuterSupport_x + $APAFrameYInnerSupport_x/2 - $EdgeFrameSteelThickness/2)"
1869 # y="$APAFrameCenter_y"
1870 # z="$APAFrameCenter_z"/>
1871 # <rotationref ref="rIdentity"/>
1874 # <volumeref ref="volAPAFrameYOuterSupport\-$APA_i"/>
1875 # <position name="posAPAFrameYOuterSupportPos\-$APA_i" unit="cm"
1876 # x="$APAFrameCenter_x + ($APAFrameYOuterSupport_x + $APAFrameYInnerSupport_x/2 - $EdgeFrameSteelThickness/2)"
1877 # y="$APAFrameCenter_y"
1878 # z="$APAFrameCenter_z"/>
1879 # <rotationref ref="rIdentity"/>
1885 <volumeref ref="volAPAFrameYSide"/>
1886 <position name="posAPAFrameYSideNeg\-$APA_i" unit="cm"
1887 x="@{[$APAFrameCenter_x]}"
1888 y="@{[$APAFrameCenter_y]}"
1889 z="@{[$APAFrameCenter_z - $APAFrame_z/2 + $APAFrameYSide_z/2]}"/>
1890 <rotationref ref="rIdentity"/>
1893 <volumeref ref="volAPAFrameYSide"/>
1894 <position name="posAPAFrameYSidePos\-$APA_i" unit="cm"
1895 x="@{[$APAFrameCenter_x]}"
1896 y="@{[$APAFrameCenter_y]}"
1897 z="@{[$APAFrameCenter_z + $APAFrame_z/2 - $APAFrameYSide_z/2]}"/>
1898 <rotationref ref="rIdentity"/>
1901 <volumeref ref="volAPAFrameZSide"/>
1902 <position name="posAPAFrameZSidePos\-$APA_i" unit="cm"
1903 x="@{[$APAFrameCenter_x]}"
1904 y="@{[$APAFrameCenter_y + $APAFrame_y/2 - $APAFrameZSide_y/2]}"
1905 z="@{[$APAFrameCenter_z]}"/>
1906 <rotationref ref="rIdentity"/>
1909 <volumeref ref="volAPAFrameZSide"/>
1910 <position name="posAPAFrameZSideNeg\-$APA_i" unit="cm"
1911 x="@{[$APAFrameCenter_x]}"
1912 y="@{[$APAFrameCenter_y - $APAFrame_y/2 + $APAFrameZSide_y/2]}"
1913 z="@{[$APAFrameCenter_z]}"/>
1914 <rotationref ref="rIdentity"/>
1918 <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1919 - Add the *parts* of the G10 boards that exist directly in volCryostat.
1920 - There are two boards on each the up and downstream end,
1921 one each to wrap the U and V views around the APA frame
1922 - There are 4 on the bottom which anchor the U V and Z wires and the grid plane
1923 - The rest of the parts of the G10 boards must be placed directly in volTPC -->
1926 <volumeref ref="volG10BoardYSideCenterSeg"/>
1927 <position name="posG10BoardYSideCenterSeg\-Vup\-$APA_i" unit="cm"
1928 x="@{[$APAFrameCenter_x]}"
1929 y="@{[$APAFrameCenter_y]}"
1930 z="@{[$APAFrameCenter_z - $APAFrame_z/2 - (0+.5)*($G10BoardYSide_z)]}"/>
1931 <rotationref ref="rIdentity"/>
1934 <volumeref ref="volG10BoardYSideCenterSeg"/>
1935 <position name="posG10BoardYSideCenterSeg\-Uup\-$APA_i" unit="cm"
1936 x="@{[$APAFrameCenter_x]}"
1937 y="@{[$APAFrameCenter_y]}"
1938 z="@{[$APAFrameCenter_z - $APAFrame_z/2 - (1+.5)*($G10BoardYSide_z)]}"/>
1939 <rotationref ref="rIdentity"/>
1943 <volumeref ref="volG10BoardYSideCenterSeg"/>
1944 <position name="posG10BoardYSideCenterSeg\-Vdown\-$APA_i" unit="cm"
1945 x="@{[$APAFrameCenter_x]}"
1946 y="@{[$APAFrameCenter_y]}"
1947 z="@{[$APAFrameCenter_z + $APAFrame_z/2 + (0+.5)*($G10BoardYSide_z)]}"/>
1948 <rotationref ref="rIdentity"/>
1951 <volumeref ref="volG10BoardYSideCenterSeg"/>
1952 <position name="posG10BoardYSideCenterSeg\-Udown\-$APA_i" unit="cm"
1953 x="@{[$APAFrameCenter_x]}"
1954 y="@{[$APAFrameCenter_y]}"
1955 z="@{[$APAFrameCenter_z + $APAFrame_z/2 + (1+.5)*($G10BoardYSide_z)]}"/>
1956 <rotationref ref="rIdentity"/>
1960 <volumeref ref="volG10BoardZSideCenterSeg"/>
1961 <position name="posG10BoardZSideCenterSeg\-Z\-$APA_i" unit="cm"
1962 x="@{[$APAFrameCenter_x]}"
1963 y="@{[$posG10ZSideZ_y]}"
1964 z="@{[$APAFrameCenter_z]}"/>
1965 <rotationref ref="rIdentity"/>
1968 <volumeref ref="volG10BoardZSideCenterSeg"/>
1969 <position name="posG10BoardZSideCenterSeg\-V\-$APA_i" unit="cm"
1970 x="@{[$APAFrameCenter_x]}"
1971 y="@{[$posG10ZSideV_y]}"
1972 z="@{[$APAFrameCenter_z]}"/>
1973 <rotationref ref="rIdentity"/>
1976 <volumeref ref="volG10BoardZSideCenterSeg"/>
1977 <position name="posG10BoardZSideCenterSeg\-U\-$APA_i" unit="cm"
1978 x="@{[$APAFrameCenter_x]}"
1979 y="@{[$posG10ZSideU_y]}"
1980 z="@{[$APAFrameCenter_z]}"/>
1981 <rotationref ref="rIdentity"/>
1984 <volumeref ref="volG10BoardZSideCenterSeg"/>
1985 <position name="posG10BoardZSideCenterSeg\-Grid\-$APA_i" unit="cm"
1986 x="@{[$APAFrameCenter_x]}"
1987 y="@{[$posG10ZSideGrid_y]}"
1988 z="@{[$APAFrameCenter_z]}"/>
1989 <rotationref ref="rIdentity"/>
2000 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2001 #+++++++++++++++++++++++++++++++++++++ gen_Enclosure +++++++++++++++++++++++++++++++++++++
2002 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2007 # Create the detector enclosure fragment file name,
2008 # add file to list of output GDML fragments,
2010 $ENCL = "dune10kt_v3_DetEnclosure" . $suffix . ".gdml";
2011 push (@gdmlFiles, $ENCL);
2012 $ENCL = ">" . $ENCL;
2013 open(ENCL) or die("Could not open file $ENCL for writing");
2016 # The standard XML prefix and starting the gdml
2018 <?xml version='1.0'?>
2023 # All the detector enclosure solids.
2027 <box name="FoamPadBlock" lunit="cm"
2028 x="@{[$Cryostat_x + 2*$FoamPadding]}"
2029 y="@{[$Cryostat_y + 2*$FoamPadding]}"
2030 z="@{[$Cryostat_z + 2*$FoamPadding]}" />
2032 <box name="FoamPadInner" lunit="cm"
2033 x="@{[$Cryostat_x + 0.01]}"
2034 y="@{[$Cryostat_y + 0.01]}"
2035 z="@{[$Cryostat_z + 0.01]}" />
2037 <subtraction name="FoamPadding">
2038 <first ref="FoamPadBlock"/>
2039 <second ref="FoamPadInner"/>
2040 <positionref ref="posCenter"/>
2043 <box name="SteelSupportBlock" lunit="cm"
2044 x="@{[$Cryostat_x + 2*$FoamPadding + 2*$SteelSupport_x]}"
2045 y="@{[$Cryostat_y + 2*$FoamPadding + 2*$SteelSupport_y]}"
2046 z="@{[$Cryostat_z + 2*$FoamPadding + 2*$SteelSupport_z]}" />
2048 <box name="SteelSupportInner" lunit="cm"
2049 x="@{[$Cryostat_x + 2*$FoamPadding + 0.01]}"
2050 y="@{[$Cryostat_y + 2*$FoamPadding + 0.01]}"
2051 z="@{[$Cryostat_z + 2*$FoamPadding + 0.01]}" />
2053 <subtraction name="SteelSupport">
2054 <first ref="SteelSupportBlock"/>
2055 <second ref="SteelSupportInner"/>
2056 <positionref ref="posCenter"/>
2059 <box name="DetEnclosure" lunit="cm"
2060 x="@{[$DetEncWidth]}"
2061 y="@{[$DetEncHeight]}"
2062 z="@{[$DetEncLength]}"/>
2069 # Detector enclosure structure
2072 <volume name="volFoamPadding">
2073 <materialref ref="FD_foam"/>
2074 <solidref ref="FoamPadding"/>
2077 <volume name="volSteelSupport">
2078 <materialref ref="AirSteelMixture"/>
2079 <solidref ref="SteelSupport"/>
2082 <volume name="volDetEnclosure">
2083 <materialref ref="Air"/>
2084 <solidref ref="DetEnclosure"/>
2087 <volumeref ref="volFoamPadding"/>
2088 <positionref ref="posCryoInDetEnc"/>
2091 <volumeref ref="volSteelSupport"/>
2092 <positionref ref="posCryoInDetEnc"/>
2095 <volumeref ref="volCryostat"/>
2096 <positionref ref="posCryoInDetEnc"/>
2115 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2116 #+++++++++++++++++++++++++++++++++++++++ gen_World +++++++++++++++++++++++++++++++++++++++
2117 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2122 # Create the WORLD fragment file name,
2123 # add file to list of output GDML fragments,
2125 $WORLD = "dune10kt_v3_World" . $suffix . ".gdml";
2126 push (@gdmlFiles, $WORLD);
2127 $WORLD = ">" . $WORLD;
2128 open(WORLD) or die("Could not open file $WORLD for writing");
2131 # The standard XML prefix and starting the gdml
2133 <?xml version='1.0'?>
2138 # All the World solids.
2141 <box name="World" lunit="cm"
2142 x="@{[$DetEncWidth+2*$RockThickness]}"
2143 y="@{[$DetEncHeight+2*$RockThickness]}"
2144 z="@{[$DetEncLength+2*$RockThickness]}"/>
2151 <volume name="volWorld" >
2152 <materialref ref="DUSEL_Rock"/>
2153 <solidref ref="World"/>
2156 <volumeref ref="volDetEnclosure"/>
2157 <position name="posDetEnclosure" unit="cm" x="@{[$OriginXSet]}" y="@{[$OriginYSet]}" z="@{[$OriginZSet]}"/>
2165 # make_gdml.pl will take care of <setup/>
2172 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2173 #++++++++++++++++++++++++++++++++++++ write_fragments ++++++++++++++++++++++++++++++++++++
2174 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2176 sub write_fragments()
2178 # This subroutine creates an XML file that summarizes the the subfiles output
2179 # by the other sub routines - it is the input file for make_gdml.pl which will
2180 # give the final desired GDML file. Specify its name with the output option.
2181 # (you can change the name when running make_gdml)
2183 # This code is taken straigh from the similar MicroBooNE generate script, Thank you.
2185 if ( ! defined $output )
2187 $output = "-"; # write to STDOUT
2190 # Set up the output file.
2191 $OUTPUT = ">" . $output;
2192 open(OUTPUT) or die("Could not open file $OUTPUT");
2195 <?xml version='1.0'?>
2197 <!-- Input to Geometry/gdml/make_gdml.pl; define the GDML fragments
2198 that will be zipped together to create a detector description.
2205 <!-- These files contain GDML <constant></constant>
2206 blocks. They are read in separately, so they can be
2207 interpreted into the remaining GDML. See make_gdml.pl for
2213 foreach $filename (@defFiles)
2216 <filename> $filename </filename>
2226 <!-- The GDML file fragments to be zipped together. -->
2230 foreach $filename (@gdmlFiles)
2233 <filename> $filename </filename>
2249 # run the sub routines that generate the fragments
2251 gen_Define(); # generates definitions at beginning of GDML
2252 gen_Materials(); # generates materials to be used
2255 gen_TPC( $TPCInner_x, $TPC_y, $TPC_z, 'Inner');
2256 gen_TPC( $TPCOuter_x, $TPC_y, $TPC_z, 'Outer');
2260 gen_Cryostat(); # places (2*nAPAWide x nAPAHigh x nAPALong) volTPC,
2261 # half rotated 180 about Y
2262 gen_Enclosure(); # places two cryostats and concrete volumes
2264 gen_World(); # places the enclosure among DUSEL Rock
2267 write_fragments(); # writes the XML input for make_gdml.pl
2268 # which zips together the final GDML