5 # contact tylerdalion@gmail.com for any GDML/generate questions
6 # I would love to help!
8 # Each subroutine generates a fragment GDML file, and the last subroutine
9 # creates an XML file that make_gdml.pl will use to appropriately arrange
10 # the fragment GDML files to create the final desired DUNE GDML file,
11 # to be named by make_gdml output command
13 # If you are playing with different geometries, you can use the
14 # suffix command to help organize your work.
16 # trj update for iceberg
23 Math::BigFloat->precision(-16);
25 open(my $wout, '>', 'gdmlWireCenters.txt');
27 GetOptions( "help|h" => \$help,
28 "suffix|s:s" => \$suffix,
29 "output|o:s" => \$output,
30 "wires|w:s" => \$wires,
31 "protoDune|p:s" => \$protoDune,
32 "workspace|k:s" => \$workspace);
36 # If the user requested help, print the usage notes and exit.
41 if ( ! defined $suffix )
43 # The user didn't supply a suffix, so append nothing to the file
49 # Otherwise, stick a "-" before the suffix, so that a suffix of
50 # "test" applied to filename.gdml becomes "filename-test.gdml".
51 $suffix = "-" . $suffix;
56 if ( ! defined $workspace )
59 if ( ! defined $protoDune )
62 print "\t\tCreating full geometry.\n";
64 elsif ( $protoDune == 1 )
66 print "\t\tCreating rough version of protoDUNE.\n";
69 elsif ( $workspace == 1)
71 print "\t\tCreating smaller (1x2x2-APA) workspace geometry.\n";
73 elsif ( $workspace == 2)
75 print "\t\tCreating 1x2x6-APA geometry.\n";
77 elsif ( $workspace == 3)
79 print "\t\tCreating Iceberg geometry.\n";
82 # set wires on to be the default, unless given an input by the user
83 $wires_on = 1; # 1=on, 0=off
93 # options for different parameters
99 #++++++++++++++++++++++++ Begin defining variables +++++++++++++++++++++++++
101 ## The GDML is build from the inside out to avoid overlaps, but that means
102 ## that the larger dimensions (such as the cryostat dimensions) are calculated
103 ## to be slightly different than the parameters calculated and reported by
104 ## engineers. All of this error is within reason and for the better, since
105 ## we don't want this Geometry to be overly complex or long.
110 ##################################################################
111 ##################### Wire Plane Parameters ######################
114 $UWirePitch = 0.4667;
115 $VWirePitch = 0.4667;
119 $nZChannelsPerAPA = 480;
121 # dune10kt 3mm version
122 if($Pitch3mmVersion==1){
126 $nZChannelsPerAPA = 2*(229.44/0.3 + 1);
129 # dune10kt ~45 deg UV wires version
130 if($UVAngle45Option==1){
147 $SinUAngle = sin( deg2rad($UAngle) );
148 $CosUAngle = cos( deg2rad($UAngle) );
149 $TanUAngle = tan( deg2rad($UAngle) );
151 $SinVAngle = sin( deg2rad($VAngle) );
152 $CosVAngle = cos( deg2rad($VAngle) );
153 $TanVAngle = tan( deg2rad($VAngle) );
155 $UWire_yint = $UWirePitch/$SinUAngle;
156 $UWire_zint = $UWirePitch/$CosUAngle;
158 $VWire_yint = $VWirePitch/$SinVAngle;
159 $VWire_zint = $VWirePitch/$CosVAngle;
161 $TPCWireThickness = 0.015;
163 $TPCWirePlaneThickness = $TPCWireThickness;
164 #height and length defined lower
168 ##################################################################
169 ################### Cryostat/APA parameters ######################
175 $nAPAs = $nAPAWide*$nAPAHigh*$nAPALong;
178 $G10thickness = $inch/8;
179 $WrapCover = $inch/16;
181 $SpaceAPAToCryoWall = 15;
182 $SpaceAPAToFloor = 59.4 - 10.2; # 10.2cm just adjusts for how spaces are reported
183 $SpaceAPAToTopLAr = 50.9 - 10.2;
184 $UpstreamLArPadding = 311.4 - 10.2;
185 $DownstreamLArPadding = 59.4 - 10.2;
188 $SpaceAPAToCryoWall = 20;
189 $SpaceAPAToFloor = 45;
190 $SpaceAPAToTopLAr = 45;
191 $UpstreamLArPadding = 80;
192 $DownstreamLArPadding = 80;
197 $SpaceAPAToCryoWall = 100;
198 $SpaceAPAToFloor = 45;
199 $SpaceAPAToTopLAr = 45;
200 $UpstreamLArPadding = 20;
201 $DownstreamLArPadding = 20;
203 #InnerDrift is the max distance form the edge of the CPA to the edge of the first wire plane
205 $OuterDrift = $SpaceAPAToCryoWall;
206 $APAFrame_x = 5.0661; # ~2in -- this does not include the wire spacing
208 $TPCWireThickness = 0.015;
209 $TPCWirePlaneThickness = $TPCWireThickness;
210 #$APAWirePlaneSpacing = 0.4730488 + $TPCWirePlaneThickness; # center to center spacing between all of the wire planes (g, u, v, and x)
212 if($Pitch3mmVersion==1){
213 $APAWirePlaneSpacing = 0.3;
215 $APAWirePlaneSpacing = 0.476;
218 # At creation of the plane volumes, the y and z boundaries will be increased
219 # by this much at each of the 4 edges. this is so the corners of the wire
220 # tubes don't extrude. For all other purposes, the plane dimensions stay as originally defined
221 $UVPlaneBoundNudge = $TPCWireThickness;
225 # The following are all widths about the z center of an APA
226 $Zactive_z = ($nZChannelsPerAPA/2-1)*$XWirePitch + $TPCWireThickness;
227 # print "Zactive_z: $Zactive_z \n";
228 $APAFrame_z = 117. - 2*(2*$G10thickness+$WrapCover);
229 $Vactive_z = $APAFrame_z;
230 $Uactive_z = $APAFrame_z + 2*$G10thickness;
235 $ReadoutBoardOverlap = 7.61; #board overlaps wires, chop this off of their active height
237 $Zactive_y = $APAFrame_y + 0*$G10thickness - $ReadoutBoardOverlap;
238 $Vactive_y = $APAFrame_y + 1*$G10thickness - $ReadoutBoardOverlap;
239 $Uactive_y = $APAFrame_y + 2*$G10thickness - $ReadoutBoardOverlap;
240 # the last G10 board for the grid, then a cover. This is not "covered" by the board
241 $APAphys_y = $APAFrame_y + 4*$G10thickness + $WrapCover;
244 $APAGap_y = 0.4; #separation between APAs (cover to cover) along the incident beam axis
245 $APAGap_z = 0.8; #separation between APAs (cover to cover) along the vertical axis
248 # include APA spacing in y and z so volTPCs touch in y and z directions with correct APA
249 # spacing - this makes for smoother event generation.
251 $APA_UtoU_x = $APAFrame_x + 6*$APAWirePlaneSpacing + $TPCWirePlaneThickness; # thickness of APA between its
252 # outer wire planes (center to center)
253 $TPCInner_x = $InnerDrift + 3*$APAWirePlaneSpacing + $TPCWirePlaneThickness;
254 $TPCOuter_x = $OuterDrift + 3*$APAWirePlaneSpacing + $TPCWirePlaneThickness;
256 $TPC_z = $APAphys_z + $APAGap_z;
257 $TPC_y = $APAphys_y + $APAGap_y;
260 #$CPATube_ID = 4.747;
263 $Cathode_y = $APAphys_y - $CPATube_OD;
264 $Cathode_z = $APAphys_z - $CPATube_OD;
267 $APAToAPA = $APAFrame_x
269 + $Cathode_x; # center to center
271 $CPAToAPA = $APAFrame_x/2
273 + $Cathode_x/2; # center to center
275 $SteelThickness = 0.5*$inch; #half inch
276 $HeightGaseousAr = 50;
278 $Argon_x = ($nAPAWide-1)*$APAToAPA
279 + $APA_UtoU_x + $TPCWirePlaneThickness
280 + 2*$SpaceAPAToCryoWall;
282 if($workspace==1||$workspace==2){ # this is arbitrary for the workspace, but size down a little
283 $Argon_x = 2*$CPAToAPA + $Cathode_x + 2*$SpaceAPAToCryoWall;
287 $Argon_y = $nAPAHigh*$APAphys_y
288 + ($nAPAHigh-1)*$APAGap_y
289 + $SpaceAPAToFloor + $SpaceAPAToTopLAr
291 # both liquid AND gaseous argon
293 $Argon_z = $nAPALong*$APAphys_z
294 + ($nAPALong-1)*$APAGap_z
295 + $UpstreamLArPadding + $DownstreamLArPadding;
297 $Cryostat_x = $Argon_x + 2*$SteelThickness;
298 $Cryostat_y = $Argon_y + 2*$SteelThickness;
299 $Cryostat_z = $Argon_z + 2*$SteelThickness;
303 ##################################################################
304 ############## DetEnc and World relevant parameters #############
307 $SteelSupport_x = 100;
308 $SteelSupport_y = 50;
309 $SteelSupport_z = 100;
311 $FracMassOfSteel = 0.998; #The steel support is not a solid block, but a mixture of air and steel
312 $FracMassOfAir = 1-$FracMassOfSteel;
314 $SpaceSteelSupportToWall = 100;
315 $SpaceSteelSupportToCeiling = 100;
317 $DetEncWidth = $Cryostat_x
318 + 2*($SteelSupport_x + $FoamPadding) + $SpaceSteelSupportToCeiling;
319 $DetEncHeight = $Cryostat_y
320 + 2*($SteelSupport_y + $FoamPadding) + 2*$SpaceSteelSupportToWall;
321 $DetEncLength = $Cryostat_z
322 + 2*($SteelSupport_z + $FoamPadding) + 2*$SpaceSteelSupportToWall;
324 $posCryoInDetEnc_y = - $DetEncHeight/2 + $SteelSupport_y + $FoamPadding + $Cryostat_y/2;
326 $RockThickness = 3000;
327 if ($workspace == 0){
328 # Initially, the world dimensions and the OriginZSet
329 # left only ~222cm to the world boundary from the
330 # +z boundary of volDetEnclosure. Bump that up to
331 # at least 10m for good measure.
332 # This is in an if statement so that it does not affect
333 # the workspace geometries, which are already being used
334 $RockThickness += 800
337 # We want the world origin to be at the very front of the fiducial volume.
338 # move it to the front of the enclosure, then back it up through the concrete/foam,
339 # then through the Cryostat shell, then through the upstream dead LAr (including the
340 # dead LAr on the edge of the TPC, but this is covered in $UpstreamLArPadding).
341 # This is to be added to the z position of every volume in volWorld
343 $OriginZSet = $DetEncLength/2
344 - $SpaceSteelSupportToWall
348 - $UpstreamLArPadding
349 - ($APAphys_z - $Uactive_z)/2;
351 # We want the world origin to be vertically centered between the stacked APAs.
352 # This is to be added to the y position of every volume in volWorld
354 $OriginYSet = $DetEncHeight/2
362 #if($protoDune==1){ # bring the origin to the bottom of the APAs for protoDUNE
364 $OriginYSet = $OriginYSet + $APAphys_y + $APAGap_y/2;
367 $OriginXSet = 0; # centered for now
374 ####################################################################
375 ######################## Paddle Dimensions ########################
377 $APAFrameZSide_y = 4*$inch;
378 $APAFrameYSide_z = 4*$inch;
379 $LightPaddle_x = 0.476;
380 $LightPaddle_y = 4*$inch;
381 $LightPaddle_z = $APAFrame_z - 2*$APAFrameYSide_z;
382 $nLightPaddlesPerAPA = 10; # 10, or 20 for double coverage (for now)
383 $PaddleYInterval = (2*$APAphys_y+$APAGap_y-$LightPaddle_y-2*$APAFrameZSide_y)
384 /(2*$nLightPaddlesPerAPA-1);
385 $FrameToPaddleSpace = ($PaddleYInterval-$APAGap_y)/2;
389 # $PaddleYInterval is defined so that the center-to-center distance in the
390 # y direction between paddles is uniform between vertically stacked APAs.
391 # $FrameToPaddleSpace is from the BOTTOM of the APA frame (4" in y direction)
392 # to the CENTER of a paddle, including the 4" part of the frame. This variable's
393 # primary purpose is to position the lowest paddle in each APA.
398 #+++++++++++++++++++++++++ End defining variables ++++++++++++++++++++++++++
401 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
402 #+++++++++++++++++++++++++++++++++++++++++ usage +++++++++++++++++++++++++++++++++++++++++
403 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
407 print "Usage: $0 [-h|--help] [-o|--output <fragments-file>] [-s|--suffix <string>]\n";
408 print " if -o is omitted, output goes to STDOUT; <fragments-file> is input to make_gdml.pl\n";
409 print " -s <string> appends the string to the file names; useful for multiple detector versions\n";
410 print " -h prints this message, then quits\n";
415 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
416 #++++++++++++++++++++++++++++++++++++++ gen_Define +++++++++++++++++++++++++++++++++++++++
417 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
422 # Create the <define> fragment file name,
423 # add file to list of fragments,
425 $DEF = "iceberg_v1_Def" . $suffix . ".gdml";
426 push (@gdmlFiles, $DEF);
428 open(DEF) or die("Could not open file $DEF for writing");
432 <?xml version='1.0'?>
442 <position name="posCryoInDetEnc" unit="cm" x="0" y="$posCryoInDetEnc_y" z="0"/>
443 <position name="posCenter" unit="cm" x="0" y="0" z="0"/>
444 <rotation name="rPlus90AboutX" unit="deg" x="90" y="0" z="0"/>
445 <rotation name="rMinus90AboutY" unit="deg" x="0" y="270" z="0"/>
446 <rotation name="rMinus90AboutYMinus90AboutX" unit="deg" x="270" y="270" z="0"/>
447 <rotation name="rPlusUAngleAboutX" unit="deg" x="90-$UAngle" y="0" z="0"/>
448 <rotation name="rPlusVAngleAboutX" unit="deg" x="90+$VAngle" y="0" z="0"/>
449 <rotation name="rPlus180AboutX" unit="deg" x="180" y="0" z="0"/>
450 <rotation name="rPlus180AboutY" unit="deg" x="0" y="180" z="0"/>
451 <rotation name="rPlus180AboutXPlus180AboutY" unit="deg" x="180" y="180" z="0"/>
452 <rotation name="rIdentity" unit="deg" x="0" y="0" z="0"/>
459 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
460 #+++++++++++++++++++++++++++++++++++++ gen_Materials +++++++++++++++++++++++++++++++++++++
461 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
466 # Create the <materials> fragment file name,
467 # add file to list of output GDML fragments,
469 $MAT = "iceberg_v1_Materials" . $suffix . ".gdml";
470 push (@gdmlFiles, $MAT);
473 open(MAT) or die("Could not open file $MAT for writing");
475 # Add any materials special to this geometry by defining a mulitline string
476 # and passing it to the gdmlMaterials::gen_Materials() function.
478 $DensityAirSteel = 1/(0.001205/$FracMassOfAir + 7.9300/$FracMassOfSteel);
481 <!-- preliminary values -->
482 <material name="AirSteelMixture" formula="AirSteelMixture">
483 <D value="$DensityAirSteel" unit="g/cm3"/>
484 <fraction n="$FracMassOfSteel" ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
485 <fraction n="$FracMassOfAir" ref="Air"/>
489 # add the general materials used anywere
490 print MAT gdmlMaterials::gen_Materials( $asmix );
495 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
496 #++++++++++++++++++++++++++++++++++++++++ gen_TPC ++++++++++++++++++++++++++++++++++++++++
497 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
508 my $TPCActive_x = $_[0]-(3*$APAWirePlaneSpacing);
509 my $TPCActive_y = $_[1] - $APAGap_y/2 - $ReadoutBoardOverlap ; #TODO: make the Active height more accurate
510 my $TPCActive_z = $_[2];
513 #constructs everything inside volTPC, namely
514 # (moving from left to right, or from +x to -x)
516 # -volTPCPlaneU: with wires angled from vertical slightly different than in V
517 # -volTPCPlaneV: with wires angled from vertical slightly differently than in U
518 # -volTPCPlaneX: with vertical wires
521 # Create the TPC fragment file name,
522 # add file to list of output GDML fragments,
524 $TPC = "iceberg_v1_TPC_${_[3]}" . $suffix . ".gdml";
525 push (@gdmlFiles, $TPC);
527 open(TPC) or die("Could not open file $TPC for writing");
530 print $wout "\n\n\n----- Wires for $_[3] -----\n\n\n";
533 # The standard XML prefix and starting the gdml
535 <?xml version='1.0'?>
540 # All the TPC solids save the wires.
543 <box name="$_[3]" lunit="cm"
547 <box name="${_[3]}UPlane" lunit="cm"
548 x="$TPCWirePlaneThickness"
549 y="$Uactive_y + $UVPlaneBoundNudge"
550 z="$Uactive_z + $UVPlaneBoundNudge"/>
551 <box name="${_[3]}VPlane" lunit="cm"
552 x="$TPCWirePlaneThickness"
553 y="$Vactive_y + $UVPlaneBoundNudge"
554 z="$Vactive_z + $UVPlaneBoundNudge"/>
555 <box name="${_[3]}ZPlane" lunit="cm"
556 x="$TPCWirePlaneThickness"
559 <box name="${_[3]}Active" lunit="cm"
566 #++++++++++++++++++++++++++++ Wire Solids ++++++++++++++++++++++++++++++
570 <tube name="${_[3]}WireVert"
571 rmax="0.5*$TPCWireThickness"
578 # Set number of wires to default to zero, when $wires_on = 0, for a low memory
579 # version. But if $wires_on = 1, calculate the number of wires on each side of each
580 # plane to be used in the for loops
582 my $NumberCornerUWires = 0;
583 my $NumberSideUWires = 0;
584 my $NumberCommonUWires = 0;
585 my $NumberCornerVWires = 0;
586 my $NumberSideVWires = 0;
587 my $NumberCommonVWires = 0;
588 my $NumberVerticalWires = 0;
592 # Number of wires in one corner
593 $NumberCornerUWires = int( $APAFrame_z/($UWirePitch/$CosUAngle) );
595 $NumberCornerVWires = int( $APAFrame_z/($VWirePitch/$CosVAngle) );
598 # Total number of wires touching one vertical (longer) side
599 # Note that the total number of wires per plane is this + another set of corner wires
600 $NumberSideUWires = int( $Uactive_y/$UWire_yint );
601 if($Pitch3mmVersion==1){ $NumberSideUWires = $NumberSideUWires-1; }
603 $NumberSideVWires = int( $Vactive_y/$VWire_yint );
605 # Number of wires per side that aren't cut off by the corner
606 $NumberCommonUWires = $NumberSideUWires - $NumberCornerUWires;
608 $NumberCommonVWires = $NumberSideVWires - $NumberCornerVWires;
610 # Number of wires on the vertical plane
611 # Since APA Active z is defined in docdb 3383 to be distance
612 # between outer vertical wires, + 1 since the floor of this
613 # division will be one under, giving the amt of spaces, not wires
614 $NumberVerticalWires = int( $Zactive_z/$XWirePitch ) + 1;
615 #$NumberVerticalWires = 480;
618 $nUchans = 2*$NumberCornerUWires;
619 $nVchans = 2*$NumberCornerVWires;
621 print $wout "$nUchans U channels\n";
622 print $wout "$nVchans V channels\n";
623 print $wout "$NumberVerticalWires Z channels per side\n";
625 print $wout "$NumberCornerUWires U corner wires\n";
626 print $wout "$NumberCommonUWires U common wires\n";
627 print $wout "$NumberCornerVWires V corner wires\n";
628 print $wout "$NumberCommonVWires V common wires\n";
632 # hard codeed number will be a factor determined from engineering spreadsheets on wire endpoints,
633 # but since that won't exist for a while, use this number to avoid overlaps
634 my $FirstUWireOffset = .55 + $G10thickness + 2*$G10thickness*$TanUAngle - $UWire_zint;
635 my $FirstVWireOffset = .5; # doesnt include a G10 board in width
637 if($Pitch3mmVersion==1){
638 my $FirstUWireOffset = .15 + $G10thickness + 2*$G10thickness*$TanUAngle - $UWire_zint;
639 my $FirstVWireOffset = .15; # doesnt include a G10 board in width
642 if($UVAngle45Option==1){$FirstVWireOffset = .7;}
645 my $FirstTopUWire_yspan =
648 + $FirstUWireOffset/$TanUAngle # walk us up to the first wire
649 + $UWire_yint*($NumberSideUWires-1) # up to the top of the top common wire
650 - $Uactive_z/$TanUAngle # back to the bottom of the top common wire
651 + $UWire_yint); # nudge up to bottom of the first top corner wire
653 my $FirstTopVWire_yspan =
656 + $FirstVWireOffset/$TanVAngle # walk us up to the first wire
657 + $VWire_yint*($NumberSideVWires-1) # up to the top of the top common wire
658 - $Vactive_z/$TanVAngle # back to the bottom of the top common wire
659 + $VWire_yint); # nudge up to bottom of the first top corner wire
662 # The corner wires for the U plane
665 for ($i = 0; $i < $NumberCornerUWires; $i++)
667 $CornerUWireLength[$i] = ($FirstUWireOffset + $i*$UWire_zint)/$SinUAngle;
670 <tube name="${_[3]}WireU$i"
671 rmax="0.5*$TPCWireThickness"
672 z="$CornerUWireLength[$i]"
680 $CommonUWireLength = $Uactive_z/$SinUAngle;
683 <tube name="${_[3]}WireUCommon"
684 rmax="0.5*$TPCWireThickness"
685 z="$CommonUWireLength"
691 for ($i = 0; $i < $NumberCornerUWires; $i++)
694 $TopCornerUWireLength[$i] = ($FirstTopUWire_yspan - $i*$UWire_yint)/$CosUAngle;
696 $j = $i + $NumberSideUWires;
699 <tube name="${_[3]}WireU$j"
700 rmax="0.5*$TPCWireThickness"
701 z="$TopCornerUWireLength[$i]"
712 # The corner wires for the V plane
715 for ($i = 0; $i < $NumberCornerVWires; ++$i)
717 $CornerVWireLength[$i] = ($FirstVWireOffset + $i*$VWire_zint)/$SinVAngle;
721 <tube name="${_[3]}WireV$i"
722 rmax="0.5*$TPCWireThickness"
723 z="$CornerVWireLength[$i]"
732 # The wire used many times in the middle of the V plane
733 # Same subtraction as U common
735 $CommonVWireLength = $Vactive_z/$SinVAngle;
738 <tube name="${_[3]}WireVCommon"
739 rmax="0.5*$TPCWireThickness"
740 z="$CommonVWireLength"
746 for ($i = 0; $i < $NumberCornerVWires; $i++)
749 $TopCornerVWireLength[$i] = ($FirstTopVWire_yspan - $i*$VWire_yint)/$CosVAngle;
751 $j = $i + $NumberSideVWires;
754 <tube name="${_[3]}WireV$j"
755 rmax="0.5*$TPCWireThickness"
756 z="$TopCornerVWireLength[$i]"
767 # Begin structure and create the vertical wire logical volume
771 <volume name="volTPCActive${_[3]}">
772 <materialref ref="LAr"/>
773 <solidref ref="${_[3]}Active"/>
782 <volume name="volTPCWireVert${_[3]}">
783 <materialref ref="Copper_Beryllium_alloy25"/>
784 <solidref ref="${_[3]}WireVert"/>
788 # Corner U wires logical volumes
789 for ($i = 0; $i < $NumberCornerUWires; ++$i)
792 <volume name="volTPCWireU$i${_[3]}">
793 <materialref ref="Copper_Beryllium_alloy25"/>
794 <solidref ref="${_[3]}WireU$i"/>
800 # Top Corner U wires logical volumes
801 for ($j = $NumberSideUWires; $j < $NumberSideUWires + $NumberCornerUWires; ++$j)
804 <volume name="volTPCWireU$j${_[3]}">
805 <materialref ref="Copper_Beryllium_alloy25"/>
806 <solidref ref="${_[3]}WireU$j"/>
812 # Common U wire logical volume, referenced many times
814 <volume name="volTPCWireUCommon${_[3]}">
815 <materialref ref="Copper_Beryllium_alloy25"/>
816 <solidref ref="${_[3]}WireUCommon"/>
821 # Corner V wires logical volumes
822 for ($i = 0; $i < $NumberCornerVWires; ++$i)
825 <volume name="volTPCWireV$i${_[3]}">
826 <materialref ref="Copper_Beryllium_alloy25"/>
827 <solidref ref="${_[3]}WireV$i"/>
833 # Top Corner V wires logical volumes
834 for ($j = $NumberSideVWires; $j < $NumberSideVWires + $NumberCornerVWires; ++$j)
837 <volume name="volTPCWireV$j${_[3]}">
838 <materialref ref="Copper_Beryllium_alloy25"/>
839 <solidref ref="${_[3]}WireV$j"/>
844 # Common V wire logical volume, referenced many times
846 <volume name="volTPCWireVCommon${_[3]}">
847 <materialref ref="Copper_Beryllium_alloy25"/>
848 <solidref ref="${_[3]}WireVCommon"/>
859 #+++++++++++++++++++++++++ Position physical wires ++++++++++++++++++++++++++
861 # ++++++++++++++++++++++ U Plane +++++++++++++++++++++++
863 # Create U plane logical volume
865 <volume name="volTPCPlaneU${_[3]}">
866 <materialref ref="LAr"/>
867 <solidref ref="${_[3]}UPlane"/>
871 print $wout "\n- Wires for U plane -\n\n";
872 print $wout " Uplane_y: $Uactive_y\n";
873 print $wout " Uplane_z: $Uactive_z\n";
879 # Starting with the bottom left corner wires:
880 # x=0 to center the wires in the plane
881 # y positioning: (-0.5*$TPCWirePlaneHeight) starts the incremental increase
882 # from the bottom of the plane, and trigonometry gives the increment
883 # z positioning: Looking at the plane from the positive x direction,
884 # (0.5*$TPCWirePlaneLength) starts the incremental increase from
885 # the lower left corner.
886 # rotation: same as common wire in code below
888 $FirstU_ypos = - $Uactive_y/2 + $FirstUWireOffset/$TanUAngle/2;
889 $FirstU_zpos = + $Uactive_z/2 - $FirstUWireOffset/2;
891 for ($i = 0; $i < $NumberCornerUWires; ++$i)
894 my $ypos = $FirstU_ypos + ($i)*0.5*$UWire_yint;
895 my $zpos = $FirstU_zpos - ($i)*0.5*$UWire_zint;
897 $pitch = ($ypos - $lastYpos) * $SinUAngle
898 - ($zpos - $lastZpos) * $CosUAngle;
902 <volumeref ref="volTPCWireU$i${_[3]}"/>
903 <position name="pos${_[3]}WireU$i" unit="cm" x="0" y="$ypos " z="$zpos"/>
904 <rotation name="rUAngle$i" unit="deg" x="90-$UAngle" y="0" z="0"/>
908 $topY = $ypos + ($CosUAngle*$CornerUWireLength[$i]/2);
909 $bottomY = $ypos - ($CosUAngle*$CornerUWireLength[$i]/2);
910 $edgeZ_p = $zpos + ($SinUAngle*$CornerUWireLength[$i]/2);
911 $edgeZ_m = $zpos - ($SinUAngle*$CornerUWireLength[$i]/2);
912 print $wout "U$i: ( $ypos , $zpos ) (pitch = $pitch)\n";
913 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
921 # Moving upwards to the common wires:
922 # x and z are zero to center the wires along a vertical axis
923 # y positioning: The trick is positioning the lowest common wire so that the pitch
924 # is consistent, then the increment is double the increment of
925 # the corner wires since there is no z incriment.
926 # rotation: wires in \\\\ direction, so +90deg to bring them to vertical and
927 # +UAngle counterclockwise to arrive at proper orientation
928 # Note that the counter maintains wire number (in pos. name) counting bottom to top
931 my $StartCommonUWires_ypos = $lastYpos + $UWire_yint - abs( $lastZpos )/$TanUAngle;
933 for ($i = $NumberCornerUWires; $i < $NumberSideUWires; ++$i)
936 $j = $i - $NumberCornerUWires;
937 my $ypos = $StartCommonUWires_ypos + $UWire_yint*($j);
940 if ( $ypos < $lastYpos ){ print "WARNING: y position dropped from $lastYpos (wire U$lastWnum) to $ypos (wire U$i)\n"; }
941 if ( $ypos == $lastYpos ){ print "WARNING: y position between wire U$lastWnum and U$lastWnum did not move: $ypos\n"; }
944 $pitch = ($ypos - $lastYpos) * $SinUAngle - ($zpos - $lastZpos) * $CosUAngle ;
948 <volumeref ref="volTPCWireUCommon${_[3]}"/>
949 <position name="pos${_[3]}WireU$i" unit="cm" x="0" y="$ypos " z="0"/>
950 <rotation name="rUAngle$i" unit="deg" x="90-$UAngle" y="0" z="0"/>
954 $topY = $ypos + ($CosUAngle*$CommonUWireLength/2);
955 $bottomY = $ypos - ($CosUAngle*$CommonUWireLength/2);
956 $edgeZ_p = + ($SinUAngle*$CommonUWireLength/2);
957 $edgeZ_m = - ($SinUAngle*$CommonUWireLength/2);
958 print $wout "U$i: ( $ypos , 0 ) (pitch = $pitch)\n";
959 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
968 my $FirstTopUWire_zspan = $FirstTopUWire_yspan*$TanUAngle;
969 my $StartTopUWires_ypos = + $Uactive_y/2 - $FirstTopUWire_yspan/2;
970 my $StartTopUWires_zpos = - $Uactive_z/2 + $FirstTopUWire_zspan/2;
972 # Finally moving to the corner wires on the top right:
973 # x=0 to center the wires in the plane
974 # y positioning: plug wire number into same equation
975 # z positioning: start at z=0 and go negatively at the same z increment
976 # rotation: same as common wire in code above
977 # note that the counter maintains wire number shown in the position name
979 for ($j = $NumberSideUWires; $j < $NumberSideUWires+$NumberCornerUWires; ++$j)
982 $i = $j - $NumberSideUWires;
984 my $ypos = $StartTopUWires_ypos + ($i)*0.5*$UWire_yint;
985 my $zpos = $StartTopUWires_zpos - ($i)*0.5*$UWire_zint;
988 if ( $ypos < $lastYpos ){ print "WARNING: y position dropped from $lastYpos (wire U$lastWnum) to $ypos (wire U$j)\n"; }
989 if ( $ypos == $lastYpos ){ print "WARNING: y position between wire U$lastWnum and U$j did not move: $ypos\n"; }
991 $pitch = ($ypos - $lastYpos) * $SinUAngle - ($zpos - $lastZpos) * $CosUAngle ;
995 <volumeref ref="volTPCWireU$j${_[3]}"/>
996 <position name="pos${_[3]}WireU$j" unit="cm" x="0" y="$ypos " z="$zpos"/>
997 <rotation name="rUAngle$j" unit="deg" x="90-$UAngle" y="0" z="0"/>
1001 $topY = $ypos + ($CosUAngle*$TopCornerUWireLength[$i]/2);
1002 $bottomY = $ypos - ($CosUAngle*$TopCornerUWireLength[$i]/2);
1003 $edgeZ_p = $zpos + ($SinUAngle*$TopCornerUWireLength[$i]/2);
1004 $edgeZ_m = $zpos - ($SinUAngle*$TopCornerUWireLength[$i]/2);
1005 print $wout "U$j: ( $ypos , $zpos ) (pitch = $pitch)\n";
1006 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1016 # ++++++++++++++++++++++ V Plane +++++++++++++++++++++++
1018 # End U plane and create V plane logical volume
1022 <volume name="volTPCPlaneV${_[3]}">
1023 <materialref ref="LAr"/>
1024 <solidref ref="${_[3]}VPlane"/>
1027 print $wout "\n- Wires for V plane -\n\n";
1028 print $wout " Vplane_y: $Vactive_y\n";
1029 print $wout " Vplane_z: $Vactive_z\n";
1035 # Starting with the bottom right corner wires:
1036 # x=0 to center the wires in the plane
1037 # y positioning: (-0.5*$TPCWirePlaneHeight) starts the incremental increase
1038 # from the bottom of the plane, and trigonometry gives the increment
1039 # z positioning: Looking at the plane from the positive x direction,
1040 # (-0.5*$TPCWirePlaneLength) starts the incremental increase from
1041 # the lower right corner.
1042 # rotation: same as common wire in code below
1044 $FirstV_ypos = - $Vactive_y/2 + $FirstVWireOffset/$TanVAngle/2;
1045 $FirstV_zpos = - $Vactive_z/2 + $FirstVWireOffset/2;
1047 for ($i = 0; $i < $NumberCornerVWires; ++$i)
1050 my $ypos = $FirstV_ypos + ($i)*0.5*$VWire_yint;
1051 my $zpos = $FirstV_zpos + ($i)*0.5*$VWire_zint;
1055 <volumeref ref="volTPCWireV$i${_[3]}"/>
1056 <position name="pos${_[3]}WireV$i" unit="cm" x="0" y="$ypos " z="$zpos"/>
1057 <rotation name="rVAngle$i" unit="deg" x="90+$VAngle" y="0" z="0"/>
1061 $topY = $ypos + ($CosVAngle*$CornerVWireLength[$i]/2);
1062 $bottomY = $ypos - ($CosVAngle*$CornerVWireLength[$i]/2);
1063 $edgeZ_p = $zpos + ($SinVAngle*$CornerVWireLength[$i]/2);
1064 $edgeZ_m = $zpos - ($SinVAngle*$CornerVWireLength[$i]/2);
1065 print $wout "V$i: ( $ypos , $zpos ) \n";
1066 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1074 # Moving upwards to the common wires:
1075 # x and z are zero to center the wires along a vertical axis
1076 # y positioning: Plug wire number into the same corner ypos equation
1077 # rotation: wires in //// direction, so +90deg to bring them to vertical and
1078 # --VAngle counterclockwise to arrive at proper orientation
1079 # Note that the counter maintains wire number in the position name
1081 my $StartCommonVWires_ypos = $lastYpos + $VWire_yint - abs( $lastZpos )/$TanVAngle;
1083 for ($i = $NumberCornerVWires; $i < $NumberSideVWires; ++$i)
1086 $j = $i - $NumberCornerVWires;
1087 my $ypos = $StartCommonVWires_ypos + $VWire_yint*($j);
1091 <volumeref ref="volTPCWireVCommon${_[3]}"/>
1092 <position name="pos${_[3]}WireV$i" unit="cm" x="0" y="$ypos " z="0"/>
1093 <rotation name="rVAngle$i" unit="deg" x="90+$VAngle" y="0" z="0"/>
1097 $topY = $ypos + ($CosVAngle*$CommonVWireLength/2);
1098 $bottomY = $ypos - ($CosVAngle*$CommonVWireLength/2);
1099 $edgeZ_p = + ($SinVAngle*$CommonVWireLength/2);
1100 $edgeZ_m = - ($SinVAngle*$CommonVWireLength/2);
1101 print $wout "V$i: ( $ypos , 0 ) \n";
1102 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1105 #$lastZpos = $zpos; always 0
1110 my $FirstTopVWire_zspan = $FirstTopVWire_yspan*$TanVAngle;
1111 my $StartTopVWires_ypos = + $Vactive_y/2 - $FirstTopVWire_yspan/2;
1112 my $StartTopVWires_zpos = + $Vactive_z/2 - $FirstTopVWire_zspan/2;
1114 # Finally moving to the corner wires on the top right:
1115 # x=0 to center the wires in the plane
1116 # y positioning: plug wire number into same equation
1117 # z positioning: start at z=0 and go positively at the same z increment
1118 # rotation: same as common wire in code above
1119 # note that the counter maintains wire number shown in the position name
1121 for ($j = $NumberSideVWires; $j < $NumberSideVWires+$NumberCornerVWires; ++$j)
1124 $i = $j - $NumberSideVWires;
1126 my $ypos = $StartTopVWires_ypos + ($i)*0.5*$VWire_yint;
1127 my $zpos = $StartTopVWires_zpos + ($i)*0.5*$VWire_zint;
1131 <volumeref ref="volTPCWireV$j${_[3]}"/>
1132 <position name="pos${_[3]}WireV$j" unit="cm" x="0" y="$ypos " z="$zpos"/>
1133 <rotation name="rVAngle$j" unit="deg" x="90+$VAngle" y="0" z="0"/>
1137 $topY = $ypos + ($CosVAngle*$TopCornerVWireLength[$i]/2);
1138 $bottomY = $ypos - ($CosVAngle*$TopCornerVWireLength[$i]/2);
1139 $edgeZ_p = $zpos + ($SinVAngle*$TopCornerVWireLength[$i]/2);
1140 $edgeZ_m = $zpos - ($SinVAngle*$TopCornerVWireLength[$i]/2);
1141 print $wout "V$j: ( $ypos , $zpos ) \n";
1142 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1155 # ++++++++++++++++++++++ Z Plane +++++++++++++++++++++++
1157 # End V plane and create Z plane logical volume
1161 <volume name="volTPCPlaneZ${_[3]}">
1162 <materialref ref="LAr"/>
1163 <solidref ref="${_[3]}ZPlane"/>
1169 # This is the simplest plane, one loop creates all of the wires
1170 # x and y position at zero to center the wires
1171 # z position: moving from front of detector to back, in the positive z direction,
1172 # starting at (-0.5*$TPCWirePlaneLength), the right side looking from
1175 for ($i=0; $i<$NumberVerticalWires; ++$i)
1177 my $zpos = (-0.5*$Zactive_z) + $i*$XWirePitch + $TPCWireThickness/2;
1181 <volumeref ref="volTPCWireVert${_[3]}"/>
1182 <position name="pos${_[3]}WireZ$i" unit="cm" x="0" y="0 " z="$zpos"/>
1183 <rotationref ref="rPlus90AboutX"/>
1195 #+++++++++++++++++++++ ^^ Position physical wires Above ^^ +++++++++++++++++++++
1197 ## make the TPC active volume extend down to the G10 for the grid
1199 my $BottomOfAPA = - $TPC_y/2 + $APAGap_y/2;
1202 $posZplane[0] = -$_[0]/2 + $APAWirePlaneSpacing - $TPCWirePlaneThickness/2;
1203 $posZplane[1] = $BottomOfAPA + $WrapCover + 4*$G10thickness + $Zactive_y/2;
1206 $posVplane[0] = $posZplane[0] + $APAWirePlaneSpacing;
1207 $posVplane[1] = $BottomOfAPA + $WrapCover + 3*$G10thickness + $Vactive_y/2;
1208 $posVplane[2] = $posZplane[2];
1210 $posUplane[0] = $posVplane[0] + $APAWirePlaneSpacing;
1211 $posUplane[1] = $BottomOfAPA + $WrapCover + 2*$G10thickness + $Uactive_y/2;
1212 $posUplane[2] = $posZplane[2];
1214 $posTPCActive[0] = $posUplane[0] + ($TPCWirePlaneThickness/2 + $TPCActive_x/2);
1215 $posTPCActive[1] = -$_[1]/2 + $TPCActive_y/2;
1216 $posTPCActive[2] = 0;
1218 #wrap up the TPC file
1220 <volume name="volTPC${_[3]}">
1221 <materialref ref="LAr"/>
1222 <solidref ref="${_[3]}"/>
1224 <volumeref ref="volTPCPlaneZ${_[3]}"/>
1225 <position name="pos${_[3]}PlaneZ" unit="cm"
1226 x="$posZplane[0]" y="$posZplane[1]" z="$posZplane[2]"/>
1227 <rotationref ref="rIdentity"/>
1230 <volumeref ref="volTPCPlaneV${_[3]}"/>
1231 <position name="pos${_[3]}PlaneV" unit="cm"
1232 x="$posVplane[0]" y="$posVplane[1]" z="$posVplane[2]"/>
1233 <rotationref ref="rIdentity"/>
1236 <volumeref ref="volTPCPlaneU${_[3]}"/>
1237 <position name="pos${_[3]}PlaneU" unit="cm"
1238 x="$posUplane[0]" y="$posUplane[1]" z="$posUplane[2]"/>
1239 <rotationref ref="rIdentity"/>
1243 # Option to omit the active volume on the outside for the prototype.
1244 if( !($killOuterActive==1 && $_[3] eq 'Outer') ){
1247 <volumeref ref="volTPCActive${_[3]}"/>
1248 <position name="pos${_[3]}Active" unit="cm"
1249 x="$posTPCActive[0]" y="$posTPCActive[1]" z="$posTPCActive[2]"/>
1250 <rotationref ref="rIdentity"/>
1263 } #end of sub gen_TPC
1267 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1268 #++++++++++++++++++++++++++++++++++++++ gen_Cryostat +++++++++++++++++++++++++++++++++++++
1269 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1274 # Create the cryostat fragment file name,
1275 # add file to list of output GDML fragments,
1277 $CRYO = "iceberg_v1_Cryostat" . $suffix . ".gdml";
1278 push (@gdmlFiles, $CRYO);
1279 $CRYO = ">" . $CRYO;
1280 open(CRYO) or die("Could not open file $CRYO for writing");
1283 # The standard XML prefix and starting the gdml
1285 <?xml version='1.0'?>
1289 $APAFrameZSide_x = $APAFrame_x;
1290 $APAFrameZSide_y = 4*$inch;
1291 $APAFrameZSide_z = $APAFrame_z;
1293 $APAFrameYSide_x = $APAFrame_x;
1294 $APAFrameYSide_y = $APAFrame_y-2*$APAFrameZSide_y;
1295 $APAFrameYSide_z = 4*$inch;
1297 # Two outer Y supports will sandwich the light paddles
1298 $APAFrameYOuterSupport_x = ($APAFrame_x-$LightPaddle_x)/2;
1299 $APAFrameYOuterSupport_y = $APAFrame_y-2*$APAFrameZSide_y;
1300 $APAFrameYOuterSupport_z = 4*$inch;
1302 $EdgeFrameSteelThickness = 0.12*$inch;
1303 $InnerFrameSteelThickness = 0.062*$inch;
1306 $G10BoardYSide_x = $APAFrame_x;
1307 $G10BoardYSide_y = $APAFrame_y;
1308 $G10BoardYSide_z = $G10thickness;
1310 $G10BoardZSide_x = $APAFrame_x;
1311 $G10BoardZSide_y = $G10thickness;
1312 $G10BoardZSide_z = $APAFrame_z;
1315 # All the cryostat solids.
1318 <box name="Cryostat" lunit="cm"
1322 <box name="ArgonInterior" lunit="cm"
1326 <box name="GaseousArgon" lunit="cm"
1328 y="$HeightGaseousAr"
1330 <subtraction name="SteelShell">
1331 <first ref="Cryostat"/>
1332 <second ref="ArgonInterior"/>
1335 <box name="Cathode" lunit="cm"
1340 <box name="LightPaddle" lunit="cm"
1343 z="$LightPaddle_z + $SiPM_z"/>
1345 <box name="APAFrameYSideHollow" lunit="cm"
1346 x="$APAFrameYSide_x-2*$EdgeFrameSteelThickness"
1347 y="$APAFrameYSide_y-2*$EdgeFrameSteelThickness"
1348 z="$APAFrameYSide_z"/>
1349 <box name="APAFrameYSideShell" lunit="cm"
1350 x="$APAFrameYSide_x"
1351 y="$APAFrameYSide_y"
1352 z="$APAFrameYSide_z"/>
1353 <subtraction name="APAFrameYSide">
1354 <first ref="APAFrameYSideShell"/>
1355 <second ref="APAFrameYSideHollow"/>
1356 <positionref ref="posCenter"/>
1357 <rotationref ref="rIdentity"/>
1360 <box name="APAFrameZSideHollow" lunit="cm"
1361 x="$APAFrameZSide_x-2*$EdgeFrameSteelThickness"
1362 y="$APAFrameZSide_y-2*$EdgeFrameSteelThickness"
1363 z="$APAFrameZSide_z"/>
1364 <box name="APAFrameZSideShell" lunit="cm"
1365 x="$APAFrameZSide_x"
1366 y="$APAFrameZSide_y"
1367 z="$APAFrameZSide_z"/>
1368 <subtraction name="APAFrameZSide">
1369 <first ref="APAFrameZSideShell"/>
1370 <second ref="APAFrameZSideHollow"/>
1371 <positionref ref="posCenter"/>
1372 <rotationref ref="rIdentity"/>
1375 <box name="APAFrameYOuterSupport" lunit="cm"
1376 x="$EdgeFrameSteelThickness"
1377 y="$APAFrameYOuterSupport_y"
1378 z="$APAFrameYOuterSupport_z"/>
1381 <box name="G10BoardYSideCenterSeg" lunit="cm"
1382 x="$G10BoardYSide_x"
1383 y="$G10BoardYSide_y"
1384 z="$G10BoardYSide_z"/>
1386 <box name="G10BoardZSideCenterSeg" lunit="cm"
1387 x="$G10BoardZSide_x"
1388 y="$G10BoardZSide_y"
1389 z="$G10BoardZSide_z"/>
1394 # Cryostat structure
1397 <volume name="volSteelShell">
1398 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1399 <solidref ref="SteelShell" />
1401 <volume name="volGaseousArgon">
1402 <materialref ref="ArGas"/>
1403 <solidref ref="GaseousArgon"/>
1406 <volume name="volCathode">
1407 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1408 <solidref ref="Cathode" />
1412 for($i=0 ; $i<$nAPAs ; $i++){
1413 for($p=0 ; $p<10 ; $p++){
1415 <volume name="volOpDetSensitive_$i\-$p">
1416 <materialref ref="Acrylic"/>
1417 <solidref ref="LightPaddle"/>
1426 <volume name="volAPAFrameYSide">
1427 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1428 <solidref ref="APAFrameYSide"/>
1431 <volume name="volAPAFrameZSide">
1432 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1433 <solidref ref="APAFrameZSide"/>
1436 <volume name="volAPAFrameYOuterSupport">
1437 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1438 <solidref ref="APAFrameYOuterSupport"/>
1441 <volume name="volG10BoardYSideCenterSeg">
1442 <materialref ref="G10"/>
1443 <solidref ref="G10BoardYSideCenterSeg"/>
1446 <volume name="volG10BoardZSideCenterSeg">
1447 <materialref ref="G10"/>
1448 <solidref ref="G10BoardZSideCenterSeg"/>
1451 <volume name="volCryostat">
1452 <materialref ref="LAr" />
1453 <solidref ref="Cryostat" />
1455 <volumeref ref="volGaseousArgon"/>
1456 <position name="posGaseousArgon" unit="cm" x="0" y="$Argon_y/2-$HeightGaseousAr/2" z="0"/>
1459 <volumeref ref="volSteelShell"/>
1460 <position name="posSteelShell" unit="cm" x="0" y="0" z="0"/>
1464 # nested for loops to place the non-rotated AND rotated volTPC
1465 # x loop rotation: There are six drift volumes. Looking into the
1466 # detector from incident direction, and counting from right (-x) to
1467 # left (+x), odd number volumes need to be rotated 180deg about Y in
1468 # order for the cathode to be on the right of the APA.
1475 for($k=0 ; $k<$nAPALong ; $k++)
1477 $APACenter_z = - $Argon_z/2
1478 + $UpstreamLArPadding
1480 + $k*($APAphys_z+$APAGap_z);
1483 for($j=0 ; $j<$nAPAHigh ; $j++) # nAPAHigh always going to be 2
1484 { # $j=0 for bottom APAs
1486 $APACenter_y = - $Argon_y/2 + $SpaceAPAToFloor
1488 + $j*($APAphys_y+$APAGap_y);
1491 if( $workspace == 0 )
1494 for($i=0 ; $i<$nAPAWide ; $i++)
1498 $APACenter_x = - $Argon_x/2
1499 + $SpaceAPAToCryoWall + $APA_UtoU_x/2 + $TPCWirePlaneThickness/2
1502 $CPA_x = $APACenter_x + $CPAToAPA;
1505 #place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, $j);
1506 place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, 1); # top readout hack for iceberg
1507 place_OpDets($APACenter_x, $APACenter_y, $APACenter_z, $apa_i);
1508 $tpc_0 = 2*$apa_i+0;
1509 $tpc_1 = 2*$apa_i+1;
1512 $SelectTPC_0 = "Inner";
1513 $SelectTPC_1 = "Inner";
1514 $TPC_0_x = $TPCInner_x;
1515 $TPC_1_x = $TPCInner_x;
1516 $rot_0 = "rPlus180AboutY";
1517 $rot_1 = "rIdentity";
1518 if($i == 0) { $SelectTPC_0 = "Outer"; $TPC_0_x = $TPCOuter_x; }
1519 if($i == $nAPAWide-1) { $SelectTPC_1 = "Outer"; $TPC_1_x = $TPCOuter_x; }
1520 if($j == 0) { $rot_0 = "rPlus180AboutXPlus180AboutY";
1521 $rot_1 = "rPlus180AboutX"; } #put the readout end at the bottom for bottom APAs
1528 <volumeref ref="volTPC$SelectTPC_0"/>
1529 <position name="posTPC\-$tpc_0" unit="cm"
1530 x="$APACenter_x - $APAFrame_x/2 - $TPC_0_x/2"
1533 <rotationref ref="$rot_0"/>
1536 <volumeref ref="volTPC$SelectTPC_1"/>
1537 <position name="posTPC\-$tpc_1" unit="cm"
1538 x="$APACenter_x + $APAFrame_x/2 + $TPC_1_x/2"
1541 <rotationref ref="$rot_1"/>
1547 if( $i < $nAPAWide - 1 ){ # avoid placeing the last row of CPAs since the APAs are on the outside
1552 <volumeref ref="volCathode"/>
1553 <position name="posCathode\-$cpa_i" unit="cm"
1557 <rotationref ref="rIdentity"/>
1567 } # end if not the smaller workspace
1570 # Make the workspace have only one center APA with CPAs and the full drift on either side
1571 elsif( $workspace == 1 || $workspace==2 || $workspace==3 ){
1574 $CPA_0_x = $APACenter_x - $CPAToAPA;
1575 $CPA_1_x = $APACenter_x + $CPAToAPA;
1578 # place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, $j);
1579 place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, 1); # top readout hack for iceberg
1580 place_OpDets($APACenter_x, $APACenter_y, $APACenter_z, $apa_i);
1582 $tpc_0 = 2*$apa_i+0;
1583 $tpc_1 = 2*$apa_i+1;
1586 $rot_0 = "rPlus180AboutY";
1587 $rot_1 = "rIdentity";
1588 if($j != 0) { $rot_0 = "rPlus180AboutXPlus180AboutY"; #hack for iceberg
1589 $rot_1 = "rPlus180AboutX"; } #put the readout end at the bottom for bottom APAs
1594 <volumeref ref="volTPCInner"/>
1595 <position name="posTPC\-$tpc_0" unit="cm"
1596 x="$APACenter_x - $APAFrame_x/2 - $TPCInner_x/2"
1599 <rotationref ref="$rot_0"/>
1602 <volumeref ref="volTPCInner"/>
1603 <position name="posTPC\-$tpc_1" unit="cm"
1604 x="$APACenter_x + $APAFrame_x/2 + $TPCInner_x/2"
1607 <rotationref ref="$rot_1"/>
1611 <volumeref ref="volCathode"/>
1612 <position name="posCathode\-$apa_i-0" unit="cm"
1616 <rotationref ref="rIdentity"/>
1619 <volumeref ref="volCathode"/>
1620 <position name="posCathode\-$apa_i-1" unit="cm"
1624 <rotationref ref="rIdentity"/>
1629 } # if the smaller workspace
1648 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1649 #++++++++++++++++++++++++++++++++++++ place_OpDets +++++++++++++++++++++++++++++++++++++++
1650 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1655 $APACenter_x = $_[0];
1656 $APACenter_y = $_[1];
1657 $APACenter_z = $_[2];
1660 for ($paddle = 0; $paddle<$nLightPaddlesPerAPA; $paddle++)
1663 # All Light Paddle centers will have the same
1664 # X coordinate as the center of the current APA
1665 # Z coordinate as the current TPC pair
1666 # The Y coordinate must be looped over:
1668 #the multiplication by j here is a temporary dirty trick to get around some strange behavior
1670 $Paddle_Y = $APACenter_y
1672 + $j*$FrameToPaddleSpace
1673 + (1-$j)*($LightPaddle_y/2 + $APAFrameZSide_y)
1674 + $PaddleYInterval*$paddle;
1676 # Alternate the paddle orientations
1677 if ( $paddle % 2 == 0 ) { $rot = "rIdentity"; }
1678 else { $rot = "rPlus180AboutY"; }
1683 <volumeref ref="volOpDetSensitive_$apa_i\-$paddle"/>
1684 <position name="posPaddle\-$paddle\-TPC\-$i\-$j\-$k" unit="cm"
1687 z="$APACenter_z + $SiPM_z/2"/>
1688 <rotationref ref="$rot"/>
1692 }#end Paddle for-loop
1698 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1699 #++++++++++++++++++++++++++++++++++++++ place_APA ++++++++++++++++++++++++++++++++++++++++
1700 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1703 # Must be called only within gen_Cryostat(),
1706 # $_[0] = x APA physical center
1707 # $_[1] = y APA physical center
1708 # $_[2] = z APA physical center
1709 # $_[3] = APA number
1710 # $_[4] = 0 for APA with readout on bottom
1711 # 1 for APA with readout on top
1718 ####################################################################
1719 ################# APA Frame and Paddle Dimensions ##################
1721 # The center passed to this function is the physical APA center,
1722 # which is not quite the frame's center, since there are more boards
1723 # at the bottom. Transform them:
1725 $APAFrameCenter_x = $_[0];
1726 $APAFrameCenter_z = $_[2];
1728 # The bottom APAs are upside down relative to how the TPC is initially generated,
1729 # and the center needs to be slightly shifted since there is extra G10 on the
1730 # end that doesn't read out.
1732 if($_[4]==1) # top APAs
1734 $APAFrameCenter_y = $_[1] - $APAphys_y/2
1735 + $WrapCover + 4*$G10thickness
1738 elsif($_[4]==0) # bottom APAs
1740 $APAFrameCenter_y = $_[1] + $APAphys_y/2
1741 - $WrapCover - 4*$G10thickness
1744 else{ print "APA not labeled as top or bottom"; }
1746 $APAFrameZSide_x = $APAFrame_x;
1747 $APAFrameZSide_y = 4*$inch;
1748 $APAFrameZSide_z = $APAFrame_z;
1750 $APAFrameYSide_x = $APAFrame_x;
1751 $APAFrameYSide_y = $APAFrame_y-2*$APAFrameZSide_y;
1752 $APAFrameYSide_z = 4*$inch;
1754 # Two outer Y supports will sandwich the light paddles
1755 $APAFrameYOuterSupport_x = ($APAFrame_x-$LightPaddle_x)/2;
1756 $APAFrameYOuterSupport_y = $APAFrame_y-2*$APAFrameZSide_y;
1757 $APAFrameYOuterSupport_z = 4*$inch;
1759 # if there were an inner support to fill the hole
1760 $APAFrameYInnerSupport_x = $LightPaddle_x;
1762 $EdgeFrameSteelThickness = 0.12*$inch;
1763 $InnerFrameSteelThickness = 0.062*$inch;
1766 $G10BoardYSide_x = $APAFrame_x;
1767 $G10BoardYSide_y = $APAFrame_y;
1768 $G10BoardYSide_z = $G10thickness;
1770 $G10BoardZSide_x = $APAFrame_x;
1771 $G10BoardZSide_y = $G10thickness;
1772 $G10BoardZSide_z = $APAFrame_z;
1774 if($_[4]==1) # top APAs
1776 $posG10ZSideZ_y = $APAFrameCenter_y - $APAFrame_y/2 - (0+.5)*($G10BoardZSide_y);
1777 $posG10ZSideV_y = $APAFrameCenter_y - $APAFrame_y/2 - (1+.5)*($G10BoardZSide_y);
1778 $posG10ZSideU_y = $APAFrameCenter_y - $APAFrame_y/2 - (2+.5)*($G10BoardZSide_y);
1779 $posG10ZSideGrid_y = $APAFrameCenter_y - $APAFrame_y/2 - (3+.5)*($G10BoardZSide_y);
1781 elsif($_[4]==0) # bottom APAs
1783 $posG10ZSideZ_y = $APAFrameCenter_y + $APAFrame_y/2 + (0+.5)*($G10BoardZSide_y);
1784 $posG10ZSideV_y = $APAFrameCenter_y + $APAFrame_y/2 + (1+.5)*($G10BoardZSide_y);
1785 $posG10ZSideU_y = $APAFrameCenter_y + $APAFrame_y/2 + (2+.5)*($G10BoardZSide_y);
1786 $posG10ZSideGrid_y = $APAFrameCenter_y + $APAFrame_y/2 + (3+.5)*($G10BoardZSide_y);
1788 else{ print "APA not labeled as top or bottom"; }
1790 # First put in the frame
1794 # <volumeref ref="volAPAFrameYOuterSupport\-$APA_i"/>
1795 # <position name="posAPAFrameYOuterSupportNeg\-$APA_i" unit="cm"
1796 # x="$APAFrameCenter_x - ($APAFrameYOuterSupport_x + $APAFrameYInnerSupport_x/2 - $EdgeFrameSteelThickness/2)"
1797 # y="$APAFrameCenter_y"
1798 # z="$APAFrameCenter_z"/>
1799 # <rotationref ref="rIdentity"/>
1802 # <volumeref ref="volAPAFrameYOuterSupport\-$APA_i"/>
1803 # <position name="posAPAFrameYOuterSupportPos\-$APA_i" unit="cm"
1804 # x="$APAFrameCenter_x + ($APAFrameYOuterSupport_x + $APAFrameYInnerSupport_x/2 - $EdgeFrameSteelThickness/2)"
1805 # y="$APAFrameCenter_y"
1806 # z="$APAFrameCenter_z"/>
1807 # <rotationref ref="rIdentity"/>
1813 <volumeref ref="volAPAFrameYSide"/>
1814 <position name="posAPAFrameYSideNeg\-$APA_i" unit="cm"
1815 x="$APAFrameCenter_x"
1816 y="$APAFrameCenter_y"
1817 z="$APAFrameCenter_z - $APAFrame_z/2 + $APAFrameYSide_z/2"/>
1818 <rotationref ref="rIdentity"/>
1821 <volumeref ref="volAPAFrameYSide"/>
1822 <position name="posAPAFrameYSidePos\-$APA_i" unit="cm"
1823 x="$APAFrameCenter_x"
1824 y="$APAFrameCenter_y"
1825 z="$APAFrameCenter_z + $APAFrame_z/2 - $APAFrameYSide_z/2"/>
1826 <rotationref ref="rIdentity"/>
1829 <volumeref ref="volAPAFrameZSide"/>
1830 <position name="posAPAFrameZSidePos\-$APA_i" unit="cm"
1831 x="$APAFrameCenter_x"
1832 y="$APAFrameCenter_y + $APAFrame_y/2 - $APAFrameZSide_y/2"
1833 z="$APAFrameCenter_z"/>
1834 <rotationref ref="rIdentity"/>
1837 <volumeref ref="volAPAFrameZSide"/>
1838 <position name="posAPAFrameZSideNeg\-$APA_i" unit="cm"
1839 x="$APAFrameCenter_x"
1840 y="$APAFrameCenter_y - $APAFrame_y/2 + $APAFrameZSide_y/2"
1841 z="$APAFrameCenter_z"/>
1842 <rotationref ref="rIdentity"/>
1846 <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1847 - Add the *parts* of the G10 boards that exist directly in volCryostat.
1848 - There are two boards on each the up and downstream end,
1849 one each to wrap the U and V views around the APA frame
1850 - There are 4 on the bottom which anchor the U V and Z wires and the grid plane
1851 - The rest of the parts of the G10 boards must be placed directly in volTPC -->
1854 <volumeref ref="volG10BoardYSideCenterSeg"/>
1855 <position name="posG10BoardYSideCenterSeg\-Vup\-$APA_i" unit="cm"
1856 x="$APAFrameCenter_x"
1857 y="$APAFrameCenter_y"
1858 z="$APAFrameCenter_z - $APAFrame_z/2 - (0+.5)*($G10BoardYSide_z)"/>
1859 <rotationref ref="rIdentity"/>
1862 <volumeref ref="volG10BoardYSideCenterSeg"/>
1863 <position name="posG10BoardYSideCenterSeg\-Uup\-$APA_i" unit="cm"
1864 x="$APAFrameCenter_x"
1865 y="$APAFrameCenter_y"
1866 z="$APAFrameCenter_z - $APAFrame_z/2 - (1+.5)*($G10BoardYSide_z)"/>
1867 <rotationref ref="rIdentity"/>
1871 <volumeref ref="volG10BoardYSideCenterSeg"/>
1872 <position name="posG10BoardYSideCenterSeg\-Vdown\-$APA_i" unit="cm"
1873 x="$APAFrameCenter_x"
1874 y="$APAFrameCenter_y"
1875 z="$APAFrameCenter_z + $APAFrame_z/2 + (0+.5)*($G10BoardYSide_z)"/>
1876 <rotationref ref="rIdentity"/>
1879 <volumeref ref="volG10BoardYSideCenterSeg"/>
1880 <position name="posG10BoardYSideCenterSeg\-Udown\-$APA_i" unit="cm"
1881 x="$APAFrameCenter_x"
1882 y="$APAFrameCenter_y"
1883 z="$APAFrameCenter_z + $APAFrame_z/2 + (1+.5)*($G10BoardYSide_z)"/>
1884 <rotationref ref="rIdentity"/>
1888 <volumeref ref="volG10BoardZSideCenterSeg"/>
1889 <position name="posG10BoardZSideCenterSeg\-Z\-$APA_i" unit="cm"
1890 x="$APAFrameCenter_x"
1892 z="$APAFrameCenter_z"/>
1893 <rotationref ref="rIdentity"/>
1896 <volumeref ref="volG10BoardZSideCenterSeg"/>
1897 <position name="posG10BoardZSideCenterSeg\-V\-$APA_i" unit="cm"
1898 x="$APAFrameCenter_x"
1900 z="$APAFrameCenter_z"/>
1901 <rotationref ref="rIdentity"/>
1904 <volumeref ref="volG10BoardZSideCenterSeg"/>
1905 <position name="posG10BoardZSideCenterSeg\-U\-$APA_i" unit="cm"
1906 x="$APAFrameCenter_x"
1908 z="$APAFrameCenter_z"/>
1909 <rotationref ref="rIdentity"/>
1912 <volumeref ref="volG10BoardZSideCenterSeg"/>
1913 <position name="posG10BoardZSideCenterSeg\-Grid\-$APA_i" unit="cm"
1914 x="$APAFrameCenter_x"
1915 y="$posG10ZSideGrid_y"
1916 z="$APAFrameCenter_z"/>
1917 <rotationref ref="rIdentity"/>
1928 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1929 #+++++++++++++++++++++++++++++++++++++ gen_Enclosure +++++++++++++++++++++++++++++++++++++
1930 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1935 # Create the detector enclosure fragment file name,
1936 # add file to list of output GDML fragments,
1938 $ENCL = "iceberg_v1_DetEnclosure" . $suffix . ".gdml";
1939 push (@gdmlFiles, $ENCL);
1940 $ENCL = ">" . $ENCL;
1941 open(ENCL) or die("Could not open file $ENCL for writing");
1944 # The standard XML prefix and starting the gdml
1946 <?xml version='1.0'?>
1951 # All the detector enclosure solids.
1955 <box name="FoamPadBlock" lunit="cm"
1956 x="$Cryostat_x + 2*$FoamPadding"
1957 y="$Cryostat_y + 2*$FoamPadding"
1958 z="$Cryostat_z + 2*$FoamPadding" />
1960 <box name="FoamPadInner" lunit="cm"
1961 x="$Cryostat_x + 0.01"
1962 y="$Cryostat_y + 0.01"
1963 z="$Cryostat_z + 0.01" />
1965 <subtraction name="FoamPadding">
1966 <first ref="FoamPadBlock"/>
1967 <second ref="FoamPadInner"/>
1968 <positionref ref="posCenter"/>
1971 <box name="SteelSupportBlock" lunit="cm"
1972 x="$Cryostat_x + 2*$FoamPadding + 2*$SteelSupport_x"
1973 y="$Cryostat_y + 2*$FoamPadding + 2*$SteelSupport_y"
1974 z="$Cryostat_z + 2*$FoamPadding + 2*$SteelSupport_z" />
1976 <box name="SteelSupportInner" lunit="cm"
1977 x="$Cryostat_x + 2*$FoamPadding + 0.01"
1978 y="$Cryostat_y + 2*$FoamPadding + 0.01"
1979 z="$Cryostat_z + 2*$FoamPadding + 0.01" />
1981 <subtraction name="SteelSupport">
1982 <first ref="SteelSupportBlock"/>
1983 <second ref="SteelSupportInner"/>
1984 <positionref ref="posCenter"/>
1987 <box name="DetEnclosure" lunit="cm"
1997 # Detector enclosure structure
2000 <volume name="volFoamPadding">
2001 <materialref ref="FD_foam"/>
2002 <solidref ref="FoamPadding"/>
2005 <volume name="volSteelSupport">
2006 <materialref ref="AirSteelMixture"/>
2007 <solidref ref="SteelSupport"/>
2010 <volume name="volDetEnclosure">
2011 <materialref ref="Air"/>
2012 <solidref ref="DetEnclosure"/>
2015 <volumeref ref="volFoamPadding"/>
2016 <positionref ref="posCryoInDetEnc"/>
2019 <volumeref ref="volSteelSupport"/>
2020 <positionref ref="posCryoInDetEnc"/>
2023 <volumeref ref="volCryostat"/>
2024 <positionref ref="posCryoInDetEnc"/>
2043 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2044 #+++++++++++++++++++++++++++++++++++++++ gen_World +++++++++++++++++++++++++++++++++++++++
2045 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2050 # Create the WORLD fragment file name,
2051 # add file to list of output GDML fragments,
2053 $WORLD = "iceberg_v1_World" . $suffix . ".gdml";
2054 push (@gdmlFiles, $WORLD);
2055 $WORLD = ">" . $WORLD;
2056 open(WORLD) or die("Could not open file $WORLD for writing");
2059 # The standard XML prefix and starting the gdml
2061 <?xml version='1.0'?>
2066 # All the World solids.
2069 <box name="World" lunit="cm"
2070 x="$DetEncWidth+2*$RockThickness"
2071 y="$DetEncHeight+2*$RockThickness"
2072 z="$DetEncLength+2*$RockThickness"/>
2079 <volume name="volWorld" >
2080 <materialref ref="DUSEL_Rock"/>
2081 <solidref ref="World"/>
2084 <volumeref ref="volDetEnclosure"/>
2085 <position name="posDetEnclosure" unit="cm" x="$OriginXSet" y="$OriginYSet" z="$OriginZSet"/>
2093 # make_gdml.pl will take care of <setup/>
2100 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2101 #++++++++++++++++++++++++++++++++++++ write_fragments ++++++++++++++++++++++++++++++++++++
2102 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2104 sub write_fragments()
2106 # This subroutine creates an XML file that summarizes the the subfiles output
2107 # by the other sub routines - it is the input file for make_gdml.pl which will
2108 # give the final desired GDML file. Specify its name with the output option.
2109 # (you can change the name when running make_gdml)
2111 # This code is taken straigh from the similar MicroBooNE generate script, Thank you.
2113 if ( ! defined $output )
2115 $output = "-"; # write to STDOUT
2118 # Set up the output file.
2119 $OUTPUT = ">" . $output;
2120 open(OUTPUT) or die("Could not open file $OUTPUT");
2123 <?xml version='1.0'?>
2125 <!-- Input to Geometry/gdml/make_gdml.pl; define the GDML fragments
2126 that will be zipped together to create a detector description.
2133 <!-- These files contain GDML <constant></constant>
2134 blocks. They are read in separately, so they can be
2135 interpreted into the remaining GDML. See make_gdml.pl for
2141 foreach $filename (@defFiles)
2144 <filename> $filename </filename>
2154 <!-- The GDML file fragments to be zipped together. -->
2158 foreach $filename (@gdmlFiles)
2161 <filename> $filename </filename>
2177 # run the sub routines that generate the fragments
2179 gen_Define(); # generates definitions at beginning of GDML
2180 gen_Materials(); # generates materials to be used
2183 gen_TPC( $TPCInner_x, $TPC_y, $TPC_z, 'Inner');
2184 gen_TPC( $TPCOuter_x, $TPC_y, $TPC_z, 'Outer');
2188 gen_Cryostat(); # places (2*nAPAWide x nAPAHigh x nAPALong) volTPC,
2189 # half rotated 180 about Y
2190 gen_Enclosure(); # places two cryostats and concrete volumes
2192 gen_World(); # places the enclosure among DUSEL Rock
2195 write_fragments(); # writes the XML input for make_gdml.pl
2196 # which zips together the final GDML