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 ############### Double Sided Arapuca Dimensions ###################
387 $APAFrameZSide_y = 4*$inch;
388 $APAFrameYSide_z = 4*$inch;
391 $ArapucaOut_y = 11.8;
392 $ArapucaOut_z = 209.2;
393 #$ArapucaOut_z = $APAFrame_z - 2*$APAFrameYSide_z;
397 $ArapucaAcceptanceWindow_x = 2.2;
398 $ArapucaAcceptanceWindow_y = 9.3;
399 $ArapucaAcceptanceWindow_z = 46.8;
400 $gapCenter_arapuca_z = 16.0;
401 $gapBetween_arapuca_z = 2.0;
403 $list_pos[0]=-0.5*$gapCenter_arapuca_z-1.5*$ArapucaIn_z-$gapBetween_arapuca_z;
404 $list_pos[1]=$list_pos[0]+$ArapucaIn_z+$gapBetween_arapuca_z;
405 $list_pos[2]=0.5*$gapCenter_arapuca_z+0.5*$ArapucaIn_z;
406 $list_pos[3]=$list_pos[2]+$ArapucaIn_z+$gapBetween_arapuca_z;
408 $nLightPaddlesPerAPA = 10; # 10, or 20 for double coverage (for now)
409 $PaddleYInterval = (2*$APAphys_y+$APAGap_y-$ArapucaOut_y-2*$APAFrameZSide_y)
410 /(2*$nLightPaddlesPerAPA-1);
411 $FrameToPaddleSpace = ($PaddleYInterval-$APAGap_y)/2;
414 # $PaddleYInterval is defined so that the center-to-center distance in the
415 # y direction between paddles is uniform between vertically stacked APAs.
416 # $FrameToPaddleSpace is from the BOTTOM of the APA frame (4" in y direction)
417 # to the CENTER of a paddle, including the 4" part of the frame. This variable's
418 # primary purpose is to position the lowest paddle in each APA.
423 #+++++++++++++++++++++++++ End defining variables ++++++++++++++++++++++++++
426 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
427 #+++++++++++++++++++++++++++++++++++++++++ usage +++++++++++++++++++++++++++++++++++++++++
428 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
432 print "Usage: $0 [-h|--help] [-o|--output <fragments-file>] [-s|--suffix <string>]\n";
433 print " if -o is omitted, output goes to STDOUT; <fragments-file> is input to make_gdml.pl\n";
434 print " -s <string> appends the string to the file names; useful for multiple detector versions\n";
435 print " -h prints this message, then quits\n";
440 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
441 #++++++++++++++++++++++++++++++++++++++ gen_Define +++++++++++++++++++++++++++++++++++++++
442 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
447 # Create the <define> fragment file name,
448 # add file to list of fragments,
450 $DEF = "dune10kt_v4_Def" . $suffix . ".gdml";
451 push (@gdmlFiles, $DEF);
453 open(DEF) or die("Could not open file $DEF for writing");
457 <?xml version='1.0'?>
467 <position name="posCryoInDetEnc" unit="cm" x="0" y="@{[$posCryoInDetEnc_y]}" z="0"/>
468 <position name="posCenter" unit="cm" x="0" y="0" z="0"/>
469 <rotation name="rPlus90AboutX" unit="deg" x="90" y="0" z="0"/>
470 <rotation name="rMinus90AboutY" unit="deg" x="0" y="270" z="0"/>
471 <rotation name="rMinus90AboutYMinus90AboutX" unit="deg" x="270" y="270" z="0"/>
472 <rotation name="rPlusUAngleAboutX" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
473 <rotation name="rPlusVAngleAboutX" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
474 <rotation name="rPlus180AboutX" unit="deg" x="180" y="0" z="0"/>
475 <rotation name="rPlus180AboutY" unit="deg" x="0" y="180" z="0"/>
476 <rotation name="rPlus180AboutXPlus180AboutY" unit="deg" x="180" y="180" z="0"/>
477 <rotation name="rIdentity" unit="deg" x="0" y="0" z="0"/>
478 <position name="posArapucaSub0" unit="cm" x="0" y="0" z="@{[$list_pos[0]]}"/>
479 <position name="posArapucaSub1" unit="cm" x="0" y="0" z="@{[$list_pos[1]]}"/>
480 <position name="posArapucaSub2" unit="cm" x="0" y="0" z="@{[$list_pos[2]]}"/>
481 <position name="posArapucaSub3" unit="cm" x="0" y="0" z="@{[$list_pos[3]]}"/>
488 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
489 #+++++++++++++++++++++++++++++++++++++ gen_Materials +++++++++++++++++++++++++++++++++++++
490 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
495 # Create the <materials> fragment file name,
496 # add file to list of output GDML fragments,
498 $MAT = "dune10kt_v4_Materials" . $suffix . ".gdml";
499 push (@gdmlFiles, $MAT);
502 open(MAT) or die("Could not open file $MAT for writing");
504 # Add any materials special to this geometry by defining a mulitline string
505 # and passing it to the gdmlMaterials::gen_Materials() function.
507 $DensityAirSteel = 1/(0.001205/$FracMassOfAir + 7.9300/$FracMassOfSteel);
510 <!-- preliminary values -->
511 <material name="AirSteelMixture" formula="AirSteelMixture">
512 <D value="$DensityAirSteel" unit="g/cm3"/>
513 <fraction n="$FracMassOfSteel" ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
514 <fraction n="$FracMassOfAir" ref="Air"/>
518 # add the general materials used anywere
519 print MAT gdmlMaterials::gen_Materials( $asmix );
524 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
525 #++++++++++++++++++++++++++++++++++++++++ gen_TPC ++++++++++++++++++++++++++++++++++++++++
526 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
537 my $TPCActive_x = $_[0]-(3*$APAWirePlaneSpacing);
538 my $TPCActive_y = $_[1] - $APAGap_y/2 - $ReadoutBoardOverlap ; #TODO: make the Active height more accurate
539 my $TPCActive_z = $_[2];
542 #constructs everything inside volTPC, namely
543 # (moving from left to right, or from +x to -x)
545 # -volTPCPlaneU: with wires angled from vertical slightly different than in V
546 # -volTPCPlaneV: with wires angled from vertical slightly differently than in U
547 # -volTPCPlaneX: with vertical wires
550 # Create the TPC fragment file name,
551 # add file to list of output GDML fragments,
553 $TPC = "dune10kt_v4_TPC_${_[3]}" . $suffix . ".gdml";
554 push (@gdmlFiles, $TPC);
556 open(TPC) or die("Could not open file $TPC for writing");
559 print $wout "\n\n\n----- Wires for $_[3] -----\n\n\n";
562 # The standard XML prefix and starting the gdml
564 <?xml version='1.0'?>
569 # All the TPC solids save the wires.
572 <box name="$_[3]" lunit="cm"
576 <box name="${_[3]}UPlane" lunit="cm"
577 x="@{[$TPCWirePlaneThickness]}"
578 y="@{[$Uactive_y + $UVPlaneBoundNudge]}"
579 z="@{[$Uactive_z + $UVPlaneBoundNudge]}"/>
580 <box name="${_[3]}VPlane" lunit="cm"
581 x="@{[$TPCWirePlaneThickness]}"
582 y="@{[$Vactive_y + $UVPlaneBoundNudge]}"
583 z="@{[$Vactive_z + $UVPlaneBoundNudge]}"/>
584 <box name="${_[3]}ZPlane" lunit="cm"
585 x="@{[$TPCWirePlaneThickness]}"
587 z="@{[$Zactive_z]}"/>
588 <box name="${_[3]}Active" lunit="cm"
589 x="@{[$TPCActive_x]}"
590 y="@{[$TPCActive_y]}"
591 z="@{[$TPCActive_z]}"/>
595 #++++++++++++++++++++++++++++ Wire Solids ++++++++++++++++++++++++++++++
599 <tube name="${_[3]}WireVert"
600 rmax="@{[0.5*$TPCWireThickness]}"
607 # Set number of wires to default to zero, when $wires_on = 0, for a low memory
608 # version. But if $wires_on = 1, calculate the number of wires on each side of each
609 # plane to be used in the for loops
611 my $NumberCornerUWires = 0;
612 my $NumberSideUWires = 0;
613 my $NumberCommonUWires = 0;
614 my $NumberCornerVWires = 0;
615 my $NumberSideVWires = 0;
616 my $NumberCommonVWires = 0;
617 my $NumberVerticalWires = 0;
621 # Number of wires in one corner
622 $NumberCornerUWires = int( $APAFrame_z/($UWirePitch/$CosUAngle) );
624 $NumberCornerVWires = int( $APAFrame_z/($VWirePitch/$CosVAngle) );
627 # Total number of wires touching one vertical (longer) side
628 # Note that the total number of wires per plane is this + another set of corner wires
629 $NumberSideUWires = int( $Uactive_y/$UWire_yint );
630 if($Pitch3mmVersion==1){ $NumberSideUWires = $NumberSideUWires-1; }
632 $NumberSideVWires = int( $Vactive_y/$VWire_yint );
634 # Number of wires per side that aren't cut off by the corner
635 $NumberCommonUWires = $NumberSideUWires - $NumberCornerUWires;
637 $NumberCommonVWires = $NumberSideVWires - $NumberCornerVWires;
639 # Number of wires on the vertical plane
640 # Since APA Active z is defined in docdb 3383 to be distance
641 # between outer vertical wires, + 1 since the floor of this
642 # division will be one under, giving the amt of spaces, not wires
643 $NumberVerticalWires = int( $Zactive_z/$XWirePitch ) + 1;
644 #$NumberVerticalWires = 960;
647 $nUchans = 2*$NumberCornerUWires;
648 $nVchans = 2*$NumberCornerVWires;
650 print $wout "$nUchans U channels\n";
651 print $wout "$nVchans V channels\n";
652 print $wout "$NumberVerticalWires Z channels per side\n";
654 print $wout "$NumberCornerUWires U corner wires\n";
655 print $wout "$NumberCommonUWires U common wires\n";
656 print $wout "$NumberCornerVWires V corner wires\n";
657 print $wout "$NumberCommonVWires V common wires\n";
661 # hard codeed number will be a factor determined from engineering spreadsheets on wire endpoints,
662 # but since that won't exist for a while, use this number to avoid overlaps
663 my $FirstUWireOffset = .55 + $G10thickness + 2*$G10thickness*$TanUAngle - $UWire_zint;
664 my $FirstVWireOffset = .5; # doesnt include a G10 board in width
666 if($Pitch3mmVersion==1){
667 my $FirstUWireOffset = .15 + $G10thickness + 2*$G10thickness*$TanUAngle - $UWire_zint;
668 my $FirstVWireOffset = .15; # doesnt include a G10 board in width
671 if($UVAngle45Option==1){$FirstVWireOffset = .7;}
674 my $FirstTopUWire_yspan =
677 + $FirstUWireOffset/$TanUAngle # walk us up to the first wire
678 + $UWire_yint*($NumberSideUWires-1) # up to the top of the top common wire
679 - $Uactive_z/$TanUAngle # back to the bottom of the top common wire
680 + $UWire_yint); # nudge up to bottom of the first top corner wire
682 my $FirstTopVWire_yspan =
685 + $FirstVWireOffset/$TanVAngle # walk us up to the first wire
686 + $VWire_yint*($NumberSideVWires-1) # up to the top of the top common wire
687 - $Vactive_z/$TanVAngle # back to the bottom of the top common wire
688 + $VWire_yint); # nudge up to bottom of the first top corner wire
691 # The corner wires for the U plane
694 for ($i = 0; $i < $NumberCornerUWires; $i++)
696 $CornerUWireLength[$i] = ($FirstUWireOffset + $i*$UWire_zint)/$SinUAngle;
699 <tube name="${_[3]}WireU$i"
700 rmax="@{[0.5*$TPCWireThickness]}"
701 z="@{[$CornerUWireLength[$i]]}"
709 $CommonUWireLength = $Uactive_z/$SinUAngle;
712 <tube name="${_[3]}WireUCommon"
713 rmax="@{[0.5*$TPCWireThickness]}"
714 z="@{[$CommonUWireLength]}"
720 for ($i = 0; $i < $NumberCornerUWires; $i++)
723 $TopCornerUWireLength[$i] = ($FirstTopUWire_yspan - $i*$UWire_yint)/$CosUAngle;
725 $j = $i + $NumberSideUWires;
728 <tube name="${_[3]}WireU$j"
729 rmax="@{[0.5*$TPCWireThickness]}"
730 z="@{[$TopCornerUWireLength[$i]]}"
741 # The corner wires for the V plane
744 for ($i = 0; $i < $NumberCornerVWires; ++$i)
746 $CornerVWireLength[$i] = ($FirstVWireOffset + $i*$VWire_zint)/$SinVAngle;
750 <tube name="${_[3]}WireV$i"
751 rmax="@{[0.5*$TPCWireThickness]}"
752 z="@{[$CornerVWireLength[$i]]}"
761 # The wire used many times in the middle of the V plane
762 # Same subtraction as U common
764 $CommonVWireLength = $Vactive_z/$SinVAngle;
767 <tube name="${_[3]}WireVCommon"
768 rmax="@{[0.5*$TPCWireThickness]}"
769 z="@{[$CommonVWireLength]}"
775 for ($i = 0; $i < $NumberCornerVWires; $i++)
778 $TopCornerVWireLength[$i] = ($FirstTopVWire_yspan - $i*$VWire_yint)/$CosVAngle;
780 $j = $i + $NumberSideVWires;
783 <tube name="${_[3]}WireV$j"
784 rmax="@{[0.5*$TPCWireThickness]}"
785 z="@{[$TopCornerVWireLength[$i]]}"
796 # Begin structure and create the vertical wire logical volume
800 <volume name="volTPCActive${_[3]}">
801 <materialref ref="LAr"/>
802 <solidref ref="${_[3]}Active"/>
811 <volume name="volTPCWireVert${_[3]}">
812 <materialref ref="Copper_Beryllium_alloy25"/>
813 <solidref ref="${_[3]}WireVert"/>
817 # Corner U wires logical volumes
818 for ($i = 0; $i < $NumberCornerUWires; ++$i)
821 <volume name="volTPCWireU$i${_[3]}">
822 <materialref ref="Copper_Beryllium_alloy25"/>
823 <solidref ref="${_[3]}WireU$i"/>
829 # Top Corner U wires logical volumes
830 for ($j = $NumberSideUWires; $j < $NumberSideUWires + $NumberCornerUWires; ++$j)
833 <volume name="volTPCWireU$j${_[3]}">
834 <materialref ref="Copper_Beryllium_alloy25"/>
835 <solidref ref="${_[3]}WireU$j"/>
841 # Common U wire logical volume, referenced many times
843 <volume name="volTPCWireUCommon${_[3]}">
844 <materialref ref="Copper_Beryllium_alloy25"/>
845 <solidref ref="${_[3]}WireUCommon"/>
850 # Corner V wires logical volumes
851 for ($i = 0; $i < $NumberCornerVWires; ++$i)
854 <volume name="volTPCWireV$i${_[3]}">
855 <materialref ref="Copper_Beryllium_alloy25"/>
856 <solidref ref="${_[3]}WireV$i"/>
862 # Top Corner V wires logical volumes
863 for ($j = $NumberSideVWires; $j < $NumberSideVWires + $NumberCornerVWires; ++$j)
866 <volume name="volTPCWireV$j${_[3]}">
867 <materialref ref="Copper_Beryllium_alloy25"/>
868 <solidref ref="${_[3]}WireV$j"/>
873 # Common V wire logical volume, referenced many times
875 <volume name="volTPCWireVCommon${_[3]}">
876 <materialref ref="Copper_Beryllium_alloy25"/>
877 <solidref ref="${_[3]}WireVCommon"/>
888 #+++++++++++++++++++++++++ Position physical wires ++++++++++++++++++++++++++
890 # ++++++++++++++++++++++ U Plane +++++++++++++++++++++++
892 # Create U plane logical volume
894 <volume name="volTPCPlaneU${_[3]}">
895 <materialref ref="LAr"/>
896 <solidref ref="${_[3]}UPlane"/>
900 print $wout "\n- Wires for U plane -\n\n";
901 print $wout " Uplane_y: $Uactive_y\n";
902 print $wout " Uplane_z: $Uactive_z\n";
908 # Starting with the bottom left corner wires:
909 # x=0 to center the wires in the plane
910 # y positioning: (-0.5*$TPCWirePlaneHeight) starts the incremental increase
911 # from the bottom of the plane, and trigonometry gives the increment
912 # z positioning: Looking at the plane from the positive x direction,
913 # (0.5*$TPCWirePlaneLength) starts the incremental increase from
914 # the lower left corner.
915 # rotation: same as common wire in code below
917 $FirstU_ypos = - $Uactive_y/2 + $FirstUWireOffset/$TanUAngle/2;
918 $FirstU_zpos = + $Uactive_z/2 - $FirstUWireOffset/2;
920 for ($i = 0; $i < $NumberCornerUWires; ++$i)
923 my $ypos = $FirstU_ypos + ($i)*0.5*$UWire_yint;
924 my $zpos = $FirstU_zpos - ($i)*0.5*$UWire_zint;
926 $pitch = ($ypos - $lastYpos) * $SinUAngle
927 - ($zpos - $lastZpos) * $CosUAngle;
931 <volumeref ref="volTPCWireU$i${_[3]}"/>
932 <position name="pos${_[3]}WireU$i" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
933 <rotation name="rUAngle$i" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
937 $topY = $ypos + ($CosUAngle*$CornerUWireLength[$i]/2);
938 $bottomY = $ypos - ($CosUAngle*$CornerUWireLength[$i]/2);
939 $edgeZ_p = $zpos + ($SinUAngle*$CornerUWireLength[$i]/2);
940 $edgeZ_m = $zpos - ($SinUAngle*$CornerUWireLength[$i]/2);
941 print $wout "U$i: ( $ypos , $zpos ) (pitch = $pitch)\n";
942 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
950 # Moving upwards to the common wires:
951 # x and z are zero to center the wires along a vertical axis
952 # y positioning: The trick is positioning the lowest common wire so that the pitch
953 # is consistent, then the increment is double the increment of
954 # the corner wires since there is no z incriment.
955 # rotation: wires in \\\\ direction, so +90deg to bring them to vertical and
956 # +UAngle counterclockwise to arrive at proper orientation
957 # Note that the counter maintains wire number (in pos. name) counting bottom to top
960 my $StartCommonUWires_ypos = $lastYpos + $UWire_yint - abs( $lastZpos )/$TanUAngle;
962 for ($i = $NumberCornerUWires; $i < $NumberSideUWires; ++$i)
965 $j = $i - $NumberCornerUWires;
966 my $ypos = $StartCommonUWires_ypos + $UWire_yint*($j);
969 if ( $ypos < $lastYpos ){ print "WARNING: y position dropped from $lastYpos (wire U$lastWnum) to $ypos (wire U$i)\n"; }
970 if ( $ypos == $lastYpos ){ print "WARNING: y position between wire U$lastWnum and U$lastWnum did not move: $ypos\n"; }
973 $pitch = ($ypos - $lastYpos) * $SinUAngle - ($zpos - $lastZpos) * $CosUAngle ;
977 <volumeref ref="volTPCWireUCommon${_[3]}"/>
978 <position name="pos${_[3]}WireU$i" unit="cm" x="0" y="@{[$ypos ]}" z="0"/>
979 <rotation name="rUAngle$i" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
983 $topY = $ypos + ($CosUAngle*$CommonUWireLength/2);
984 $bottomY = $ypos - ($CosUAngle*$CommonUWireLength/2);
985 $edgeZ_p = + ($SinUAngle*$CommonUWireLength/2);
986 $edgeZ_m = - ($SinUAngle*$CommonUWireLength/2);
987 print $wout "U$i: ( $ypos , 0 ) (pitch = $pitch)\n";
988 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
997 my $FirstTopUWire_zspan = $FirstTopUWire_yspan*$TanUAngle;
998 my $StartTopUWires_ypos = + $Uactive_y/2 - $FirstTopUWire_yspan/2;
999 my $StartTopUWires_zpos = - $Uactive_z/2 + $FirstTopUWire_zspan/2;
1001 # Finally moving to the corner wires on the top right:
1002 # x=0 to center the wires in the plane
1003 # y positioning: plug wire number into same equation
1004 # z positioning: start at z=0 and go negatively at the same z increment
1005 # rotation: same as common wire in code above
1006 # note that the counter maintains wire number shown in the position name
1008 for ($j = $NumberSideUWires; $j < $NumberSideUWires+$NumberCornerUWires; ++$j)
1011 $i = $j - $NumberSideUWires;
1013 my $ypos = $StartTopUWires_ypos + ($i)*0.5*$UWire_yint;
1014 my $zpos = $StartTopUWires_zpos - ($i)*0.5*$UWire_zint;
1017 if ( $ypos < $lastYpos ){ print "WARNING: y position dropped from $lastYpos (wire U$lastWnum) to $ypos (wire U$j)\n"; }
1018 if ( $ypos == $lastYpos ){ print "WARNING: y position between wire U$lastWnum and U$j did not move: $ypos\n"; }
1020 $pitch = ($ypos - $lastYpos) * $SinUAngle - ($zpos - $lastZpos) * $CosUAngle ;
1024 <volumeref ref="volTPCWireU$j${_[3]}"/>
1025 <position name="pos${_[3]}WireU$j" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
1026 <rotation name="rUAngle$j" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
1030 $topY = $ypos + ($CosUAngle*$TopCornerUWireLength[$i]/2);
1031 $bottomY = $ypos - ($CosUAngle*$TopCornerUWireLength[$i]/2);
1032 $edgeZ_p = $zpos + ($SinUAngle*$TopCornerUWireLength[$i]/2);
1033 $edgeZ_m = $zpos - ($SinUAngle*$TopCornerUWireLength[$i]/2);
1034 print $wout "U$j: ( $ypos , $zpos ) (pitch = $pitch)\n";
1035 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1045 # ++++++++++++++++++++++ V Plane +++++++++++++++++++++++
1047 # End U plane and create V plane logical volume
1051 <volume name="volTPCPlaneV${_[3]}">
1052 <materialref ref="LAr"/>
1053 <solidref ref="${_[3]}VPlane"/>
1056 print $wout "\n- Wires for V plane -\n\n";
1057 print $wout " Vplane_y: $Vactive_y\n";
1058 print $wout " Vplane_z: $Vactive_z\n";
1064 # Starting with the bottom right corner wires:
1065 # x=0 to center the wires in the plane
1066 # y positioning: (-0.5*$TPCWirePlaneHeight) starts the incremental increase
1067 # from the bottom of the plane, and trigonometry gives the increment
1068 # z positioning: Looking at the plane from the positive x direction,
1069 # (-0.5*$TPCWirePlaneLength) starts the incremental increase from
1070 # the lower right corner.
1071 # rotation: same as common wire in code below
1073 $FirstV_ypos = - $Vactive_y/2 + $FirstVWireOffset/$TanVAngle/2;
1074 $FirstV_zpos = - $Vactive_z/2 + $FirstVWireOffset/2;
1076 for ($i = 0; $i < $NumberCornerVWires; ++$i)
1079 my $ypos = $FirstV_ypos + ($i)*0.5*$VWire_yint;
1080 my $zpos = $FirstV_zpos + ($i)*0.5*$VWire_zint;
1084 <volumeref ref="volTPCWireV$i${_[3]}"/>
1085 <position name="pos${_[3]}WireV$i" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
1086 <rotation name="rVAngle$i" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1090 $topY = $ypos + ($CosVAngle*$CornerVWireLength[$i]/2);
1091 $bottomY = $ypos - ($CosVAngle*$CornerVWireLength[$i]/2);
1092 $edgeZ_p = $zpos + ($SinVAngle*$CornerVWireLength[$i]/2);
1093 $edgeZ_m = $zpos - ($SinVAngle*$CornerVWireLength[$i]/2);
1094 print $wout "V$i: ( $ypos , $zpos ) \n";
1095 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1103 # Moving upwards to the common wires:
1104 # x and z are zero to center the wires along a vertical axis
1105 # y positioning: Plug wire number into the same corner ypos equation
1106 # rotation: wires in //// direction, so +90deg to bring them to vertical and
1107 # --VAngle counterclockwise to arrive at proper orientation
1108 # Note that the counter maintains wire number in the position name
1110 my $StartCommonVWires_ypos = $lastYpos + $VWire_yint - abs( $lastZpos )/$TanVAngle;
1112 for ($i = $NumberCornerVWires; $i < $NumberSideVWires; ++$i)
1115 $j = $i - $NumberCornerVWires;
1116 my $ypos = $StartCommonVWires_ypos + $VWire_yint*($j);
1120 <volumeref ref="volTPCWireVCommon${_[3]}"/>
1121 <position name="pos${_[3]}WireV$i" unit="cm" x="0" y="@{[$ypos ]}" z="0"/>
1122 <rotation name="rVAngle$i" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1126 $topY = $ypos + ($CosVAngle*$CommonVWireLength/2);
1127 $bottomY = $ypos - ($CosVAngle*$CommonVWireLength/2);
1128 $edgeZ_p = + ($SinVAngle*$CommonVWireLength/2);
1129 $edgeZ_m = - ($SinVAngle*$CommonVWireLength/2);
1130 print $wout "V$i: ( $ypos , 0 ) \n";
1131 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1134 #$lastZpos = $zpos; always 0
1139 my $FirstTopVWire_zspan = $FirstTopVWire_yspan*$TanVAngle;
1140 my $StartTopVWires_ypos = + $Vactive_y/2 - $FirstTopVWire_yspan/2;
1141 my $StartTopVWires_zpos = + $Vactive_z/2 - $FirstTopVWire_zspan/2;
1143 # Finally moving to the corner wires on the top right:
1144 # x=0 to center the wires in the plane
1145 # y positioning: plug wire number into same equation
1146 # z positioning: start at z=0 and go positively at the same z increment
1147 # rotation: same as common wire in code above
1148 # note that the counter maintains wire number shown in the position name
1150 for ($j = $NumberSideVWires; $j < $NumberSideVWires+$NumberCornerVWires; ++$j)
1153 $i = $j - $NumberSideVWires;
1155 my $ypos = $StartTopVWires_ypos + ($i)*0.5*$VWire_yint;
1156 my $zpos = $StartTopVWires_zpos + ($i)*0.5*$VWire_zint;
1160 <volumeref ref="volTPCWireV$j${_[3]}"/>
1161 <position name="pos${_[3]}WireV$j" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
1162 <rotation name="rVAngle$j" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1166 $topY = $ypos + ($CosVAngle*$TopCornerVWireLength[$i]/2);
1167 $bottomY = $ypos - ($CosVAngle*$TopCornerVWireLength[$i]/2);
1168 $edgeZ_p = $zpos + ($SinVAngle*$TopCornerVWireLength[$i]/2);
1169 $edgeZ_m = $zpos - ($SinVAngle*$TopCornerVWireLength[$i]/2);
1170 print $wout "V$j: ( $ypos , $zpos ) \n";
1171 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1184 # ++++++++++++++++++++++ Z Plane +++++++++++++++++++++++
1186 # End V plane and create Z plane logical volume
1190 <volume name="volTPCPlaneZ${_[3]}">
1191 <materialref ref="LAr"/>
1192 <solidref ref="${_[3]}ZPlane"/>
1198 # This is the simplest plane, one loop creates all of the wires
1199 # x and y position at zero to center the wires
1200 # z position: moving from front of detector to back, in the positive z direction,
1201 # starting at (-0.5*$TPCWirePlaneLength), the right side looking from
1204 for ($i=0; $i<$NumberVerticalWires; ++$i)
1206 my $zpos = (-0.5*$Zactive_z) + $i*$XWirePitch + $TPCWireThickness/2;
1210 <volumeref ref="volTPCWireVert${_[3]}"/>
1211 <position name="pos${_[3]}WireZ$i" unit="cm" x="0" y="0 " z="@{[$zpos]}"/>
1212 <rotationref ref="rPlus90AboutX"/>
1224 #+++++++++++++++++++++ ^^ Position physical wires Above ^^ +++++++++++++++++++++
1226 ## make the TPC active volume extend down to the G10 for the grid
1228 my $BottomOfAPA = - $TPC_y/2 + $APAGap_y/2;
1231 $posZplane[0] = -$_[0]/2 + $APAWirePlaneSpacing - $TPCWirePlaneThickness/2;
1232 $posZplane[1] = $BottomOfAPA + $WrapCover + 4*$G10thickness + $Zactive_y/2;
1235 $posVplane[0] = $posZplane[0] + $APAWirePlaneSpacing;
1236 $posVplane[1] = $BottomOfAPA + $WrapCover + 3*$G10thickness + $Vactive_y/2;
1237 $posVplane[2] = $posZplane[2];
1239 $posUplane[0] = $posVplane[0] + $APAWirePlaneSpacing;
1240 $posUplane[1] = $BottomOfAPA + $WrapCover + 2*$G10thickness + $Uactive_y/2;
1241 $posUplane[2] = $posZplane[2];
1243 $posTPCActive[0] = $posUplane[0] + ($TPCWirePlaneThickness/2 + $TPCActive_x/2);
1244 $posTPCActive[1] = -$_[1]/2 + $TPCActive_y/2;
1245 $posTPCActive[2] = 0;
1247 #wrap up the TPC file
1249 <volume name="volTPC${_[3]}">
1250 <materialref ref="LAr"/>
1251 <solidref ref="${_[3]}"/>
1253 <volumeref ref="volTPCPlaneZ${_[3]}"/>
1254 <position name="pos${_[3]}PlaneZ" unit="cm"
1255 x="@{[$posZplane[0]]}" y="@{[$posZplane[1]]}" z="@{[$posZplane[2]]}"/>
1256 <rotationref ref="rIdentity"/>
1259 <volumeref ref="volTPCPlaneV${_[3]}"/>
1260 <position name="pos${_[3]}PlaneV" unit="cm"
1261 x="@{[$posVplane[0]]}" y="@{[$posVplane[1]]}" z="@{[$posVplane[2]]}"/>
1262 <rotationref ref="rIdentity"/>
1265 <volumeref ref="volTPCPlaneU${_[3]}"/>
1266 <position name="pos${_[3]}PlaneU" unit="cm"
1267 x="@{[$posUplane[0]]}" y="@{[$posUplane[1]]}" z="@{[$posUplane[2]]}"/>
1268 <rotationref ref="rIdentity"/>
1272 # Option to omit the active volume on the outside for the prototype.
1273 if( !($killOuterActive==1 && $_[3] eq 'Outer') ){
1276 <volumeref ref="volTPCActive${_[3]}"/>
1277 <position name="pos${_[3]}Active" unit="cm"
1278 x="@{[$posTPCActive[0]]}" y="@{[$posTPCActive[1]]}" z="@{[$posTPCActive[2]]}"/>
1279 <rotationref ref="rIdentity"/>
1292 } #end of sub gen_TPC
1296 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1297 #++++++++++++++++++++++++++++++++++++++ gen_Cryostat +++++++++++++++++++++++++++++++++++++
1298 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1303 # Create the cryostat fragment file name,
1304 # add file to list of output GDML fragments,
1306 $CRYO = "dune10kt_v4_Cryostat" . $suffix . ".gdml";
1307 push (@gdmlFiles, $CRYO);
1308 $CRYO = ">" . $CRYO;
1309 open(CRYO) or die("Could not open file $CRYO for writing");
1312 # The standard XML prefix and starting the gdml
1314 <?xml version='1.0'?>
1318 $APAFrameZSide_x = $APAFrame_x;
1319 $APAFrameZSide_y = 4*$inch;
1320 $APAFrameZSide_z = $APAFrame_z;
1322 $APAFrameYSide_x = $APAFrame_x;
1323 $APAFrameYSide_y = $APAFrame_y-2*$APAFrameZSide_y;
1324 $APAFrameYSide_z = 4*$inch;
1326 # Two outer Y supports will sandwich the light paddles
1327 $APAFrameYOuterSupport_x = ($APAFrame_x-$ArapucaOut_x)/2;
1328 $APAFrameYOuterSupport_y = $APAFrame_y-2*$APAFrameZSide_y;
1329 $APAFrameYOuterSupport_z = 4*$inch;
1331 $EdgeFrameSteelThickness = 0.12*$inch;
1332 $InnerFrameSteelThickness = 0.062*$inch;
1335 $G10BoardYSide_x = $APAFrame_x;
1336 $G10BoardYSide_y = $APAFrame_y;
1337 $G10BoardYSide_z = $G10thickness;
1339 $G10BoardZSide_x = $APAFrame_x;
1340 $G10BoardZSide_y = $G10thickness;
1341 $G10BoardZSide_z = $APAFrame_z;
1343 ##################################################################
1344 ################### Field Cage Y and Z centers ###################
1350 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.
1352 $tmp_APACenter_z = - $Argon_z/2
1353 + $UpstreamLArPadding
1355 + $k*($APAphys_z+$APAGap_z);
1356 $FC_z_center = $FC_z_center + $tmp_APACenter_z;
1358 $FC_z_center = $FC_z_center / $nAPALong;
1360 for($j=0 ; $j<$nAPAHigh ; $j++) # nAPAHigh always going to be 2
1362 $tmp_APACenter_y = - $Argon_y/2 + $SpaceAPAToFloor
1364 + $j*($APAphys_y+$APAGap_y);
1365 $FC_y_center = $FC_y_center + $tmp_APACenter_y;
1367 $FC_y_center = $FC_y_center / $nAPAHigh;
1369 # All the cryostat solids.
1372 <tube name="SourceModerator"
1373 rmax="@{[0.5*$SourceModerator_d]}"
1374 z="@{[$SourceModerator_z]}"
1378 <box name="Cryostat" lunit="cm"
1379 x="@{[$Cryostat_x]}"
1380 y="@{[$Cryostat_y]}"
1381 z="@{[$Cryostat_z]}"/>
1382 <box name="ArgonInterior" lunit="cm"
1386 <box name="FieldCageOut" lunit="cm"
1390 <box name="FieldCageIn" lunit="cm"
1394 <subtraction name="FieldCage">
1395 <first ref="FieldCageOut"/>
1396 <second ref="FieldCageIn"/>
1398 <box name="GaseousArgon" lunit="cm"
1400 y="@{[$HeightGaseousAr]}"
1402 <subtraction name="SteelShell">
1403 <first ref="Cryostat"/>
1404 <second ref="ArgonInterior"/>
1406 <box name="Cathode" lunit="cm"
1409 z="@{[$Cathode_z]}"/>
1411 <box name="ArapucaOut" lunit="cm"
1412 x="@{[$ArapucaOut_x]}"
1413 y="@{[$ArapucaOut_y]}"
1414 z="@{[$ArapucaOut_z]}"/>
1416 <box name="ArapucaIn" lunit="cm"
1417 x="@{[$ArapucaIn_x]}"
1418 y="@{[$ArapucaIn_y]}"
1419 z="@{[$ArapucaIn_z]}"/>
1421 <subtraction name="ArapucaWalls0">
1422 <first ref="ArapucaOut"/>
1423 <second ref="ArapucaIn"/>
1424 <positionref ref="posArapucaSub0"/>
1426 <subtraction name="ArapucaWalls1">
1427 <first ref="ArapucaWalls0"/>
1428 <second ref="ArapucaIn"/>
1429 <positionref ref="posArapucaSub1"/>
1431 <subtraction name="ArapucaWalls2">
1432 <first ref="ArapucaWalls1"/>
1433 <second ref="ArapucaIn"/>
1434 <positionref ref="posArapucaSub2"/>
1436 <subtraction name="ArapucaWalls">
1437 <first ref="ArapucaWalls2"/>
1438 <second ref="ArapucaIn"/>
1439 <positionref ref="posArapucaSub3"/>
1442 <box name="ArapucaAcceptanceWindow" lunit="cm"
1443 x="@{[$ArapucaAcceptanceWindow_x]}"
1444 y="@{[$ArapucaAcceptanceWindow_y]}"
1445 z="@{[$ArapucaAcceptanceWindow_z]}"/>
1447 <box name="APAFrameYSideHollow" lunit="cm"
1448 x="@{[$APAFrameYSide_x-2*$EdgeFrameSteelThickness]}"
1449 y="@{[$APAFrameYSide_y-2*$EdgeFrameSteelThickness]}"
1450 z="@{[$APAFrameYSide_z]}"/>
1451 <box name="APAFrameYSideShell" lunit="cm"
1452 x="@{[$APAFrameYSide_x]}"
1453 y="@{[$APAFrameYSide_y]}"
1454 z="@{[$APAFrameYSide_z]}"/>
1455 <subtraction name="APAFrameYSide">
1456 <first ref="APAFrameYSideShell"/>
1457 <second ref="APAFrameYSideHollow"/>
1458 <positionref ref="posCenter"/>
1459 <rotationref ref="rIdentity"/>
1462 <box name="APAFrameZSideHollow" lunit="cm"
1463 x="@{[$APAFrameZSide_x-2*$EdgeFrameSteelThickness]}"
1464 y="@{[$APAFrameZSide_y-2*$EdgeFrameSteelThickness]}"
1465 z="@{[$APAFrameZSide_z]}"/>
1466 <box name="APAFrameZSideShell" lunit="cm"
1467 x="@{[$APAFrameZSide_x]}"
1468 y="@{[$APAFrameZSide_y]}"
1469 z="@{[$APAFrameZSide_z]}"/>
1470 <subtraction name="APAFrameZSide">
1471 <first ref="APAFrameZSideShell"/>
1472 <second ref="APAFrameZSideHollow"/>
1473 <positionref ref="posCenter"/>
1474 <rotationref ref="rIdentity"/>
1477 <box name="APAFrameYOuterSupport" lunit="cm"
1478 x="@{[$EdgeFrameSteelThickness]}"
1479 y="@{[$APAFrameYOuterSupport_y]}"
1480 z="@{[$APAFrameYOuterSupport_z]}"/>
1483 <box name="G10BoardYSideCenterSeg" lunit="cm"
1484 x="@{[$G10BoardYSide_x]}"
1485 y="@{[$G10BoardYSide_y]}"
1486 z="@{[$G10BoardYSide_z]}"/>
1488 <box name="G10BoardZSideCenterSeg" lunit="cm"
1489 x="@{[$G10BoardZSide_x]}"
1490 y="@{[$G10BoardZSide_y]}"
1491 z="@{[$G10BoardZSide_z]}"/>
1496 # Cryostat structure
1499 <volume name="volSteelShell">
1500 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1501 <solidref ref="SteelShell" />
1503 <volume name="volSourceModerator">
1504 <materialref ref="Delrin"/>
1505 <solidref ref="SourceModerator"/>
1507 <volume name="volFieldCage">
1508 <materialref ref="ALUMINUM_Al"/>
1509 <solidref ref="FieldCage"/>
1511 <volume name="volGaseousArgon">
1512 <materialref ref="ArGas"/>
1513 <solidref ref="GaseousArgon"/>
1515 <volume name="volCathode">
1516 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1517 <solidref ref="Cathode" />
1521 for($i=0 ; $i<$nAPAs ; $i++){
1522 for($p=0 ; $p<10 ; $p++){
1523 for($ncuts=0 ; $ncuts<4; $ncuts++){
1525 <volume name="volOpDetSensitive_$i\-$p\-$ncuts">
1526 <materialref ref="Acrylic"/>
1527 <solidref ref="ArapucaAcceptanceWindow"/>
1534 for($i=0 ; $i<$nAPAs ; $i++){
1535 for($p=0 ; $p<10 ; $p++){
1537 <volume name="volArapuca_$i\-$p">
1538 <materialref ref="G10"/>
1539 <solidref ref="ArapucaWalls"/>
1548 <volume name="volAPAFrameYSide">
1549 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1550 <solidref ref="APAFrameYSide"/>
1553 <volume name="volAPAFrameZSide">
1554 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1555 <solidref ref="APAFrameZSide"/>
1558 <volume name="volAPAFrameYOuterSupport">
1559 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1560 <solidref ref="APAFrameYOuterSupport"/>
1563 <volume name="volG10BoardYSideCenterSeg">
1564 <materialref ref="G10"/>
1565 <solidref ref="G10BoardYSideCenterSeg"/>
1568 <volume name="volG10BoardZSideCenterSeg">
1569 <materialref ref="G10"/>
1570 <solidref ref="G10BoardZSideCenterSeg"/>
1573 <volume name="volCryostat">
1574 <materialref ref="LAr" />
1575 <solidref ref="Cryostat" />
1577 <volumeref ref="volGaseousArgon"/>
1578 <position name="posGaseousArgon" unit="cm" x="0" y="@{[$Argon_y/2-$HeightGaseousAr/2]}" z="0"/>
1581 <volumeref ref="volSourceModerator"/>
1582 <position name="posSourceModerator" unit="cm"
1583 x="@{[$Source_x_center]}"
1584 y="@{[$Source_y_center]}"
1585 z="@{[$Source_z_center]}"/>
1586 <rotationref ref="rPlus90AboutX"/>
1589 <volumeref ref="volFieldCage"/>
1590 <position name="posFieldCage" unit="cm"
1591 x="@{[$FC_x_center]}"
1592 y="@{[$FC_y_center]}"
1593 z="@{[$FC_z_center]}"/>
1596 <volumeref ref="volSteelShell"/>
1597 <position name="posSteelShell" unit="cm" x="0" y="0" z="0"/>
1601 # nested for loops to place the non-rotated AND rotated volTPC
1602 # x loop rotation: There are six drift volumes. Looking into the
1603 # detector from incident direction, and counting from right (-x) to
1604 # left (+x), odd number volumes need to be rotated 180deg about Y in
1605 # order for the cathode to be on the right of the APA.
1612 for($k=0 ; $k<$nAPALong ; $k++)
1614 $APACenter_z = - $Argon_z/2
1615 + $UpstreamLArPadding
1617 + $k*($APAphys_z+$APAGap_z);
1620 for($j=0 ; $j<$nAPAHigh ; $j++) # nAPAHigh always going to be 2
1621 { # $j=0 for bottom APAs
1623 $APACenter_y = - $Argon_y/2 + $SpaceAPAToFloor
1625 + $j*($APAphys_y+$APAGap_y);
1628 if( $workspace == 0 )
1631 for($i=0 ; $i<$nAPAWide ; $i++)
1635 $APACenter_x = - $Argon_x/2
1636 + $SpaceAPAToCryoWall + $APA_UtoU_x/2 + $TPCWirePlaneThickness/2
1639 $CPA_x = $APACenter_x + $CPAToAPA;
1642 place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, $j);
1643 place_OpDets($APACenter_x, $APACenter_y, $APACenter_z, $apa_i);
1644 $tpc_0 = 2*$apa_i+0;
1645 $tpc_1 = 2*$apa_i+1;
1648 $SelectTPC_0 = "Inner";
1649 $SelectTPC_1 = "Inner";
1650 $TPC_0_x = $TPCInner_x;
1651 $TPC_1_x = $TPCInner_x;
1652 $rot_0 = "rPlus180AboutY";
1653 $rot_1 = "rIdentity";
1654 if($i == 0) { $SelectTPC_0 = "Outer"; $TPC_0_x = $TPCOuter_x; }
1655 if($i == $nAPAWide-1) { $SelectTPC_1 = "Outer"; $TPC_1_x = $TPCOuter_x; }
1656 if($j == 0) { $rot_0 = "rPlus180AboutXPlus180AboutY";
1657 $rot_1 = "rPlus180AboutX"; } #put the readout end at the bottom for bottom APAs
1664 <volumeref ref="volTPC$SelectTPC_0"/>
1665 <position name="posTPC\-$tpc_0" unit="cm"
1666 x="@{[$APACenter_x - $APAFrame_x/2 - $TPC_0_x/2]}"
1667 y="@{[$APACenter_y]}"
1668 z="@{[$APACenter_z]}"/>
1669 <rotationref ref="$rot_0"/>
1672 <volumeref ref="volTPC$SelectTPC_1"/>
1673 <position name="posTPC\-$tpc_1" unit="cm"
1674 x="@{[$APACenter_x + $APAFrame_x/2 + $TPC_1_x/2]}"
1675 y="@{[$APACenter_y]}"
1676 z="@{[$APACenter_z]}"/>
1677 <rotationref ref="$rot_1"/>
1683 if( $i < $nAPAWide - 1 ){ # avoid placeing the last row of CPAs since the APAs are on the outside
1688 <volumeref ref="volCathode"/>
1689 <position name="posCathode\-$cpa_i" unit="cm"
1691 y="@{[$APACenter_y]}"
1692 z="@{[$APACenter_z]}"/>
1693 <rotationref ref="rIdentity"/>
1703 } # end if not the smaller workspace
1706 # Make the workspace have only one center APA with CPAs and the full drift on either side
1707 elsif( $workspace == 1 || $workspace==2 ){
1710 $CPA_0_x = $APACenter_x - $CPAToAPA;
1711 $CPA_1_x = $APACenter_x + $CPAToAPA;
1714 place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, $j);
1715 place_OpDets($APACenter_x, $APACenter_y, $APACenter_z, $apa_i);
1717 $tpc_0 = 2*$apa_i+0;
1718 $tpc_1 = 2*$apa_i+1;
1721 $rot_0 = "rPlus180AboutY";
1722 $rot_1 = "rIdentity";
1723 if($j == 0) { $rot_0 = "rPlus180AboutXPlus180AboutY";
1724 $rot_1 = "rPlus180AboutX"; } #put the readout end at the bottom for bottom APAs
1729 <volumeref ref="volTPCInner"/>
1730 <position name="posTPC\-$tpc_0" unit="cm"
1731 x="@{[$APACenter_x - $APAFrame_x/2 - $TPCInner_x/2]}"
1732 y="@{[$APACenter_y]}"
1733 z="@{[$APACenter_z]}"/>
1734 <rotationref ref="$rot_0"/>
1737 <volumeref ref="volTPCInner"/>
1738 <position name="posTPC\-$tpc_1" unit="cm"
1739 x="@{[$APACenter_x + $APAFrame_x/2 + $TPCInner_x/2]}"
1740 y="@{[$APACenter_y]}"
1741 z="@{[$APACenter_z]}"/>
1742 <rotationref ref="$rot_1"/>
1746 <volumeref ref="volCathode"/>
1747 <position name="posCathode\-$apa_i-0" unit="cm"
1749 y="@{[$APACenter_y]}"
1750 z="@{[$APACenter_z]}"/>
1751 <rotationref ref="rIdentity"/>
1754 <volumeref ref="volCathode"/>
1755 <position name="posCathode\-$apa_i-1" unit="cm"
1757 y="@{[$APACenter_y]}"
1758 z="@{[$APACenter_z]}"/>
1759 <rotationref ref="rIdentity"/>
1764 } # if the smaller workspace
1783 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1784 #++++++++++++++++++++++++++++++++++++ place_OpDets +++++++++++++++++++++++++++++++++++++++
1785 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1790 $APACenter_x = $_[0];
1791 $APACenter_y = $_[1];
1792 $APACenter_z = $_[2];
1795 # Alternate the paddle orientations
1796 if ( $apa_i % 2 == 0 ) {
1798 $posAra_x = ($APACenter_x+0.5*$ArapucaOut_x-0.5*$ArapucaAcceptanceWindow_x-0.1);
1800 $rot = "rPlus180AboutY";
1801 $posAra_x = ($APACenter_x-0.5*$ArapucaOut_x+0.5*$ArapucaAcceptanceWindow_x+0.1);
1805 for ($paddle = 0; $paddle<$nLightPaddlesPerAPA; $paddle++)
1808 # All Light Paddle centers will have the same
1809 # X coordinate as the center of the current APA
1810 # Z coordinate as the current TPC pair
1811 # The Y coordinate must be looped over:
1813 #the multiplication by j here is a temporary dirty trick to get around some strange behavior
1815 $Paddle_Y = $APACenter_y
1817 + $j*$FrameToPaddleSpace
1818 + (1-$j)*($ArapucaOut_y/2 + $APAFrameZSide_y)
1819 + $PaddleYInterval*$paddle;
1823 <volumeref ref="volArapuca_$apa_i\-$paddle"/>
1824 <position name="posArapuca$apa_i\-$paddle\-TPC\-$i\-$j\-$k" unit="cm"
1825 x="@{[$APACenter_x]}"
1827 z="@{[$APACenter_z]}"/>
1828 <rotationref ref="$rot"/>
1833 for($nwindow=0 ; $nwindow<4; $nwindow++){
1836 <volumeref ref="volOpDetSensitive_$apa_i\-$paddle\-$nwindow"/>
1837 <position name="posOpArapuca$apa_i\-$paddle\-$nwindow\-TPC\-$i\-$j\-$k" unit="cm"
1840 z="@{[$list_pos[$nwindow]+$APACenter_z]}"/>
1841 <rotationref ref="$rot"/>
1844 }#end nwindow for-loop
1845 }#end Paddle for-loop
1851 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1852 #++++++++++++++++++++++++++++++++++++++ place_APA ++++++++++++++++++++++++++++++++++++++++
1853 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1856 # Must be called only within gen_Cryostat(),
1859 # $_[0] = x APA physical center
1860 # $_[1] = y APA physical center
1861 # $_[2] = z APA physical center
1862 # $_[3] = APA number
1863 # $_[4] = 0 for APA with readout on bottom
1864 # 1 for APA with readout on top
1871 ####################################################################
1872 ################# APA Frame and Paddle Dimensions ##################
1874 # The center passed to this function is the physical APA center,
1875 # which is not quite the frame's center, since there are more boards
1876 # at the bottom. Transform them:
1878 $APAFrameCenter_x = $_[0];
1879 $APAFrameCenter_z = $_[2];
1881 # The bottom APAs are upside down relative to how the TPC is initially generated,
1882 # and the center needs to be slightly shifted since there is extra G10 on the
1883 # end that doesn't read out.
1885 if($_[4]==1) # top APAs
1887 $APAFrameCenter_y = $_[1] - $APAphys_y/2
1888 + $WrapCover + 4*$G10thickness
1891 elsif($_[4]==0) # bottom APAs
1893 $APAFrameCenter_y = $_[1] + $APAphys_y/2
1894 - $WrapCover - 4*$G10thickness
1897 else{ print "APA not labeled as top or bottom"; }
1899 $APAFrameZSide_x = $APAFrame_x;
1900 $APAFrameZSide_y = 4*$inch;
1901 $APAFrameZSide_z = $APAFrame_z;
1903 $APAFrameYSide_x = $APAFrame_x;
1904 $APAFrameYSide_y = $APAFrame_y-2*$APAFrameZSide_y;
1905 $APAFrameYSide_z = 4*$inch;
1907 # Two outer Y supports will sandwich the light paddles
1908 $APAFrameYOuterSupport_x = ($APAFrame_x-$ArapucaOut_x)/2;
1909 $APAFrameYOuterSupport_y = $APAFrame_y-2*$APAFrameZSide_y;
1910 $APAFrameYOuterSupport_z = 4*$inch;
1912 # if there were an inner support to fill the hole
1913 $APAFrameYInnerSupport_x = $ArapucaOut_x;
1915 $EdgeFrameSteelThickness = 0.12*$inch;
1916 $InnerFrameSteelThickness = 0.062*$inch;
1919 $G10BoardYSide_x = $APAFrame_x;
1920 $G10BoardYSide_y = $APAFrame_y;
1921 $G10BoardYSide_z = $G10thickness;
1923 $G10BoardZSide_x = $APAFrame_x;
1924 $G10BoardZSide_y = $G10thickness;
1925 $G10BoardZSide_z = $APAFrame_z;
1927 if($_[4]==1) # top APAs
1929 $posG10ZSideZ_y = $APAFrameCenter_y - $APAFrame_y/2 - (0+.5)*($G10BoardZSide_y);
1930 $posG10ZSideV_y = $APAFrameCenter_y - $APAFrame_y/2 - (1+.5)*($G10BoardZSide_y);
1931 $posG10ZSideU_y = $APAFrameCenter_y - $APAFrame_y/2 - (2+.5)*($G10BoardZSide_y);
1932 $posG10ZSideGrid_y = $APAFrameCenter_y - $APAFrame_y/2 - (3+.5)*($G10BoardZSide_y);
1934 elsif($_[4]==0) # bottom APAs
1936 $posG10ZSideZ_y = $APAFrameCenter_y + $APAFrame_y/2 + (0+.5)*($G10BoardZSide_y);
1937 $posG10ZSideV_y = $APAFrameCenter_y + $APAFrame_y/2 + (1+.5)*($G10BoardZSide_y);
1938 $posG10ZSideU_y = $APAFrameCenter_y + $APAFrame_y/2 + (2+.5)*($G10BoardZSide_y);
1939 $posG10ZSideGrid_y = $APAFrameCenter_y + $APAFrame_y/2 + (3+.5)*($G10BoardZSide_y);
1941 else{ print "APA not labeled as top or bottom"; }
1943 # First put in the frame
1947 # <volumeref ref="volAPAFrameYOuterSupport\-$APA_i"/>
1948 # <position name="posAPAFrameYOuterSupportNeg\-$APA_i" unit="cm"
1949 # x="$APAFrameCenter_x - ($APAFrameYOuterSupport_x + $APAFrameYInnerSupport_x/2 - $EdgeFrameSteelThickness/2)"
1950 # y="$APAFrameCenter_y"
1951 # z="$APAFrameCenter_z"/>
1952 # <rotationref ref="rIdentity"/>
1955 # <volumeref ref="volAPAFrameYOuterSupport\-$APA_i"/>
1956 # <position name="posAPAFrameYOuterSupportPos\-$APA_i" unit="cm"
1957 # x="$APAFrameCenter_x + ($APAFrameYOuterSupport_x + $APAFrameYInnerSupport_x/2 - $EdgeFrameSteelThickness/2)"
1958 # y="$APAFrameCenter_y"
1959 # z="$APAFrameCenter_z"/>
1960 # <rotationref ref="rIdentity"/>
1966 <volumeref ref="volAPAFrameYSide"/>
1967 <position name="posAPAFrameYSideNeg\-$APA_i" unit="cm"
1968 x="@{[$APAFrameCenter_x]}"
1969 y="@{[$APAFrameCenter_y]}"
1970 z="@{[$APAFrameCenter_z - $APAFrame_z/2 + $APAFrameYSide_z/2]}"/>
1971 <rotationref ref="rIdentity"/>
1974 <volumeref ref="volAPAFrameYSide"/>
1975 <position name="posAPAFrameYSidePos\-$APA_i" unit="cm"
1976 x="@{[$APAFrameCenter_x]}"
1977 y="@{[$APAFrameCenter_y]}"
1978 z="@{[$APAFrameCenter_z + $APAFrame_z/2 - $APAFrameYSide_z/2]}"/>
1979 <rotationref ref="rIdentity"/>
1982 <volumeref ref="volAPAFrameZSide"/>
1983 <position name="posAPAFrameZSidePos\-$APA_i" unit="cm"
1984 x="@{[$APAFrameCenter_x]}"
1985 y="@{[$APAFrameCenter_y + $APAFrame_y/2 - $APAFrameZSide_y/2]}"
1986 z="@{[$APAFrameCenter_z]}"/>
1987 <rotationref ref="rIdentity"/>
1990 <volumeref ref="volAPAFrameZSide"/>
1991 <position name="posAPAFrameZSideNeg\-$APA_i" unit="cm"
1992 x="@{[$APAFrameCenter_x]}"
1993 y="@{[$APAFrameCenter_y - $APAFrame_y/2 + $APAFrameZSide_y/2]}"
1994 z="@{[$APAFrameCenter_z]}"/>
1995 <rotationref ref="rIdentity"/>
1999 <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2000 - Add the *parts* of the G10 boards that exist directly in volCryostat.
2001 - There are two boards on each the up and downstream end,
2002 one each to wrap the U and V views around the APA frame
2003 - There are 4 on the bottom which anchor the U V and Z wires and the grid plane
2004 - The rest of the parts of the G10 boards must be placed directly in volTPC -->
2007 <volumeref ref="volG10BoardYSideCenterSeg"/>
2008 <position name="posG10BoardYSideCenterSeg\-Vup\-$APA_i" unit="cm"
2009 x="@{[$APAFrameCenter_x]}"
2010 y="@{[$APAFrameCenter_y]}"
2011 z="@{[$APAFrameCenter_z - $APAFrame_z/2 - (0+.5)*($G10BoardYSide_z)]}"/>
2012 <rotationref ref="rIdentity"/>
2015 <volumeref ref="volG10BoardYSideCenterSeg"/>
2016 <position name="posG10BoardYSideCenterSeg\-Uup\-$APA_i" unit="cm"
2017 x="@{[$APAFrameCenter_x]}"
2018 y="@{[$APAFrameCenter_y]}"
2019 z="@{[$APAFrameCenter_z - $APAFrame_z/2 - (1+.5)*($G10BoardYSide_z)]}"/>
2020 <rotationref ref="rIdentity"/>
2024 <volumeref ref="volG10BoardYSideCenterSeg"/>
2025 <position name="posG10BoardYSideCenterSeg\-Vdown\-$APA_i" unit="cm"
2026 x="@{[$APAFrameCenter_x]}"
2027 y="@{[$APAFrameCenter_y]}"
2028 z="@{[$APAFrameCenter_z + $APAFrame_z/2 + (0+.5)*($G10BoardYSide_z)]}"/>
2029 <rotationref ref="rIdentity"/>
2032 <volumeref ref="volG10BoardYSideCenterSeg"/>
2033 <position name="posG10BoardYSideCenterSeg\-Udown\-$APA_i" unit="cm"
2034 x="@{[$APAFrameCenter_x]}"
2035 y="@{[$APAFrameCenter_y]}"
2036 z="@{[$APAFrameCenter_z + $APAFrame_z/2 + (1+.5)*($G10BoardYSide_z)]}"/>
2037 <rotationref ref="rIdentity"/>
2041 <volumeref ref="volG10BoardZSideCenterSeg"/>
2042 <position name="posG10BoardZSideCenterSeg\-Z\-$APA_i" unit="cm"
2043 x="@{[$APAFrameCenter_x]}"
2044 y="@{[$posG10ZSideZ_y]}"
2045 z="@{[$APAFrameCenter_z]}"/>
2046 <rotationref ref="rIdentity"/>
2049 <volumeref ref="volG10BoardZSideCenterSeg"/>
2050 <position name="posG10BoardZSideCenterSeg\-V\-$APA_i" unit="cm"
2051 x="@{[$APAFrameCenter_x]}"
2052 y="@{[$posG10ZSideV_y]}"
2053 z="@{[$APAFrameCenter_z]}"/>
2054 <rotationref ref="rIdentity"/>
2057 <volumeref ref="volG10BoardZSideCenterSeg"/>
2058 <position name="posG10BoardZSideCenterSeg\-U\-$APA_i" unit="cm"
2059 x="@{[$APAFrameCenter_x]}"
2060 y="@{[$posG10ZSideU_y]}"
2061 z="@{[$APAFrameCenter_z]}"/>
2062 <rotationref ref="rIdentity"/>
2065 <volumeref ref="volG10BoardZSideCenterSeg"/>
2066 <position name="posG10BoardZSideCenterSeg\-Grid\-$APA_i" unit="cm"
2067 x="@{[$APAFrameCenter_x]}"
2068 y="@{[$posG10ZSideGrid_y]}"
2069 z="@{[$APAFrameCenter_z]}"/>
2070 <rotationref ref="rIdentity"/>
2081 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2082 #+++++++++++++++++++++++++++++++++++++ gen_Enclosure +++++++++++++++++++++++++++++++++++++
2083 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2088 # Create the detector enclosure fragment file name,
2089 # add file to list of output GDML fragments,
2091 $ENCL = "dune10kt_v4_DetEnclosure" . $suffix . ".gdml";
2092 push (@gdmlFiles, $ENCL);
2093 $ENCL = ">" . $ENCL;
2094 open(ENCL) or die("Could not open file $ENCL for writing");
2097 # The standard XML prefix and starting the gdml
2099 <?xml version='1.0'?>
2104 # All the detector enclosure solids.
2108 <box name="FoamPadBlock" lunit="cm"
2109 x="@{[$Cryostat_x + 2*$FoamPadding]}"
2110 y="@{[$Cryostat_y + 2*$FoamPadding]}"
2111 z="@{[$Cryostat_z + 2*$FoamPadding]}" />
2113 <box name="FoamPadInner" lunit="cm"
2114 x="@{[$Cryostat_x + 0.01]}"
2115 y="@{[$Cryostat_y + 0.01]}"
2116 z="@{[$Cryostat_z + 0.01]}" />
2118 <subtraction name="FoamPadding">
2119 <first ref="FoamPadBlock"/>
2120 <second ref="FoamPadInner"/>
2121 <positionref ref="posCenter"/>
2124 <box name="SteelSupportBlock" lunit="cm"
2125 x="@{[$Cryostat_x + 2*$FoamPadding + 2*$SteelSupport_x]}"
2126 y="@{[$Cryostat_y + 2*$FoamPadding + 2*$SteelSupport_y]}"
2127 z="@{[$Cryostat_z + 2*$FoamPadding + 2*$SteelSupport_z]}" />
2129 <box name="SteelSupportInner" lunit="cm"
2130 x="@{[$Cryostat_x + 2*$FoamPadding + 0.01]}"
2131 y="@{[$Cryostat_y + 2*$FoamPadding + 0.01]}"
2132 z="@{[$Cryostat_z + 2*$FoamPadding + 0.01]}" />
2134 <subtraction name="SteelSupport">
2135 <first ref="SteelSupportBlock"/>
2136 <second ref="SteelSupportInner"/>
2137 <positionref ref="posCenter"/>
2140 <box name="DetEnclosure" lunit="cm"
2141 x="@{[$DetEncWidth]}"
2142 y="@{[$DetEncHeight]}"
2143 z="@{[$DetEncLength]}"/>
2150 # Detector enclosure structure
2153 <volume name="volFoamPadding">
2154 <materialref ref="FD_foam"/>
2155 <solidref ref="FoamPadding"/>
2158 <volume name="volSteelSupport">
2159 <materialref ref="AirSteelMixture"/>
2160 <solidref ref="SteelSupport"/>
2163 <volume name="volDetEnclosure">
2164 <materialref ref="Air"/>
2165 <solidref ref="DetEnclosure"/>
2168 <volumeref ref="volFoamPadding"/>
2169 <positionref ref="posCryoInDetEnc"/>
2172 <volumeref ref="volSteelSupport"/>
2173 <positionref ref="posCryoInDetEnc"/>
2176 <volumeref ref="volCryostat"/>
2177 <positionref ref="posCryoInDetEnc"/>
2196 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2197 #+++++++++++++++++++++++++++++++++++++++ gen_World +++++++++++++++++++++++++++++++++++++++
2198 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2203 # Create the WORLD fragment file name,
2204 # add file to list of output GDML fragments,
2206 $WORLD = "dune10kt_v4_World" . $suffix . ".gdml";
2207 push (@gdmlFiles, $WORLD);
2208 $WORLD = ">" . $WORLD;
2209 open(WORLD) or die("Could not open file $WORLD for writing");
2212 # The standard XML prefix and starting the gdml
2214 <?xml version='1.0'?>
2219 # All the World solids.
2222 <box name="World" lunit="cm"
2223 x="@{[$DetEncWidth+2*$RockThickness]}"
2224 y="@{[$DetEncHeight+2*$RockThickness]}"
2225 z="@{[$DetEncLength+2*$RockThickness]}"/>
2232 <volume name="volWorld" >
2233 <materialref ref="DUSEL_Rock"/>
2234 <solidref ref="World"/>
2237 <volumeref ref="volDetEnclosure"/>
2238 <position name="posDetEnclosure" unit="cm" x="@{[$OriginXSet]}" y="@{[$OriginYSet]}" z="@{[$OriginZSet]}"/>
2246 # make_gdml.pl will take care of <setup/>
2253 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2254 #++++++++++++++++++++++++++++++++++++ write_fragments ++++++++++++++++++++++++++++++++++++
2255 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2257 sub write_fragments()
2259 # This subroutine creates an XML file that summarizes the the subfiles output
2260 # by the other sub routines - it is the input file for make_gdml.pl which will
2261 # give the final desired GDML file. Specify its name with the output option.
2262 # (you can change the name when running make_gdml)
2264 # This code is taken straigh from the similar MicroBooNE generate script, Thank you.
2266 if ( ! defined $output )
2268 $output = "-"; # write to STDOUT
2271 # Set up the output file.
2272 $OUTPUT = ">" . $output;
2273 open(OUTPUT) or die("Could not open file $OUTPUT");
2276 <?xml version='1.0'?>
2278 <!-- Input to Geometry/gdml/make_gdml.pl; define the GDML fragments
2279 that will be zipped together to create a detector description.
2286 <!-- These files contain GDML <constant></constant>
2287 blocks. They are read in separately, so they can be
2288 interpreted into the remaining GDML. See make_gdml.pl for
2294 foreach $filename (@defFiles)
2297 <filename> $filename </filename>
2307 <!-- The GDML file fragments to be zipped together. -->
2311 foreach $filename (@gdmlFiles)
2314 <filename> $filename </filename>
2330 # run the sub routines that generate the fragments
2332 gen_Define(); # generates definitions at beginning of GDML
2333 gen_Materials(); # generates materials to be used
2336 gen_TPC( $TPCInner_x, $TPC_y, $TPC_z, 'Inner');
2337 gen_TPC( $TPCOuter_x, $TPC_y, $TPC_z, 'Outer');
2341 gen_Cryostat(); # places (2*nAPAWide x nAPAHigh x nAPALong) volTPC,
2342 # half rotated 180 about Y
2343 gen_Enclosure(); # places two cryostats and concrete volumes
2345 gen_World(); # places the enclosure among DUSEL Rock
2348 write_fragments(); # writes the XML input for make_gdml.pl
2349 # which zips together the final GDML