generate_dune10kt_v2.pl
Go to the documentation of this file.
1 #!/usr/bin/perl
2 
3 # contact tylerdalion@gmail.com for any GDML/generate questions
4 # I would love to help!
5 
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
10 
11 # If you are playing with different geometries, you can use the
12 # suffix command to help organize your work.
13 
14 #use warnings;
15 use gdmlMaterials;
16 use Math::Trig;
17 use Getopt::Long;
18 use Math::BigFloat;
19 Math::BigFloat->precision(-16);
20 
21 open(my $wout, '>', 'gdmlWireCenters.txt');
22 
23 GetOptions( "help|h" => \$help,
24  "suffix|s:s" => \$suffix,
25  "workspace|k:s" => \$workspace,
26  "output|o:s" => \$output,
27  "wires|w:s" => \$wires,
28  "protoDune|p:s" => \$protoDune);
29 
30 if ( defined $help )
31 {
32  # If the user requested help, print the usage notes and exit.
33  usage();
34  exit;
35 }
36 
37 if ( ! defined $suffix )
38 {
39  # The user didn't supply a suffix, so append nothing to the file
40  # names.
41  $suffix = "";
42 }
43 else
44 {
45  # Otherwise, stick a "-" before the suffix, so that a suffix of
46  # "test" applied to filename.gdml becomes "filename-test.gdml".
47  $suffix = "-" . $suffix;
48 }
49 
50 if ( ! defined $workspace )
51 {
52  $workspace = 0;
53  if ( ! defined $protoDune )
54  {
55  $protoDune = 0;
56  print "\t\tCreating full geometry.\n";
57  }
58  elsif ( $protoDune == 1 )
59  {
60  print "\t\tCreating rough version of protoDUNE.\n";
61  }
62 }
63 elsif ( $workspace == 1)
64 {
65  print "\t\tCreating smaller (1x2x2-APA) workspace geometry.\n";
66 }
67 elsif ( $workspace == 2)
68 {
69  print "\t\tCreating 1x2x6-APA geometry.\n";
70 }
71 
72 # set wires on to be the default, unless given an input by the user
73 $wires_on = 1; # 1=on, 0=off
74 if (defined $wires)
75 {
76 $wires_on = $wires
77 }
78 
79 $tpc_on=1;
80 
81 $killOuterActive = 0;
82 
83 # options for different parameters
84 $Pitch3mmVersion = 0;
85 $UVAngle45Option = 0;
86 
87 
88 
89 #++++++++++++++++++++++++ Begin defining variables +++++++++++++++++++++++++
90 
91 ## The GDML is build from the inside out to avoid overlaps, but that means
92 ## that the larger dimensions (such as the cryostat dimensions) are calculated
93 ## to be slightly different than the parameters calculated and reported by
94 ## engineers. All of this error is within reason and for the better, since
95 ## we don't want this Geometry to be overly complex or long.
96 
97 
98 $inch = 2.54;
99 
100 ##################################################################
101 ##################### Wire Plane Parameters ######################
102 
103 # dune10kt
104 $UWirePitch = 0.4667;
105 $VWirePitch = 0.4667;
106 $XWirePitch = 0.479;
107 $UAngle = 35.710;
108 $VAngle = 35.710;
109 $nZChannelsPerAPA = 960;
110 
111 # dune10kt 3mm version
112 if($Pitch3mmVersion==1){
113  $UWirePitch = 0.3;
114  $VWirePitch = 0.3;
115  $XWirePitch = 0.3;
116  $nZChannelsPerAPA = 2*(229.44/0.3 + 1);
117 }
118 
119 # dune10kt ~45 deg UV wires version
120 if($UVAngle45Option==1){
121  $UAngle = 45.7;
122  $VAngle = 44.3;
123 }
124 
125 $nAPAWide = 3;
126 $nAPAHigh = 2;
127 $nAPALong = 25;
128 
129 if($protoDune==1){
130  $nAPAWide = 2;
131  $nAPAHigh = 1;
132  $nAPALong = 3;
133 }
134 
135 $SinUAngle = sin( deg2rad($UAngle) );
136 $CosUAngle = cos( deg2rad($UAngle) );
137 $TanUAngle = tan( deg2rad($UAngle) );
138 
139 $SinVAngle = sin( deg2rad($VAngle) );
140 $CosVAngle = cos( deg2rad($VAngle) );
141 $TanVAngle = tan( deg2rad($VAngle) );
142 
143 $UWire_yint = $UWirePitch/$SinUAngle;
144 $UWire_zint = $UWirePitch/$CosUAngle;
145 
146 $VWire_yint = $VWirePitch/$SinVAngle;
147 $VWire_zint = $VWirePitch/$CosVAngle;
148 
149 $TPCWireThickness = 0.015;
150 
151 $TPCWirePlaneThickness = $TPCWireThickness;
152 #height and length defined lower
153 
154 
155 
156 ##################################################################
157 ################### Cryostat/APA parameters ######################
158 
159 if($workspace==1){
160  $nAPAWide = 1;
161  $nAPALong = 2;
162 }
163 elsif($workspace==2){
164  $nAPAWide = 1;
165  $nAPALong = 6;
166 }
167 
168 $nAPAs = $nAPAWide*$nAPAHigh*$nAPALong;
169 
170 
171 $G10thickness = $inch/8;
172 $WrapCover = $inch/16;
173 
174 $SpaceAPAToCryoWall = 15;
175 $SpaceAPAToFloor = 59.4 - 10.2; # 10.2cm just adjusts for how spaces are reported
176 $SpaceAPAToTopLAr = 50.9 - 10.2;
177 $UpstreamLArPadding = 311.4 - 10.2;
178 $DownstreamLArPadding = 59.4 - 10.2;
179 
180 if($protoDune==1){
181  $SpaceAPAToCryoWall = 20;
182  $SpaceAPAToFloor = 45;
183  $SpaceAPAToTopLAr = 45;
184  $UpstreamLArPadding = 80;
185  $DownstreamLArPadding = 80;
186 }
187 
188  #InnerDrift is the max distance form the edge of the CPA to the edge of the first wire plane
189 $InnerDrift = 359.4;
190 $OuterDrift = $SpaceAPAToCryoWall;
191 $APAFrame_x = 5.0661; # ~2in -- this does not include the wire spacing
192 
193 $TPCWireThickness = 0.015;
194 $TPCWirePlaneThickness = $TPCWireThickness;
195 #$APAWirePlaneSpacing = 0.4730488 + $TPCWirePlaneThickness; # center to center spacing between all of the wire planes (g, u, v, and x)
196 
197 if($Pitch3mmVersion==1){
198  $APAWirePlaneSpacing = 0.3;
199 } else {
200  $APAWirePlaneSpacing = 0.476;
201 }
202 
203 # At creation of the plane volumes, the y and z boundaries will be increased
204 # by this much at each of the 4 edges. this is so the corners of the wire
205 # tubes don't extrude. For all other purposes, the plane dimensions stay as originally defined
206 $UVPlaneBoundNudge = $TPCWireThickness;
207 
208 
209 # APA z-dimensions:
210 # The following are all widths about the z center of an APA
211 $Zactive_z = ($nZChannelsPerAPA/2-1)*$XWirePitch + $TPCWireThickness;
212 $APAFrame_z = 231.59 - 2*(2*$G10thickness+$WrapCover);
213 $Vactive_z = $APAFrame_z;
214 $Uactive_z = $APAFrame_z + 2*$G10thickness;
215 $APAphys_z = 231.59;
216 
217 
218 # APA y-dimensions:
219 $ReadoutBoardOverlap = 7.61; #board overlaps wires, chop this off of their active height
220 $APAFrame_y = 606.0;
221 $Zactive_y = $APAFrame_y + 0*$G10thickness - $ReadoutBoardOverlap;
222 $Vactive_y = $APAFrame_y + 1*$G10thickness - $ReadoutBoardOverlap;
223 $Uactive_y = $APAFrame_y + 2*$G10thickness - $ReadoutBoardOverlap;
224  # the last G10 board for the grid, then a cover. This is not "covered" by the board
225 $APAphys_y = $APAFrame_y + 4*$G10thickness + $WrapCover;
226 
227 $APAGap_y = 0.4; #separation between APAs (cover to cover) along the incident beam axis
228 $APAGap_z = 0.8; #separation between APAs (cover to cover) along the vertical axis
229 
230 
231  # include APA spacing in y and z so volTPCs touch in y and z directions with correct APA
232  # spacing - this makes for smoother event generation.
233 
234 $APA_UtoU_x = $APAFrame_x + 6*$APAWirePlaneSpacing + $TPCWirePlaneThickness; # thickness of APA between its
235  # outer wire planes (center to center)
236 $TPCInner_x = $InnerDrift + 3*$APAWirePlaneSpacing + $TPCWirePlaneThickness;
237 $TPCOuter_x = $OuterDrift + 3*$APAWirePlaneSpacing + $TPCWirePlaneThickness;
238 
239 $TPC_z = $APAphys_z + $APAGap_z;
240 $TPC_y = $APAphys_y + $APAGap_y;
241 
242 $CPATube_OD = 5.066;
243 #$CPATube_ID = 4.747;
244 
245 $Cathode_x = 0.016;
246 $Cathode_y = $APAphys_y - $CPATube_OD;
247 $Cathode_z = $APAphys_z - $CPATube_OD;
248 
249 
250 $APAToAPA = $APAFrame_x
251  + 2*$TPCInner_x
252  + $Cathode_x; # center to center
253 
254 $CPAToAPA = $APAFrame_x/2
255  + $TPCInner_x
256  + $Cathode_x/2; # center to center
257 
258 $SteelThickness = 0.5*$inch; #half inch
259 $HeightGaseousAr = 50;
260 
261 $Argon_x = ($nAPAWide-1)*$APAToAPA
262  + $APA_UtoU_x + $TPCWirePlaneThickness
263  + 2*$SpaceAPAToCryoWall;
264 
265 
266 #FIELD CAGE IN (FCI)
267 $FC_x = ($nAPAWide-1)*$APAToAPA
268  + $APA_UtoU_x + $TPCWirePlaneThickness;
269 
270 if($workspace==1||$workspace==2){ # this is arbitrary for the workspace, but size down a little
271 $Argon_x = 2*$CPAToAPA + $Cathode_x + 2*$SpaceAPAToCryoWall;
272 $FC_x = 2*$CPAToAPA + $Cathode_x;
273 }
274 
275 
276 $LArgon_y = $nAPAHigh*$APAphys_y
277  + ($nAPAHigh-1)*$APAGap_y
278  + $SpaceAPAToFloor + $SpaceAPAToTopLAr;
279 $Argon_y = $LArgon_y
280  + $HeightGaseousAr;
281 
282 $Argon_z = $nAPALong*$APAphys_z
283  + ($nAPALong-1)*$APAGap_z
284  + $UpstreamLArPadding + $DownstreamLArPadding;
285 
286 $FCI_y = $nAPAHigh*$TPC_y+$FC_b; #The +FC_b is an arbitrary +2cm to make sure the FC doesn't contact the APA or CPAs.
287 $FCO_y = $FCI_y+(0.1*$inch)*2; #The outer boundary of the Fied Cage
288 $FCI_z = $nAPALong*$TPC_z
289  + $FC_b; #the plus FC_b is +2 cm arbitrarily. This makes sure the FC doesn't contact the APAs.
290 $FCO_z = $FCI_z+(0.1*$inch)*2;
291 
292 $FC_b = 2; #2 cm buffer for FC
293 
294 $Cryostat_x = $Argon_x + 2*$SteelThickness;
295 $Cryostat_y = $Argon_y + 2*$SteelThickness;
296 $Cryostat_z = $Argon_z + 2*$SteelThickness;
297 
298 
299 
300 ##################################################################
301 ############## DetEnc and World relevant parameters #############
302 
303 
304 $SteelSupport_x = 100;
305 $SteelSupport_y = 50;
306 $SteelSupport_z = 100;
307 $FoamPadding = 80;
308 $FracMassOfSteel = 0.998; #The steel support is not a solid block, but a mixture of air and steel
309 $FracMassOfAir = 1-$FracMassOfSteel;
310 
311 $SpaceSteelSupportToWall = 100;
312 $SpaceSteelSupportToCeiling = 100;
313 
314 $DetEncWidth = $Cryostat_x
315  + 2*($SteelSupport_x + $FoamPadding) + $SpaceSteelSupportToCeiling;
316 $DetEncHeight = $Cryostat_y
317  + 2*($SteelSupport_y + $FoamPadding) + 2*$SpaceSteelSupportToWall;
318 $DetEncLength = $Cryostat_z
319  + 2*($SteelSupport_z + $FoamPadding) + 2*$SpaceSteelSupportToWall;
320 
321 $posCryoInDetEnc_y = - $DetEncHeight/2 + $SteelSupport_y + $FoamPadding + $Cryostat_y/2;
322 
323 $RockThickness = 3000;
324 if ($workspace == 0){
325  # Initially, the world dimensions and the OriginZSet
326  # left only ~222cm to the world boundary from the
327  # +z boundary of volDetEnclosure. Bump that up to
328  # at least 10m for good measure.
329  # This is in an if statement so that it does not affect
330  # the workspace geometries, which are already being used
331  $RockThickness += 800
332 }
333 
334  # We want the world origin to be at the very front of the fiducial volume.
335  # move it to the front of the enclosure, then back it up through the concrete/foam,
336  # then through the Cryostat shell, then through the upstream dead LAr (including the
337  # dead LAr on the edge of the TPC, but this is covered in $UpstreamLArPadding).
338  # This is to be added to the z position of every volume in volWorld
339 
340 $OriginZSet = $DetEncLength/2
341  - $SpaceSteelSupportToWall
342  - $SteelSupport_z
343  - $FoamPadding
344  - $SteelThickness
345  - $UpstreamLArPadding
346  - ($APAphys_z - $Uactive_z)/2;
347 
348  # We want the world origin to be vertically centered between the stacked APAs.
349  # This is to be added to the y position of every volume in volWorld
350 
351 $OriginYSet = $DetEncHeight/2
352  - $SteelSupport_y
353  - $FoamPadding
354  - $SteelThickness
355  - $SpaceAPAToFloor
356  - $APAphys_y
357  - $APAGap_y/2;
358 
359 if($protoDune==1){ # bring the origin to the bottom of the APAs for protoDUNE
360  $OriginYSet = $OriginYSet + $APAphys_y + $APAGap_y/2;
361 }
362 
363 $OriginXSet = 0; # centered for now
364 
365 
366 
367 
368 
369 
370 ####################################################################
371 ######################## Paddle Dimensions ########################
372 
373 $APAFrameZSide_y = 4*$inch;
374 $APAFrameYSide_z = 4*$inch;
375 $LightPaddle_x = 0.476;
376 $LightPaddle_y = 4*$inch;
377 $LightPaddle_z = $APAFrame_z - 2*$APAFrameYSide_z;
378 $nLightPaddlesPerAPA = 10; # 10, or 20 for double coverage (for now)
379 $PaddleYInterval = (2*$APAphys_y+$APAGap_y-$LightPaddle_y-2*$APAFrameZSide_y)
380  /(2*$nLightPaddlesPerAPA-1);
381 $FrameToPaddleSpace = ($PaddleYInterval-$APAGap_y)/2;
382 
383 $SiPM_z = 0;
384 
385 # $PaddleYInterval is defined so that the center-to-center distance in the
386 # y direction between paddles is uniform between vertically stacked APAs.
387 # $FrameToPaddleSpace is from the BOTTOM of the APA frame (4" in y direction)
388 # to the CENTER of a paddle, including the 4" part of the frame. This variable's
389 # primary purpose is to position the lowest paddle in each APA.
390 
391 
392 
393 
394 #+++++++++++++++++++++++++ End defining variables ++++++++++++++++++++++++++
395 
396 
397 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
398 #+++++++++++++++++++++++++++++++++++++++++ usage +++++++++++++++++++++++++++++++++++++++++
399 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
400 
401 sub usage()
402 {
403  print "Usage: $0 [-h|--help] [-o|--output <fragments-file>] [-s|--suffix <string>]\n";
404  print " if -o is omitted, output goes to STDOUT; <fragments-file> is input to make_gdml.pl\n";
405  print " -s <string> appends the string to the file names; useful for multiple detector versions\n";
406  print " -h prints this message, then quits\n";
407 }
408 
409 
410 
411 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
412 #++++++++++++++++++++++++++++++++++++++ gen_Define +++++++++++++++++++++++++++++++++++++++
413 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
414 
415 sub gen_Define()
416 {
417 
418 # Create the <define> fragment file name,
419 # add file to list of fragments,
420 # and open it
421  $DEF = "dune10kt_v2_Def" . $suffix . ".gdml";
422  push (@gdmlFiles, $DEF);
423  $DEF = ">" . $DEF;
424  open(DEF) or die("Could not open file $DEF for writing");
425 
426 
427 print DEF <<EOF;
428 <?xml version='1.0'?>
429 <gdml>
430 <define>
431 
432 <!--
433 
434 
435 
436 -->
437 
438  <position name="posCryoInDetEnc" unit="cm" x="0" y="@{[$posCryoInDetEnc_y]}" z="0"/>
439  <position name="posCenter" unit="cm" x="0" y="0" z="0"/>
440  <rotation name="rPlus90AboutX" unit="deg" x="90" y="0" z="0"/>
441  <rotation name="rMinus90AboutY" unit="deg" x="0" y="270" z="0"/>
442  <rotation name="rMinus90AboutYMinus90AboutX" unit="deg" x="270" y="270" z="0"/>
443  <rotation name="rPlusUAngleAboutX" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
444  <rotation name="rPlusVAngleAboutX" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
445  <rotation name="rPlus180AboutX" unit="deg" x="180" y="0" z="0"/>
446  <rotation name="rPlus180AboutY" unit="deg" x="0" y="180" z="0"/>
447  <rotation name="rPlus180AboutXPlus180AboutY" unit="deg" x="180" y="180" z="0"/>
448  <rotation name="rIdentity" unit="deg" x="0" y="0" z="0"/>
449 </define>
450 </gdml>
451 EOF
452  close (DEF);
453 }
454 
455 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
456 #+++++++++++++++++++++++++++++++++++++ gen_Materials +++++++++++++++++++++++++++++++++++++
457 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
458 
459 sub gen_Materials()
460 {
461 
462 # Create the <materials> fragment file name,
463 # add file to list of output GDML fragments,
464 # and open it
465  $MAT = "dune10kt_v2_Materials" . $suffix . ".gdml";
466  push (@gdmlFiles, $MAT);
467  $MAT = ">" . $MAT;
468 
469  open(MAT) or die("Could not open file $MAT for writing");
470 
471  # Add any materials special to this geometry by defining a mulitline string
472  # and passing it to the gdmlMaterials::gen_Materials() function.
473 
474  $DensityAirSteel = 1/(0.001205/$FracMassOfAir + 7.9300/$FracMassOfSteel);
475 
476 my $asmix = <<EOF;
477  <!-- preliminary values -->
478  <material name="AirSteelMixture" formula="AirSteelMixture">
479  <D value="$DensityAirSteel" unit="g/cm3"/>
480  <fraction n="$FracMassOfSteel" ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
481  <fraction n="$FracMassOfAir" ref="Air"/>
482  </material>
483 EOF
484 
485  # add the general materials used anywere
486  print MAT gdmlMaterials::gen_Materials( $asmix );
487 
488  close(MAT);
489 }
490 
491 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
492 #++++++++++++++++++++++++++++++++++++++++ gen_TPC ++++++++++++++++++++++++++++++++++++++++
493 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
494 
495 
496 sub gen_TPC
497 {
498 
499 # $_[0] = $TPC_x
500 # $_[1] = $TPC_y
501 # $_[2] = $TPC_z
502 # $_[3] = 'name'
503 
504  my $TPCActive_x = $_[0]-(3*$APAWirePlaneSpacing);
505  my $TPCActive_y = $_[1] - $APAGap_y/2 - $ReadoutBoardOverlap ; #TODO: make the Active height more accurate
506  my $TPCActive_z = $_[2];
507 
508 
509 #constructs everything inside volTPC, namely
510 # (moving from left to right, or from +x to -x)
511 # -volCPActive
512 # -volTPCPlaneU: with wires angled from vertical slightly different than in V
513 # -volTPCPlaneV: with wires angled from vertical slightly differently than in U
514 # -volTPCPlaneX: with vertical wires
515 
516 
517 # Create the TPC fragment file name,
518 # add file to list of output GDML fragments,
519 # and open it
520  $TPC = "dune10kt_v2_TPC_${_[3]}" . $suffix . ".gdml";
521  push (@gdmlFiles, $TPC);
522  $TPC = ">" . $TPC;
523  open(TPC) or die("Could not open file $TPC for writing");
524 
525 
526 print $wout "\n\n\n----- Wires for $_[3] -----\n\n\n";
527 
528 
529 # The standard XML prefix and starting the gdml
530  print TPC <<EOF;
531 <?xml version='1.0'?>
532 <gdml>
533 EOF
534 
535 
536 # All the TPC solids save the wires.
537 print TPC <<EOF;
538 <solids>
539  <box name="$_[3]" lunit="cm"
540  x="@{[$_[0]]}"
541  y="@{[$_[1]]}"
542  z="@{[$_[2]]}"/>
543  <box name="${_[3]}UPlane" lunit="cm"
544  x="@{[$TPCWirePlaneThickness]}"
545  y="@{[$Uactive_y + $UVPlaneBoundNudge]}"
546  z="@{[$Uactive_z + $UVPlaneBoundNudge]}"/>
547  <box name="${_[3]}VPlane" lunit="cm"
548  x="@{[$TPCWirePlaneThickness]}"
549  y="@{[$Vactive_y + $UVPlaneBoundNudge]}"
550  z="@{[$Vactive_z + $UVPlaneBoundNudge]}"/>
551  <box name="${_[3]}ZPlane" lunit="cm"
552  x="@{[$TPCWirePlaneThickness]}"
553  y="@{[$Zactive_y]}"
554  z="@{[$Zactive_z]}"/>
555  <box name="${_[3]}Active" lunit="cm"
556  x="@{[$TPCActive_x]}"
557  y="@{[$TPCActive_y]}"
558  z="@{[$TPCActive_z]}"/>
559 EOF
560 
561 
562 #++++++++++++++++++++++++++++ Wire Solids ++++++++++++++++++++++++++++++
563 
564 print TPC <<EOF;
565 
566  <tube name="${_[3]}WireVert"
567  rmax="@{[0.5*$TPCWireThickness]}"
568  z="@{[$Zactive_y]}"
569  deltaphi="360"
570  aunit="deg"
571  lunit="cm"/>
572 EOF
573 
574 # Set number of wires to default to zero, when $wires_on = 0, for a low memory
575 # version. But if $wires_on = 1, calculate the number of wires on each side of each
576 # plane to be used in the for loops
577 
578 my $NumberCornerUWires = 0;
579 my $NumberSideUWires = 0;
580 my $NumberCommonUWires = 0;
581 my $NumberCornerVWires = 0;
582 my $NumberSideVWires = 0;
583 my $NumberCommonVWires = 0;
584 my $NumberVerticalWires = 0;
585 
586 if ($wires_on == 1)
587 {
588  # Number of wires in one corner
589 $NumberCornerUWires = int( $APAFrame_z/($UWirePitch/$CosUAngle) );
590 
591 $NumberCornerVWires = int( $APAFrame_z/($VWirePitch/$CosVAngle) );
592 
593 
594  # Total number of wires touching one vertical (longer) side
595  # Note that the total number of wires per plane is this + another set of corner wires
596 $NumberSideUWires = int( $Uactive_y/$UWire_yint );
597 if($Pitch3mmVersion==1){ $NumberSideUWires = $NumberSideUWires-1; }
598 
599 $NumberSideVWires = int( $Vactive_y/$VWire_yint );
600 
601  # Number of wires per side that aren't cut off by the corner
602 $NumberCommonUWires = $NumberSideUWires - $NumberCornerUWires;
603 
604 $NumberCommonVWires = $NumberSideVWires - $NumberCornerVWires;
605 
606  # Number of wires on the vertical plane
607  # Since APA Active z is defined in docdb 3383 to be distance
608  # between outer vertical wires, + 1 since the floor of this
609  # division will be one under, giving the amt of spaces, not wires
610 $NumberVerticalWires = int( $Zactive_z/$XWirePitch ) + 1;
611 #$NumberVerticalWires = 960;
612 
613 
614 $nUchans = 2*$NumberCornerUWires;
615 $nVchans = 2*$NumberCornerVWires;
616 
617 print $wout "$nUchans U channels\n";
618 print $wout "$nVchans V channels\n";
619 print $wout "$NumberVerticalWires Z channels per side\n";
620 
621 print $wout "$NumberCornerUWires U corner wires\n";
622 print $wout "$NumberCommonUWires U common wires\n";
623 print $wout "$NumberCornerVWires V corner wires\n";
624 print $wout "$NumberCommonVWires V common wires\n";
625 
626 }
627 
628 # hard codeed number will be a factor determined from engineering spreadsheets on wire endpoints,
629 # but since that won't exist for a while, use this number to avoid overlaps
630 my $FirstUWireOffset = .55 + $G10thickness + 2*$G10thickness*$TanUAngle - $UWire_zint;
631 my $FirstVWireOffset = .5; # doesnt include a G10 board in width
632 
633 if($Pitch3mmVersion==1){
634  my $FirstUWireOffset = .15 + $G10thickness + 2*$G10thickness*$TanUAngle - $UWire_zint;
635  my $FirstVWireOffset = .15; # doesnt include a G10 board in width
636 }
637 
638 if($UVAngle45Option==1){$FirstVWireOffset = .7;}
639 
640 
641 my $FirstTopUWire_yspan =
642  $Uactive_y/2
643  - ( - $Uactive_y/2
644  + $FirstUWireOffset/$TanUAngle # walk us up to the first wire
645  + $UWire_yint*($NumberSideUWires-1) # up to the top of the top common wire
646  - $Uactive_z/$TanUAngle # back to the bottom of the top common wire
647  + $UWire_yint); # nudge up to bottom of the first top corner wire
648 
649 my $FirstTopVWire_yspan =
650  $Vactive_y/2
651  - ( - $Vactive_y/2
652  + $FirstVWireOffset/$TanVAngle # walk us up to the first wire
653  + $VWire_yint*($NumberSideVWires-1) # up to the top of the top common wire
654  - $Vactive_z/$TanVAngle # back to the bottom of the top common wire
655  + $VWire_yint); # nudge up to bottom of the first top corner wire
656 
657 
658 # The corner wires for the U plane
659 if ($wires_on==1)
660 {
661  for ($i = 0; $i < $NumberCornerUWires; $i++)
662  {
663  $CornerUWireLength[$i] = ($FirstUWireOffset + $i*$UWire_zint)/$SinUAngle;
664 
665  print TPC <<EOF;
666  <tube name="${_[3]}WireU$i"
667  rmax="@{[0.5*$TPCWireThickness]}"
668  z="@{[$CornerUWireLength[$i]]}"
669  deltaphi="360"
670  aunit="deg"
671  lunit="cm"/>
672 EOF
673 
674  }
675 
676  $CommonUWireLength = $Uactive_z/$SinUAngle;
677 
678  print TPC <<EOF;
679  <tube name="${_[3]}WireUCommon"
680  rmax="@{[0.5*$TPCWireThickness]}"
681  z="@{[$CommonUWireLength]}"
682  deltaphi="360"
683  aunit="deg"
684  lunit="cm"/>
685 EOF
686 
687  for ($i = 0; $i < $NumberCornerUWires; $i++)
688  {
689 
690  $TopCornerUWireLength[$i] = ($FirstTopUWire_yspan - $i*$UWire_yint)/$CosUAngle;
691 
692  $j = $i + $NumberSideUWires;
693 
694  print TPC <<EOF;
695  <tube name="${_[3]}WireU$j"
696  rmax="@{[0.5*$TPCWireThickness]}"
697  z="@{[$TopCornerUWireLength[$i]]}"
698  deltaphi="360"
699  aunit="deg"
700  lunit="cm"/>
701 EOF
702 
703  }
704 
705 }
706 
707 
708 # The corner wires for the V plane
709 if ($wires_on==1)
710 {
711  for ($i = 0; $i < $NumberCornerVWires; ++$i)
712  {
713  $CornerVWireLength[$i] = ($FirstVWireOffset + $i*$VWire_zint)/$SinVAngle;
714 
715  print TPC <<EOF;
716 
717  <tube name="${_[3]}WireV$i"
718  rmax="@{[0.5*$TPCWireThickness]}"
719  z="@{[$CornerVWireLength[$i]]}"
720  deltaphi="360"
721  aunit="deg"
722  lunit="cm"/>
723 
724 EOF
725 
726  }
727 
728  # The wire used many times in the middle of the V plane
729  # Same subtraction as U common
730 
731  $CommonVWireLength = $Vactive_z/$SinVAngle;
732 
733  print TPC <<EOF;
734  <tube name="${_[3]}WireVCommon"
735  rmax="@{[0.5*$TPCWireThickness]}"
736  z="@{[$CommonVWireLength]}"
737  deltaphi="360"
738  aunit="deg"
739  lunit="cm"/>
740 EOF
741 
742  for ($i = 0; $i < $NumberCornerVWires; $i++)
743  {
744 
745  $TopCornerVWireLength[$i] = ($FirstTopVWire_yspan - $i*$VWire_yint)/$CosVAngle;
746 
747  $j = $i + $NumberSideVWires;
748 
749  print TPC <<EOF;
750  <tube name="${_[3]}WireV$j"
751  rmax="@{[0.5*$TPCWireThickness]}"
752  z="@{[$TopCornerVWireLength[$i]]}"
753  deltaphi="360"
754  aunit="deg"
755  lunit="cm"/>
756 EOF
757 
758  }
759 
760 
761 }
762 
763 # Begin structure and create the vertical wire logical volume
764 print TPC <<EOF;
765 </solids>
766 <structure>
767  <volume name="volTPCActive${_[3]}">
768  <materialref ref="LAr"/>
769  <solidref ref="${_[3]}Active"/>
770  </volume>
771 
772 EOF
773 
774 
775 if ($wires_on==1)
776 {
777  print TPC <<EOF;
778  <volume name="volTPCWireVert${_[3]}">
779  <materialref ref="Copper_Beryllium_alloy25"/>
780  <solidref ref="${_[3]}WireVert"/>
781  </volume>
782 EOF
783 
784  # Corner U wires logical volumes
785  for ($i = 0; $i < $NumberCornerUWires; ++$i)
786  {
787  print TPC <<EOF;
788  <volume name="volTPCWireU$i${_[3]}">
789  <materialref ref="Copper_Beryllium_alloy25"/>
790  <solidref ref="${_[3]}WireU$i"/>
791  </volume>
792 EOF
793  }
794 
795 
796  # Top Corner U wires logical volumes
797  for ($j = $NumberSideUWires; $j < $NumberSideUWires + $NumberCornerUWires; ++$j)
798  {
799  print TPC <<EOF;
800  <volume name="volTPCWireU$j${_[3]}">
801  <materialref ref="Copper_Beryllium_alloy25"/>
802  <solidref ref="${_[3]}WireU$j"/>
803  </volume>
804 EOF
805  }
806 
807 
808  # Common U wire logical volume, referenced many times
809  print TPC <<EOF;
810  <volume name="volTPCWireUCommon${_[3]}">
811  <materialref ref="Copper_Beryllium_alloy25"/>
812  <solidref ref="${_[3]}WireUCommon"/>
813  </volume>
814 EOF
815 
816 
817  # Corner V wires logical volumes
818  for ($i = 0; $i < $NumberCornerVWires; ++$i)
819  {
820  print TPC <<EOF;
821  <volume name="volTPCWireV$i${_[3]}">
822  <materialref ref="Copper_Beryllium_alloy25"/>
823  <solidref ref="${_[3]}WireV$i"/>
824  </volume>
825 EOF
826 
827  }
828 
829  # Top Corner V wires logical volumes
830  for ($j = $NumberSideVWires; $j < $NumberSideVWires + $NumberCornerVWires; ++$j)
831  {
832  print TPC <<EOF;
833  <volume name="volTPCWireV$j${_[3]}">
834  <materialref ref="Copper_Beryllium_alloy25"/>
835  <solidref ref="${_[3]}WireV$j"/>
836  </volume>
837 EOF
838  }
839 
840  # Common V wire logical volume, referenced many times
841  print TPC <<EOF;
842  <volume name="volTPCWireVCommon${_[3]}">
843  <materialref ref="Copper_Beryllium_alloy25"/>
844  <solidref ref="${_[3]}WireVCommon"/>
845  </volume>
846 EOF
847 
848 }
849 
850 
851 my $lastYpos = 0;
852 my $lastZpos = 0;
853 
854 
855 #+++++++++++++++++++++++++ Position physical wires ++++++++++++++++++++++++++
856 
857 # ++++++++++++++++++++++ U Plane +++++++++++++++++++++++
858 
859 # Create U plane logical volume
860 print TPC <<EOF;
861  <volume name="volTPCPlaneU${_[3]}">
862  <materialref ref="LAr"/>
863  <solidref ref="${_[3]}UPlane"/>
864 EOF
865 
866 
867 print $wout "\n- Wires for U plane -\n\n";
868 print $wout " Uplane_y: $Uactive_y\n";
869 print $wout " Uplane_z: $Uactive_z\n";
870 
871 
872 if ($wires_on==1)
873 {
874 
875 # Starting with the bottom left corner wires:
876  # x=0 to center the wires in the plane
877  # y positioning: (-0.5*$TPCWirePlaneHeight) starts the incremental increase
878  # from the bottom of the plane, and trigonometry gives the increment
879  # z positioning: Looking at the plane from the positive x direction,
880  # (0.5*$TPCWirePlaneLength) starts the incremental increase from
881  # the lower left corner.
882  # rotation: same as common wire in code below
883 
884  $FirstU_ypos = - $Uactive_y/2 + $FirstUWireOffset/$TanUAngle/2;
885  $FirstU_zpos = + $Uactive_z/2 - $FirstUWireOffset/2;
886 
887 for ($i = 0; $i < $NumberCornerUWires; ++$i)
888 {
889 
890 my $ypos = $FirstU_ypos + ($i)*0.5*$UWire_yint;
891 my $zpos = $FirstU_zpos - ($i)*0.5*$UWire_zint;
892 
893 $pitch = ($ypos - $lastYpos) * $SinUAngle
894  - ($zpos - $lastZpos) * $CosUAngle;
895 
896 print TPC <<EOF;
897  <physvol>
898  <volumeref ref="volTPCWireU$i${_[3]}"/>
899  <position name="pos${_[3]}WireU$i" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
900  <rotation name="rUAngle$i" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
901  </physvol>
902 EOF
903 
904 $topY = $ypos + ($CosUAngle*$CornerUWireLength[$i]/2);
905 $bottomY = $ypos - ($CosUAngle*$CornerUWireLength[$i]/2);
906 $edgeZ_p = $zpos + ($SinUAngle*$CornerUWireLength[$i]/2);
907 $edgeZ_m = $zpos - ($SinUAngle*$CornerUWireLength[$i]/2);
908 print $wout "U$i: ( $ypos , $zpos ) (pitch = $pitch)\n";
909 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
910 
911 $lastYpos = $ypos;
912 $lastZpos = $zpos;
913 
914 }
915 
916 
917 # Moving upwards to the common wires:
918  # x and z are zero to center the wires along a vertical axis
919  # y positioning: The trick is positioning the lowest common wire so that the pitch
920  # is consistent, then the increment is double the increment of
921  # the corner wires since there is no z incriment.
922  # rotation: wires in \\\\ direction, so +90deg to bring them to vertical and
923  # +UAngle counterclockwise to arrive at proper orientation
924 # Note that the counter maintains wire number (in pos. name) counting bottom to top
925 
926 
927 my $StartCommonUWires_ypos = $lastYpos + $UWire_yint - abs( $lastZpos )/$TanUAngle;
928 
929 for ($i = $NumberCornerUWires; $i < $NumberSideUWires; ++$i)
930 {
931 
932  $j = $i - $NumberCornerUWires;
933  my $ypos = $StartCommonUWires_ypos + $UWire_yint*($j);
934 
935  $lastWnum = $i-1;
936  if ( $ypos < $lastYpos ){ print "WARNING: y position dropped from $lastYpos (wire U$lastWnum) to $ypos (wire U$i)\n"; }
937  if ( $ypos == $lastYpos ){ print "WARNING: y position between wire U$lastWnum and U$lastWnum did not move: $ypos\n"; }
938 
939 
940 $pitch = ($ypos - $lastYpos) * $SinUAngle - ($zpos - $lastZpos) * $CosUAngle ;
941 
942 print TPC <<EOF;
943  <physvol>
944  <volumeref ref="volTPCWireUCommon${_[3]}"/>
945  <position name="pos${_[3]}WireU$i" unit="cm" x="0" y="@{[$ypos ]}" z="0"/>
946  <rotation name="rUAngle$i" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
947  </physvol>
948 EOF
949 
950 $topY = $ypos + ($CosUAngle*$CommonUWireLength/2);
951 $bottomY = $ypos - ($CosUAngle*$CommonUWireLength/2);
952 $edgeZ_p = + ($SinUAngle*$CommonUWireLength/2);
953 $edgeZ_m = - ($SinUAngle*$CommonUWireLength/2);
954 print $wout "U$i: ( $ypos , 0 ) (pitch = $pitch)\n";
955 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
956 
957 $lastYpos = $ypos;
958 $lastZpos = 0;
959 
960 }
961 
962 
963 
964 my $FirstTopUWire_zspan = $FirstTopUWire_yspan*$TanUAngle;
965 my $StartTopUWires_ypos = + $Uactive_y/2 - $FirstTopUWire_yspan/2;
966 my $StartTopUWires_zpos = - $Uactive_z/2 + $FirstTopUWire_zspan/2;
967 
968 # Finally moving to the corner wires on the top right:
969  # x=0 to center the wires in the plane
970  # y positioning: plug wire number into same equation
971  # z positioning: start at z=0 and go negatively at the same z increment
972  # rotation: same as common wire in code above
973 # note that the counter maintains wire number shown in the position name
974 
975 for ($j = $NumberSideUWires; $j < $NumberSideUWires+$NumberCornerUWires; ++$j)
976 {
977 
978 $i = $j - $NumberSideUWires;
979 
980 my $ypos = $StartTopUWires_ypos + ($i)*0.5*$UWire_yint;
981 my $zpos = $StartTopUWires_zpos - ($i)*0.5*$UWire_zint;
982 
983  $lastWnum = $j-1;
984  if ( $ypos < $lastYpos ){ print "WARNING: y position dropped from $lastYpos (wire U$lastWnum) to $ypos (wire U$j)\n"; }
985  if ( $ypos == $lastYpos ){ print "WARNING: y position between wire U$lastWnum and U$j did not move: $ypos\n"; }
986 
987 $pitch = ($ypos - $lastYpos) * $SinUAngle - ($zpos - $lastZpos) * $CosUAngle ;
988 
989 print TPC <<EOF;
990  <physvol>
991  <volumeref ref="volTPCWireU$j${_[3]}"/>
992  <position name="pos${_[3]}WireU$j" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
993  <rotation name="rUAngle$j" unit="deg" x="@{[90-$UAngle]}" y="0" z="0"/>
994  </physvol>
995 EOF
996 
997 $topY = $ypos + ($CosUAngle*$TopCornerUWireLength[$i]/2);
998 $bottomY = $ypos - ($CosUAngle*$TopCornerUWireLength[$i]/2);
999 $edgeZ_p = $zpos + ($SinUAngle*$TopCornerUWireLength[$i]/2);
1000 $edgeZ_m = $zpos - ($SinUAngle*$TopCornerUWireLength[$i]/2);
1001 print $wout "U$j: ( $ypos , $zpos ) (pitch = $pitch)\n";
1002 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1003 
1004 $lastYpos = $ypos;
1005 $lastZpos = $zpos;
1006 
1007 }
1008 
1009 } #ends if wires on
1010 
1011 
1012 # ++++++++++++++++++++++ V Plane +++++++++++++++++++++++
1013 
1014 # End U plane and create V plane logical volume
1015 print TPC <<EOF;
1016  </volume>
1017 
1018  <volume name="volTPCPlaneV${_[3]}">
1019  <materialref ref="LAr"/>
1020  <solidref ref="${_[3]}VPlane"/>
1021 EOF
1022 
1023 print $wout "\n- Wires for V plane -\n\n";
1024 print $wout " Vplane_y: $Vactive_y\n";
1025 print $wout " Vplane_z: $Vactive_z\n";
1026 
1027 if ($wires_on==1)
1028 {
1029 
1030 
1031 # Starting with the bottom right corner wires:
1032  # x=0 to center the wires in the plane
1033  # y positioning: (-0.5*$TPCWirePlaneHeight) starts the incremental increase
1034  # from the bottom of the plane, and trigonometry gives the increment
1035  # z positioning: Looking at the plane from the positive x direction,
1036  # (-0.5*$TPCWirePlaneLength) starts the incremental increase from
1037  # the lower right corner.
1038  # rotation: same as common wire in code below
1039 
1040  $FirstV_ypos = - $Vactive_y/2 + $FirstVWireOffset/$TanVAngle/2;
1041  $FirstV_zpos = - $Vactive_z/2 + $FirstVWireOffset/2;
1042 
1043 for ($i = 0; $i < $NumberCornerVWires; ++$i)
1044 {
1045 
1046 my $ypos = $FirstV_ypos + ($i)*0.5*$VWire_yint;
1047 my $zpos = $FirstV_zpos + ($i)*0.5*$VWire_zint;
1048 
1049 print TPC <<EOF;
1050  <physvol>
1051  <volumeref ref="volTPCWireV$i${_[3]}"/>
1052  <position name="pos${_[3]}WireV$i" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
1053  <rotation name="rVAngle$i" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1054  </physvol>
1055 EOF
1056 
1057 $topY = $ypos + ($CosVAngle*$CornerVWireLength[$i]/2);
1058 $bottomY = $ypos - ($CosVAngle*$CornerVWireLength[$i]/2);
1059 $edgeZ_p = $zpos + ($SinVAngle*$CornerVWireLength[$i]/2);
1060 $edgeZ_m = $zpos - ($SinVAngle*$CornerVWireLength[$i]/2);
1061 print $wout "V$i: ( $ypos , $zpos ) \n";
1062 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1063 
1064 $lastYpos = $ypos;
1065 $lastZpos = $zpos;
1066 
1067 }
1068 
1069 
1070 # Moving upwards to the common wires:
1071  # x and z are zero to center the wires along a vertical axis
1072  # y positioning: Plug wire number into the same corner ypos equation
1073  # rotation: wires in //// direction, so +90deg to bring them to vertical and
1074  # --VAngle counterclockwise to arrive at proper orientation
1075 # Note that the counter maintains wire number in the position name
1076 
1077 my $StartCommonVWires_ypos = $lastYpos + $VWire_yint - abs( $lastZpos )/$TanVAngle;
1078 
1079 for ($i = $NumberCornerVWires; $i < $NumberSideVWires; ++$i)
1080 {
1081 
1082  $j = $i - $NumberCornerVWires;
1083  my $ypos = $StartCommonVWires_ypos + $VWire_yint*($j);
1084 
1085 print TPC <<EOF;
1086  <physvol>
1087  <volumeref ref="volTPCWireVCommon${_[3]}"/>
1088  <position name="pos${_[3]}WireV$i" unit="cm" x="0" y="@{[$ypos ]}" z="0"/>
1089  <rotation name="rVAngle$i" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1090  </physvol>
1091 EOF
1092 
1093 $topY = $ypos + ($CosVAngle*$CommonVWireLength/2);
1094 $bottomY = $ypos - ($CosVAngle*$CommonVWireLength/2);
1095 $edgeZ_p = + ($SinVAngle*$CommonVWireLength/2);
1096 $edgeZ_m = - ($SinVAngle*$CommonVWireLength/2);
1097 print $wout "V$i: ( $ypos , 0 ) \n";
1098 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1099 
1100 $lastYpos = $ypos;
1101 #$lastZpos = $zpos; always 0
1102 
1103 }
1104 
1105 
1106 my $FirstTopVWire_zspan = $FirstTopVWire_yspan*$TanVAngle;
1107 my $StartTopVWires_ypos = + $Vactive_y/2 - $FirstTopVWire_yspan/2;
1108 my $StartTopVWires_zpos = + $Vactive_z/2 - $FirstTopVWire_zspan/2;
1109 
1110 # Finally moving to the corner wires on the top right:
1111  # x=0 to center the wires in the plane
1112  # y positioning: plug wire number into same equation
1113  # z positioning: start at z=0 and go positively at the same z increment
1114  # rotation: same as common wire in code above
1115 # note that the counter maintains wire number shown in the position name
1116 
1117 for ($j = $NumberSideVWires; $j < $NumberSideVWires+$NumberCornerVWires; ++$j)
1118 {
1119 
1120 $i = $j - $NumberSideVWires;
1121 
1122 my $ypos = $StartTopVWires_ypos + ($i)*0.5*$VWire_yint;
1123 my $zpos = $StartTopVWires_zpos + ($i)*0.5*$VWire_zint;
1124 
1125 print TPC <<EOF;
1126  <physvol>
1127  <volumeref ref="volTPCWireV$j${_[3]}"/>
1128  <position name="pos${_[3]}WireV$j" unit="cm" x="0" y="@{[$ypos ]}" z="@{[$zpos]}"/>
1129  <rotation name="rVAngle$j" unit="deg" x="@{[90+$VAngle]}" y="0" z="0"/>
1130  </physvol>
1131 EOF
1132 
1133 $topY = $ypos + ($CosVAngle*$TopCornerVWireLength[$i]/2);
1134 $bottomY = $ypos - ($CosVAngle*$TopCornerVWireLength[$i]/2);
1135 $edgeZ_p = $zpos + ($SinVAngle*$TopCornerVWireLength[$i]/2);
1136 $edgeZ_m = $zpos - ($SinVAngle*$TopCornerVWireLength[$i]/2);
1137 print $wout "V$j: ( $ypos , $zpos ) \n";
1138 print $wout " -- Y: $bottomY to $topY -- Z: $edgeZ_m to $edgeZ_p \n";
1139 
1140 }
1141 
1142 
1143 
1144 
1145 
1146 
1147 } #ends if wires on
1148 
1149 
1150 
1151 # ++++++++++++++++++++++ Z Plane +++++++++++++++++++++++
1152 
1153 # End V plane and create Z plane logical volume
1154 print TPC <<EOF;
1155  </volume>
1156 
1157  <volume name="volTPCPlaneZ${_[3]}">
1158  <materialref ref="LAr"/>
1159  <solidref ref="${_[3]}ZPlane"/>
1160 EOF
1161 
1162 if ($wires_on==1)
1163 {
1164 
1165 # This is the simplest plane, one loop creates all of the wires
1166  # x and y position at zero to center the wires
1167  # z position: moving from front of detector to back, in the positive z direction,
1168  # starting at (-0.5*$TPCWirePlaneLength), the right side looking from
1169  # the +x direction
1170 
1171 for ($i=0; $i<$NumberVerticalWires; ++$i)
1172 {
1173 my $zpos = (-0.5*$Zactive_z) + $i*$XWirePitch + $TPCWireThickness/2;
1174 
1175 print TPC <<EOF;
1176  <physvol>/
1177  <volumeref ref="volTPCWireVert${_[3]}"/>
1178  <position name="pos${_[3]}WireZ$i" unit="cm" x="0" y="0 " z="@{[$zpos]}"/>
1179  <rotationref ref="rPlus90AboutX"/>
1180  </physvol>
1181 EOF
1182 
1183 }
1184 
1185 } #ends if wires on
1186 
1187 print TPC <<EOF;
1188  </volume>
1189 EOF
1190 
1191 #+++++++++++++++++++++ ^^ Position physical wires Above ^^ +++++++++++++++++++++
1192 
1193 ## make the TPC active volume extend down to the G10 for the grid
1194 
1195  my $BottomOfAPA = - $TPC_y/2 + $APAGap_y/2;
1196 
1197 
1198  $posZplane[0] = -$_[0]/2 + $APAWirePlaneSpacing - $TPCWirePlaneThickness/2;
1199  $posZplane[1] = $BottomOfAPA + $WrapCover + 4*$G10thickness + $Zactive_y/2;
1200  $posZplane[2] = 0;
1201 
1202  $posVplane[0] = $posZplane[0] + $APAWirePlaneSpacing;
1203  $posVplane[1] = $BottomOfAPA + $WrapCover + 3*$G10thickness + $Vactive_y/2;
1204  $posVplane[2] = $posZplane[2];
1205 
1206  $posUplane[0] = $posVplane[0] + $APAWirePlaneSpacing;
1207  $posUplane[1] = $BottomOfAPA + $WrapCover + 2*$G10thickness + $Uactive_y/2;
1208  $posUplane[2] = $posZplane[2];
1209 
1210  $posTPCActive[0] = $posUplane[0] + ($TPCWirePlaneThickness/2 + $TPCActive_x/2);
1211  $posTPCActive[1] = -$_[1]/2 + $TPCActive_y/2;
1212  $posTPCActive[2] = 0;
1213 
1214 #wrap up the TPC file
1215 print TPC <<EOF;
1216  <volume name="volTPC${_[3]}">
1217  <materialref ref="LAr"/>
1218  <solidref ref="${_[3]}"/>
1219  <physvol>
1220  <volumeref ref="volTPCPlaneZ${_[3]}"/>
1221  <position name="pos${_[3]}PlaneZ" unit="cm"
1222  x="@{[$posZplane[0]]}" y="@{[$posZplane[1]]}" z="@{[$posZplane[2]]}"/>
1223  <rotationref ref="rIdentity"/>
1224  </physvol>
1225  <physvol>
1226  <volumeref ref="volTPCPlaneV${_[3]}"/>
1227  <position name="pos${_[3]}PlaneV" unit="cm"
1228  x="@{[$posVplane[0]]}" y="@{[$posVplane[1]]}" z="@{[$posVplane[2]]}"/>
1229  <rotationref ref="rIdentity"/>
1230  </physvol>
1231  <physvol>
1232  <volumeref ref="volTPCPlaneU${_[3]}"/>
1233  <position name="pos${_[3]}PlaneU" unit="cm"
1234  x="@{[$posUplane[0]]}" y="@{[$posUplane[1]]}" z="@{[$posUplane[2]]}"/>
1235  <rotationref ref="rIdentity"/>
1236  </physvol>
1237 EOF
1238 
1239 # Option to omit the active volume on the outside for the prototype.
1240 if( !($killOuterActive==1 && $_[3] eq 'Outer') ){
1241 print TPC <<EOF;
1242  <physvol>
1243  <volumeref ref="volTPCActive${_[3]}"/>
1244  <position name="pos${_[3]}Active" unit="cm"
1245  x="@{[$posTPCActive[0]]}" y="@{[$posTPCActive[1]]}" z="@{[$posTPCActive[2]]}"/>
1246  <rotationref ref="rIdentity"/>
1247  </physvol>
1248 EOF
1249 }
1250 
1251 print TPC <<EOF;
1252  </volume>
1253 </structure>
1254 </gdml>
1255 EOF
1256 
1257  close(TPC);
1258 
1259 } #end of sub gen_TPC
1260 
1261 
1262 
1263 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1264 #++++++++++++++++++++++++++++++++++++++ gen_Cryostat +++++++++++++++++++++++++++++++++++++
1265 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1266 
1267 sub gen_Cryostat()
1268 {
1269 
1270 # Create the cryostat fragment file name,
1271 # add file to list of output GDML fragments,
1272 # and open it
1273  $CRYO = "dune10kt_v2_Cryostat" . $suffix . ".gdml";
1274  push (@gdmlFiles, $CRYO);
1275  $CRYO = ">" . $CRYO;
1276  open(CRYO) or die("Could not open file $CRYO for writing");
1277 
1278 
1279 # The standard XML prefix and starting the gdml
1280  print CRYO <<EOF;
1281 <?xml version='1.0'?>
1282 <gdml>
1283 EOF
1284 
1285 $APAFrameZSide_x = $APAFrame_x;
1286 $APAFrameZSide_y = 4*$inch;
1287 $APAFrameZSide_z = $APAFrame_z;
1288 
1289 $APAFrameYSide_x = $APAFrame_x;
1290 $APAFrameYSide_y = $APAFrame_y-2*$APAFrameZSide_y;
1291 $APAFrameYSide_z = 4*$inch;
1292 
1293 # Two outer Y supports will sandwich the light paddles
1294 $APAFrameYOuterSupport_x = ($APAFrame_x-$LightPaddle_x)/2;
1295 $APAFrameYOuterSupport_y = $APAFrame_y-2*$APAFrameZSide_y;
1296 $APAFrameYOuterSupport_z = 4*$inch;
1297 
1298 $EdgeFrameSteelThickness = 0.12*$inch;
1299 $InnerFrameSteelThickness = 0.062*$inch;
1300 
1301 
1302 $G10BoardYSide_x = $APAFrame_x;
1303 $G10BoardYSide_y = $APAFrame_y;
1304 $G10BoardYSide_z = $G10thickness;
1305 
1306 $G10BoardZSide_x = $APAFrame_x;
1307 $G10BoardZSide_y = $G10thickness;
1308 $G10BoardZSide_z = $APAFrame_z;
1309 
1310 ##################################################################
1311 ################### Field Cage Y and Z centers ###################
1312 
1313 
1314 $FC_y_center = 0.0;
1315 $FC_z_center = 0.0;
1316 for($k=0 ; $k<$nAPALong ; $k++) #TODO!!! Factor out these loops so that the calculation of each APA center for placing APAs (happens later) will always agree with placing the center of the Field Cage.
1317 {
1318  $tmp_APACenter_z = - $Argon_z/2
1319  + $UpstreamLArPadding
1320  + $APAphys_z/2
1321  + $k*($APAphys_z+$APAGap_z);
1322  $FC_z_center = $FC_z_center + $tmp_APACenter_z;
1323 }
1324 $FC_z_center = $FC_z_center / $nAPALong;
1325 
1326 for($j=0 ; $j<$nAPAHigh ; $j++) # nAPAHigh always going to be 2
1327 {
1328  $tmp_APACenter_y = - $Argon_y/2 + $SpaceAPAToFloor
1329  + $APAphys_y/2
1330  + $j*($APAphys_y+$APAGap_y);
1331  $FC_y_center = $FC_y_center + $tmp_APACenter_y;
1332 }
1333 $FC_y_center = $FC_y_center / $nAPAHigh;
1334 
1335 # All the cryostat solids.
1336 print CRYO <<EOF;
1337 <solids>
1338  <box name="Cryostat" lunit="cm"
1339  x="@{[$Cryostat_x]}"
1340  y="@{[$Cryostat_y]}"
1341  z="@{[$Cryostat_z]}"/>
1342  <box name="ArgonInterior" lunit="cm"
1343  x="@{[$Argon_x]}"
1344  y="@{[$Argon_y]}"
1345  z="@{[$Argon_z]}"/>
1346  <box name="FieldCageOut" lunit="cm"
1347  x="@{[$FC_x]}"
1348  y="@{[$FCO_y]}"
1349  z="@{[$FCO_z]}"/>
1350  <box name="FieldCageIn" lunit="cm"
1351  x="@{[$FC_x+1]}"
1352  y="@{[$FCI_y]}"
1353  z="@{[$FCI_z]}"/>
1354  <subtraction name="FieldCage">
1355  <first ref="FieldCageOut"/>
1356  <second ref="FieldCageIn"/>
1357  </subtraction>
1358  <box name="GaseousArgon" lunit="cm"
1359  x="@{[$Argon_x]}"
1360  y="@{[$HeightGaseousAr]}"
1361  z="@{[$Argon_z]}"/>
1362  <subtraction name="SteelShell">
1363  <first ref="Cryostat"/>
1364  <second ref="ArgonInterior"/>
1365  </subtraction>
1366  <box name="Cathode" lunit="cm"
1367  x="@{[$Cathode_x]}"
1368  y="@{[$Cathode_y]}"
1369  z="@{[$Cathode_z]}"/>
1370 
1371  <box name="LightPaddle" lunit="cm"
1372  x="@{[$LightPaddle_x]}"
1373  y="@{[$LightPaddle_y]}"
1374  z="@{[$LightPaddle_z + $SiPM_z]}"/>
1375 
1376  <box name="APAFrameYSideHollow" lunit="cm"
1377  x="@{[$APAFrameYSide_x-2*$EdgeFrameSteelThickness]}"
1378  y="@{[$APAFrameYSide_y-2*$EdgeFrameSteelThickness]}"
1379  z="@{[$APAFrameYSide_z]}"/>
1380  <box name="APAFrameYSideShell" lunit="cm"
1381  x="@{[$APAFrameYSide_x]}"
1382  y="@{[$APAFrameYSide_y]}"
1383  z="@{[$APAFrameYSide_z]}"/>
1384  <subtraction name="APAFrameYSide">
1385  <first ref="APAFrameYSideShell"/>
1386  <second ref="APAFrameYSideHollow"/>
1387  <positionref ref="posCenter"/>
1388  <rotationref ref="rIdentity"/>
1389  </subtraction>
1390 
1391  <box name="APAFrameZSideHollow" lunit="cm"
1392  x="@{[$APAFrameZSide_x-2*$EdgeFrameSteelThickness]}"
1393  y="@{[$APAFrameZSide_y-2*$EdgeFrameSteelThickness]}"
1394  z="@{[$APAFrameZSide_z]}"/>
1395  <box name="APAFrameZSideShell" lunit="cm"
1396  x="@{[$APAFrameZSide_x]}"
1397  y="@{[$APAFrameZSide_y]}"
1398  z="@{[$APAFrameZSide_z]}"/>
1399  <subtraction name="APAFrameZSide">
1400  <first ref="APAFrameZSideShell"/>
1401  <second ref="APAFrameZSideHollow"/>
1402  <positionref ref="posCenter"/>
1403  <rotationref ref="rIdentity"/>
1404  </subtraction>
1405 
1406  <box name="APAFrameYOuterSupport" lunit="cm"
1407  x="@{[$EdgeFrameSteelThickness]}"
1408  y="@{[$APAFrameYOuterSupport_y]}"
1409  z="@{[$APAFrameYOuterSupport_z]}"/>
1410 
1411 
1412  <box name="G10BoardYSideCenterSeg" lunit="cm"
1413  x="@{[$G10BoardYSide_x]}"
1414  y="@{[$G10BoardYSide_y]}"
1415  z="@{[$G10BoardYSide_z]}"/>
1416 
1417  <box name="G10BoardZSideCenterSeg" lunit="cm"
1418  x="@{[$G10BoardZSide_x]}"
1419  y="@{[$G10BoardZSide_y]}"
1420  z="@{[$G10BoardZSide_z]}"/>
1421 
1422 </solids>
1423 EOF
1424 
1425 # Cryostat structure
1426 print CRYO <<EOF;
1427 <structure>
1428  <volume name="volSteelShell">
1429  <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1430  <solidref ref="SteelShell" />
1431  </volume>
1432  <volume name="volFieldCage">
1433  <materialref ref="ALUMINUM_Al"/>
1434  <solidref ref="FieldCage"/>
1435  </volume>
1436  <volume name="volGaseousArgon">
1437  <materialref ref="ArGas"/>
1438  <solidref ref="GaseousArgon"/>
1439  </volume>
1440  <volume name="volCathode">
1441  <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1442  <solidref ref="Cathode" />
1443  </volume>
1444 EOF
1445 
1446 for($i=0 ; $i<$nAPAs ; $i++){
1447 for($p=0 ; $p<10 ; $p++){
1448 print CRYO <<EOF;
1449  <volume name="volOpDetSensitive_$i\-$p">
1450  <materialref ref="Acrylic"/>
1451  <solidref ref="LightPaddle"/>
1452  </volume>
1453 EOF
1454 }
1455 }
1456 
1457 
1458 print CRYO <<EOF;
1459 
1460  <volume name="volAPAFrameYSide">
1461  <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1462  <solidref ref="APAFrameYSide"/>
1463  </volume>
1464 
1465  <volume name="volAPAFrameZSide">
1466  <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1467  <solidref ref="APAFrameZSide"/>
1468  </volume>
1469 
1470  <volume name="volAPAFrameYOuterSupport">
1471  <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
1472  <solidref ref="APAFrameYOuterSupport"/>
1473  </volume>
1474 
1475  <volume name="volG10BoardYSideCenterSeg">
1476  <materialref ref="G10"/>
1477  <solidref ref="G10BoardYSideCenterSeg"/>
1478  </volume>
1479 
1480  <volume name="volG10BoardZSideCenterSeg">
1481  <materialref ref="G10"/>
1482  <solidref ref="G10BoardZSideCenterSeg"/>
1483  </volume>
1484 
1485  <volume name="volCryostat">
1486  <materialref ref="LAr" />
1487  <solidref ref="Cryostat" />
1488  <physvol>
1489  <volumeref ref="volGaseousArgon"/>
1490  <position name="posGaseousArgon" unit="cm" x="0" y="@{[$Argon_y/2-$HeightGaseousAr/2]}" z="0"/>
1491  </physvol>
1492  <physvol>
1493  <volumeref ref="volFieldCage"/>
1494  <position name="posFieldCage" unit="cm"
1495  x="0"
1496  y="@{[$FC_y_center]}"
1497  z="@{[$FC_z_center]}"/>
1498  </physvol>
1499  <physvol>
1500  <volumeref ref="volSteelShell"/>
1501  <position name="posSteelShell" unit="cm" x="0" y="0" z="0"/>
1502  </physvol>
1503 EOF
1504 
1505 # nested for loops to place the non-rotated AND rotated volTPC
1506  # x loop rotation: There are six drift volumes. Looking into the
1507  # detector from incident direction, and counting from right (-x) to
1508  # left (+x), odd number volumes need to be rotated 180deg about Y in
1509  # order for the cathode to be on the right of the APA.
1510 
1511 if ($tpc_on==1) {
1512 
1513  $apa_i=0;
1514  $cpa_i=0;
1515 
1516  for($k=0 ; $k<$nAPALong ; $k++)
1517  {
1518  $APACenter_z = - $Argon_z/2
1519  + $UpstreamLArPadding
1520  + $APAphys_z/2
1521  + $k*($APAphys_z+$APAGap_z);
1522 
1523 
1524  for($j=0 ; $j<$nAPAHigh ; $j++) # nAPAHigh always going to be 2
1525  { # $j=0 for bottom APAs
1526  # $j=1 for top APAs
1527  $APACenter_y = - $Argon_y/2 + $SpaceAPAToFloor
1528  + $APAphys_y/2
1529  + $j*($APAphys_y+$APAGap_y);
1530 
1531 
1532  if( $workspace == 0 )
1533  {
1534 
1535  for($i=0 ; $i<$nAPAWide ; $i++)
1536  {
1537 
1538 
1539  $APACenter_x = - $Argon_x/2
1540  + $SpaceAPAToCryoWall + $APA_UtoU_x/2 + $TPCWirePlaneThickness/2
1541  + $i*$APAToAPA;
1542 
1543  $CPA_x = $APACenter_x + $CPAToAPA;
1544 
1545 
1546  place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, $j);
1547  place_OpDets($APACenter_x, $APACenter_y, $APACenter_z, $apa_i);
1548  $tpc_0 = 2*$apa_i+0;
1549  $tpc_1 = 2*$apa_i+1;
1550  $apa_i++;
1551 
1552  $SelectTPC_0 = "Inner";
1553  $SelectTPC_1 = "Inner";
1554  $TPC_0_x = $TPCInner_x;
1555  $TPC_1_x = $TPCInner_x;
1556  $rot_0 = "rPlus180AboutY";
1557  $rot_1 = "rIdentity";
1558  if($i == 0) { $SelectTPC_0 = "Outer"; $TPC_0_x = $TPCOuter_x; }
1559  if($i == $nAPAWide-1) { $SelectTPC_1 = "Outer"; $TPC_1_x = $TPCOuter_x; }
1560  if($j == 0) { $rot_0 = "rPlus180AboutXPlus180AboutY";
1561  $rot_1 = "rPlus180AboutX"; } #put the readout end at the bottom for bottom APAs
1562 
1563 
1564 
1565 print CRYO <<EOF;
1566 
1567  <physvol>
1568  <volumeref ref="volTPC$SelectTPC_0"/>
1569  <position name="posTPC\-$tpc_0" unit="cm"
1570  x="@{[$APACenter_x - $APAFrame_x/2 - $TPC_0_x/2]}"
1571  y="@{[$APACenter_y]}"
1572  z="@{[$APACenter_z]}"/>
1573  <rotationref ref="$rot_0"/>
1574  </physvol>
1575  <physvol>
1576  <volumeref ref="volTPC$SelectTPC_1"/>
1577  <position name="posTPC\-$tpc_1" unit="cm"
1578  x="@{[$APACenter_x + $APAFrame_x/2 + $TPC_1_x/2]}"
1579  y="@{[$APACenter_y]}"
1580  z="@{[$APACenter_z]}"/>
1581  <rotationref ref="$rot_1"/>
1582  </physvol>
1583 
1584 EOF
1585 
1586 
1587 if( $i < $nAPAWide - 1 ){ # avoid placeing the last row of CPAs since the APAs are on the outside
1588 
1589 print CRYO <<EOF;
1590 
1591  <physvol>
1592  <volumeref ref="volCathode"/>
1593  <position name="posCathode\-$cpa_i" unit="cm"
1594  x="@{[$CPA_x]}"
1595  y="@{[$APACenter_y]}"
1596  z="@{[$APACenter_z]}"/>
1597  <rotationref ref="rIdentity"/>
1598  </physvol>
1599 
1600 EOF
1601  $cpa_i++;
1602 }
1603 
1604 
1605  } #wide
1606 
1607  } # end if not the smaller workspace
1608 
1609 
1610  # Make the workspace have only one center APA with CPAs and the full drift on either side
1611  elsif( $workspace == 1 || $workspace==2 ){
1612 
1613  $APACenter_x = 0;
1614  $CPA_0_x = $APACenter_x - $CPAToAPA;
1615  $CPA_1_x = $APACenter_x + $CPAToAPA;
1616 
1617 
1618  place_APA($APACenter_x, $APACenter_y, $APACenter_z, $apa_i, $j);
1619  place_OpDets($APACenter_x, $APACenter_y, $APACenter_z, $apa_i);
1620 
1621  $tpc_0 = 2*$apa_i+0;
1622  $tpc_1 = 2*$apa_i+1;
1623  $apa_i++;
1624 
1625  $rot_0 = "rPlus180AboutY";
1626  $rot_1 = "rIdentity";
1627  if($j == 0) { $rot_0 = "rPlus180AboutXPlus180AboutY";
1628  $rot_1 = "rPlus180AboutX"; } #put the readout end at the bottom for bottom APAs
1629 
1630 print CRYO <<EOF;
1631 
1632  <physvol>
1633  <volumeref ref="volTPCInner"/>
1634  <position name="posTPC\-$tpc_0" unit="cm"
1635  x="@{[$APACenter_x - $APAFrame_x/2 - $TPCInner_x/2]}"
1636  y="@{[$APACenter_y]}"
1637  z="@{[$APACenter_z]}"/>
1638  <rotationref ref="$rot_0"/>
1639  </physvol>
1640  <physvol>
1641  <volumeref ref="volTPCInner"/>
1642  <position name="posTPC\-$tpc_1" unit="cm"
1643  x="@{[$APACenter_x + $APAFrame_x/2 + $TPCInner_x/2]}"
1644  y="@{[$APACenter_y]}"
1645  z="@{[$APACenter_z]}"/>
1646  <rotationref ref="$rot_1"/>
1647  </physvol>
1648 
1649  <physvol>
1650  <volumeref ref="volCathode"/>
1651  <position name="posCathode\-$apa_i-0" unit="cm"
1652  x="@{[$CPA_0_x]}"
1653  y="@{[$APACenter_y]}"
1654  z="@{[$APACenter_z]}"/>
1655  <rotationref ref="rIdentity"/>
1656  </physvol>
1657  <physvol>
1658  <volumeref ref="volCathode"/>
1659  <position name="posCathode\-$apa_i-1" unit="cm"
1660  x="@{[$CPA_1_x]}"
1661  y="@{[$APACenter_y]}"
1662  z="@{[$APACenter_z]}"/>
1663  <rotationref ref="rIdentity"/>
1664  </physvol>
1665 
1666 EOF
1667 
1668  } # if the smaller workspace
1669 
1670 
1671  } #high
1672  } #long
1673 
1674 }# end if tpc
1675 
1676 print CRYO <<EOF;
1677  </volume>
1678 </structure>
1679 </gdml>
1680 EOF
1681 
1682 close(CRYO);
1683 }
1684 
1685 
1686 
1687 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1688 #++++++++++++++++++++++++++++++++++++ place_OpDets +++++++++++++++++++++++++++++++++++++++
1689 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1690 
1691 sub place_OpDets()
1692 {
1693 
1694  $APACenter_x = $_[0];
1695  $APACenter_y = $_[1];
1696  $APACenter_z = $_[2];
1697  $apa_i = $_[3];
1698 
1699 for ($paddle = 0; $paddle<$nLightPaddlesPerAPA; $paddle++)
1700 {
1701 
1702  # All Light Paddle centers will have the same
1703  # X coordinate as the center of the current APA
1704  # Z coordinate as the current TPC pair
1705  # The Y coordinate must be looped over:
1706 
1707  #the multiplication by j here is a temporary dirty trick to get around some strange behavior
1708 
1709  $Paddle_Y = $APACenter_y
1710  - $APAphys_y/2
1711  + $j*$FrameToPaddleSpace
1712  + (1-$j)*($LightPaddle_y/2 + $APAFrameZSide_y)
1713  + $PaddleYInterval*$paddle;
1714 
1715  # Alternate the paddle orientations
1716  if ( $paddle % 2 == 0 ) { $rot = "rIdentity"; }
1717  else { $rot = "rPlus180AboutY"; }
1718 
1719 
1720  print CRYO <<EOF;
1721  <physvol>
1722  <volumeref ref="volOpDetSensitive_$apa_i\-$paddle"/>
1723  <position name="posPaddle\-$paddle\-TPC\-$i\-$j\-$k" unit="cm"
1724  x="@{[$APACenter_x]}"
1725  y="@{[$Paddle_Y]}"
1726  z="@{[$APACenter_z + $SiPM_z/2]}"/>
1727  <rotationref ref="$rot"/>
1728  </physvol>
1729 EOF
1730 
1731 }#end Paddle for-loop
1732 
1733 }
1734 
1735 
1736 
1737 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1738 #++++++++++++++++++++++++++++++++++++++ place_APA ++++++++++++++++++++++++++++++++++++++++
1739 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1740 
1741 
1742 # Must be called only within gen_Cryostat(),
1743 
1744 
1745 # $_[0] = x APA physical center
1746 # $_[1] = y APA physical center
1747 # $_[2] = z APA physical center
1748 # $_[3] = APA number
1749 # $_[4] = 0 for APA with readout on bottom
1750 # 1 for APA with readout on top
1751 
1752 sub place_APA()
1753 {
1754 
1755  $APA_i = $_[3];
1756 
1757 ####################################################################
1758 ################# APA Frame and Paddle Dimensions ##################
1759 
1760 # The center passed to this function is the physical APA center,
1761 # which is not quite the frame's center, since there are more boards
1762 # at the bottom. Transform them:
1763 
1764  $APAFrameCenter_x = $_[0];
1765  $APAFrameCenter_z = $_[2];
1766 
1767 # The bottom APAs are upside down relative to how the TPC is initially generated,
1768 # and the center needs to be slightly shifted since there is extra G10 on the
1769 # end that doesn't read out.
1770 
1771  if($_[4]==1) # top APAs
1772  {
1773  $APAFrameCenter_y = $_[1] - $APAphys_y/2
1774  + $WrapCover + 4*$G10thickness
1775  + $APAFrame_y/2;
1776  }
1777  elsif($_[4]==0) # bottom APAs
1778  {
1779  $APAFrameCenter_y = $_[1] + $APAphys_y/2
1780  - $WrapCover - 4*$G10thickness
1781  - $APAFrame_y/2;
1782  }
1783  else{ print "APA not labeled as top or bottom"; }
1784 
1785 $APAFrameZSide_x = $APAFrame_x;
1786 $APAFrameZSide_y = 4*$inch;
1787 $APAFrameZSide_z = $APAFrame_z;
1788 
1789 $APAFrameYSide_x = $APAFrame_x;
1790 $APAFrameYSide_y = $APAFrame_y-2*$APAFrameZSide_y;
1791 $APAFrameYSide_z = 4*$inch;
1792 
1793 # Two outer Y supports will sandwich the light paddles
1794 $APAFrameYOuterSupport_x = ($APAFrame_x-$LightPaddle_x)/2;
1795 $APAFrameYOuterSupport_y = $APAFrame_y-2*$APAFrameZSide_y;
1796 $APAFrameYOuterSupport_z = 4*$inch;
1797 
1798 # if there were an inner support to fill the hole
1799 $APAFrameYInnerSupport_x = $LightPaddle_x;
1800 
1801 $EdgeFrameSteelThickness = 0.12*$inch;
1802 $InnerFrameSteelThickness = 0.062*$inch;
1803 
1804 
1805 $G10BoardYSide_x = $APAFrame_x;
1806 $G10BoardYSide_y = $APAFrame_y;
1807 $G10BoardYSide_z = $G10thickness;
1808 
1809 $G10BoardZSide_x = $APAFrame_x;
1810 $G10BoardZSide_y = $G10thickness;
1811 $G10BoardZSide_z = $APAFrame_z;
1812 
1813 if($_[4]==1) # top APAs
1814 {
1815  $posG10ZSideZ_y = $APAFrameCenter_y - $APAFrame_y/2 - (0+.5)*($G10BoardZSide_y);
1816  $posG10ZSideV_y = $APAFrameCenter_y - $APAFrame_y/2 - (1+.5)*($G10BoardZSide_y);
1817  $posG10ZSideU_y = $APAFrameCenter_y - $APAFrame_y/2 - (2+.5)*($G10BoardZSide_y);
1818  $posG10ZSideGrid_y = $APAFrameCenter_y - $APAFrame_y/2 - (3+.5)*($G10BoardZSide_y);
1819 }
1820 elsif($_[4]==0) # bottom APAs
1821 {
1822  $posG10ZSideZ_y = $APAFrameCenter_y + $APAFrame_y/2 + (0+.5)*($G10BoardZSide_y);
1823  $posG10ZSideV_y = $APAFrameCenter_y + $APAFrame_y/2 + (1+.5)*($G10BoardZSide_y);
1824  $posG10ZSideU_y = $APAFrameCenter_y + $APAFrame_y/2 + (2+.5)*($G10BoardZSide_y);
1825  $posG10ZSideGrid_y = $APAFrameCenter_y + $APAFrame_y/2 + (3+.5)*($G10BoardZSide_y);
1826 }
1827 else{ print "APA not labeled as top or bottom"; }
1828 
1829  # First put in the frame
1830 # print CRYO <<EOF;
1831 #<!--
1832 # <physvol>
1833 # <volumeref ref="volAPAFrameYOuterSupport\-$APA_i"/>
1834 # <position name="posAPAFrameYOuterSupportNeg\-$APA_i" unit="cm"
1835 # x="$APAFrameCenter_x - ($APAFrameYOuterSupport_x + $APAFrameYInnerSupport_x/2 - $EdgeFrameSteelThickness/2)"
1836 # y="$APAFrameCenter_y"
1837 # z="$APAFrameCenter_z"/>
1838 # <rotationref ref="rIdentity"/>
1839 # </physvol>
1840 # <physvol>
1841 # <volumeref ref="volAPAFrameYOuterSupport\-$APA_i"/>
1842 # <position name="posAPAFrameYOuterSupportPos\-$APA_i" unit="cm"
1843 # x="$APAFrameCenter_x + ($APAFrameYOuterSupport_x + $APAFrameYInnerSupport_x/2 - $EdgeFrameSteelThickness/2)"
1844 # y="$APAFrameCenter_y"
1845 # z="$APAFrameCenter_z"/>
1846 # <rotationref ref="rIdentity"/>
1847 # </physvol>
1848 #-->
1849 #EOF
1850  print CRYO <<EOF;
1851  <physvol>
1852  <volumeref ref="volAPAFrameYSide"/>
1853  <position name="posAPAFrameYSideNeg\-$APA_i" unit="cm"
1854  x="@{[$APAFrameCenter_x]}"
1855  y="@{[$APAFrameCenter_y]}"
1856  z="@{[$APAFrameCenter_z - $APAFrame_z/2 + $APAFrameYSide_z/2]}"/>
1857  <rotationref ref="rIdentity"/>
1858  </physvol>
1859  <physvol>
1860  <volumeref ref="volAPAFrameYSide"/>
1861  <position name="posAPAFrameYSidePos\-$APA_i" unit="cm"
1862  x="@{[$APAFrameCenter_x]}"
1863  y="@{[$APAFrameCenter_y]}"
1864  z="@{[$APAFrameCenter_z + $APAFrame_z/2 - $APAFrameYSide_z/2]}"/>
1865  <rotationref ref="rIdentity"/>
1866  </physvol>
1867  <physvol>
1868  <volumeref ref="volAPAFrameZSide"/>
1869  <position name="posAPAFrameZSidePos\-$APA_i" unit="cm"
1870  x="@{[$APAFrameCenter_x]}"
1871  y="@{[$APAFrameCenter_y + $APAFrame_y/2 - $APAFrameZSide_y/2]}"
1872  z="@{[$APAFrameCenter_z]}"/>
1873  <rotationref ref="rIdentity"/>
1874  </physvol>
1875  <physvol>
1876  <volumeref ref="volAPAFrameZSide"/>
1877  <position name="posAPAFrameZSideNeg\-$APA_i" unit="cm"
1878  x="@{[$APAFrameCenter_x]}"
1879  y="@{[$APAFrameCenter_y - $APAFrame_y/2 + $APAFrameZSide_y/2]}"
1880  z="@{[$APAFrameCenter_z]}"/>
1881  <rotationref ref="rIdentity"/>
1882  </physvol>
1883 
1884 
1885  <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1886  - Add the *parts* of the G10 boards that exist directly in volCryostat.
1887  - There are two boards on each the up and downstream end,
1888  one each to wrap the U and V views around the APA frame
1889  - There are 4 on the bottom which anchor the U V and Z wires and the grid plane
1890  - The rest of the parts of the G10 boards must be placed directly in volTPC -->
1891 
1892  <physvol>
1893  <volumeref ref="volG10BoardYSideCenterSeg"/>
1894  <position name="posG10BoardYSideCenterSeg\-Vup\-$APA_i" unit="cm"
1895  x="@{[$APAFrameCenter_x]}"
1896  y="@{[$APAFrameCenter_y]}"
1897  z="@{[$APAFrameCenter_z - $APAFrame_z/2 - (0+.5)*($G10BoardYSide_z)]}"/>
1898  <rotationref ref="rIdentity"/>
1899  </physvol>
1900  <physvol>
1901  <volumeref ref="volG10BoardYSideCenterSeg"/>
1902  <position name="posG10BoardYSideCenterSeg\-Uup\-$APA_i" unit="cm"
1903  x="@{[$APAFrameCenter_x]}"
1904  y="@{[$APAFrameCenter_y]}"
1905  z="@{[$APAFrameCenter_z - $APAFrame_z/2 - (1+.5)*($G10BoardYSide_z)]}"/>
1906  <rotationref ref="rIdentity"/>
1907  </physvol>
1908 
1909  <physvol>
1910  <volumeref ref="volG10BoardYSideCenterSeg"/>
1911  <position name="posG10BoardYSideCenterSeg\-Vdown\-$APA_i" unit="cm"
1912  x="@{[$APAFrameCenter_x]}"
1913  y="@{[$APAFrameCenter_y]}"
1914  z="@{[$APAFrameCenter_z + $APAFrame_z/2 + (0+.5)*($G10BoardYSide_z)]}"/>
1915  <rotationref ref="rIdentity"/>
1916  </physvol>
1917  <physvol>
1918  <volumeref ref="volG10BoardYSideCenterSeg"/>
1919  <position name="posG10BoardYSideCenterSeg\-Udown\-$APA_i" unit="cm"
1920  x="@{[$APAFrameCenter_x]}"
1921  y="@{[$APAFrameCenter_y]}"
1922  z="@{[$APAFrameCenter_z + $APAFrame_z/2 + (1+.5)*($G10BoardYSide_z)]}"/>
1923  <rotationref ref="rIdentity"/>
1924  </physvol>
1925 
1926  <physvol>
1927  <volumeref ref="volG10BoardZSideCenterSeg"/>
1928  <position name="posG10BoardZSideCenterSeg\-Z\-$APA_i" unit="cm"
1929  x="@{[$APAFrameCenter_x]}"
1930  y="@{[$posG10ZSideZ_y]}"
1931  z="@{[$APAFrameCenter_z]}"/>
1932  <rotationref ref="rIdentity"/>
1933  </physvol>
1934  <physvol>
1935  <volumeref ref="volG10BoardZSideCenterSeg"/>
1936  <position name="posG10BoardZSideCenterSeg\-V\-$APA_i" unit="cm"
1937  x="@{[$APAFrameCenter_x]}"
1938  y="@{[$posG10ZSideV_y]}"
1939  z="@{[$APAFrameCenter_z]}"/>
1940  <rotationref ref="rIdentity"/>
1941  </physvol>
1942  <physvol>
1943  <volumeref ref="volG10BoardZSideCenterSeg"/>
1944  <position name="posG10BoardZSideCenterSeg\-U\-$APA_i" unit="cm"
1945  x="@{[$APAFrameCenter_x]}"
1946  y="@{[$posG10ZSideU_y]}"
1947  z="@{[$APAFrameCenter_z]}"/>
1948  <rotationref ref="rIdentity"/>
1949  </physvol>
1950  <physvol>
1951  <volumeref ref="volG10BoardZSideCenterSeg"/>
1952  <position name="posG10BoardZSideCenterSeg\-Grid\-$APA_i" unit="cm"
1953  x="@{[$APAFrameCenter_x]}"
1954  y="@{[$posG10ZSideGrid_y]}"
1955  z="@{[$APAFrameCenter_z]}"/>
1956  <rotationref ref="rIdentity"/>
1957  </physvol>
1958 
1959 EOF
1960 
1961 
1962 }
1963 
1964 
1965 
1966 
1967 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1968 #+++++++++++++++++++++++++++++++++++++ gen_Enclosure +++++++++++++++++++++++++++++++++++++
1969 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1970 
1971 sub gen_Enclosure()
1972 {
1973 
1974 # Create the detector enclosure fragment file name,
1975 # add file to list of output GDML fragments,
1976 # and open it
1977  $ENCL = "dune10kt_v2_DetEnclosure" . $suffix . ".gdml";
1978  push (@gdmlFiles, $ENCL);
1979  $ENCL = ">" . $ENCL;
1980  open(ENCL) or die("Could not open file $ENCL for writing");
1981 
1982 
1983 # The standard XML prefix and starting the gdml
1984  print ENCL <<EOF;
1985 <?xml version='1.0'?>
1986 <gdml>
1987 EOF
1988 
1989 
1990 # All the detector enclosure solids.
1991 print ENCL <<EOF;
1992 <solids>
1993 
1994  <box name="FoamPadBlock" lunit="cm"
1995  x="@{[$Cryostat_x + 2*$FoamPadding]}"
1996  y="@{[$Cryostat_y + 2*$FoamPadding]}"
1997  z="@{[$Cryostat_z + 2*$FoamPadding]}" />
1998 
1999  <box name="FoamPadInner" lunit="cm"
2000  x="@{[$Cryostat_x + 0.01]}"
2001  y="@{[$Cryostat_y + 0.01]}"
2002  z="@{[$Cryostat_z + 0.01]}" />
2003 
2004  <subtraction name="FoamPadding">
2005  <first ref="FoamPadBlock"/>
2006  <second ref="FoamPadInner"/>
2007  <positionref ref="posCenter"/>
2008  </subtraction>
2009 
2010  <box name="SteelSupportBlock" lunit="cm"
2011  x="@{[$Cryostat_x + 2*$FoamPadding + 2*$SteelSupport_x]}"
2012  y="@{[$Cryostat_y + 2*$FoamPadding + 2*$SteelSupport_y]}"
2013  z="@{[$Cryostat_z + 2*$FoamPadding + 2*$SteelSupport_z]}" />
2014 
2015  <box name="SteelSupportInner" lunit="cm"
2016  x="@{[$Cryostat_x + 2*$FoamPadding + 0.01]}"
2017  y="@{[$Cryostat_y + 2*$FoamPadding + 0.01]}"
2018  z="@{[$Cryostat_z + 2*$FoamPadding + 0.01]}" />
2019 
2020  <subtraction name="SteelSupport">
2021  <first ref="SteelSupportBlock"/>
2022  <second ref="SteelSupportInner"/>
2023  <positionref ref="posCenter"/>
2024  </subtraction>
2025 
2026  <box name="DetEnclosure" lunit="cm"
2027  x="@{[$DetEncWidth]}"
2028  y="@{[$DetEncHeight]}"
2029  z="@{[$DetEncLength]}"/>
2030 
2031 </solids>
2032 EOF
2033 
2034 
2035 
2036 # Detector enclosure structure
2037  print ENCL <<EOF;
2038 <structure>
2039  <volume name="volFoamPadding">
2040  <materialref ref="FD_foam"/>
2041  <solidref ref="FoamPadding"/>
2042  </volume>
2043 
2044  <volume name="volSteelSupport">
2045  <materialref ref="AirSteelMixture"/>
2046  <solidref ref="SteelSupport"/>
2047  </volume>
2048 
2049  <volume name="volDetEnclosure">
2050  <materialref ref="Air"/>
2051  <solidref ref="DetEnclosure"/>
2052 
2053  <physvol>
2054  <volumeref ref="volFoamPadding"/>
2055  <positionref ref="posCryoInDetEnc"/>
2056  </physvol>
2057  <physvol>
2058  <volumeref ref="volSteelSupport"/>
2059  <positionref ref="posCryoInDetEnc"/>
2060  </physvol>
2061  <physvol>
2062  <volumeref ref="volCryostat"/>
2063  <positionref ref="posCryoInDetEnc"/>
2064  </physvol>
2065 EOF
2066 
2067 
2068 
2069  print ENCL <<EOF;
2070  </volume>
2071 EOF
2072 
2073 print ENCL <<EOF;
2074 </structure>
2075 </gdml>
2076 EOF
2077 
2078 close(ENCL);
2079 }
2080 
2081 
2082 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2083 #+++++++++++++++++++++++++++++++++++++++ gen_World +++++++++++++++++++++++++++++++++++++++
2084 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2085 
2086 sub gen_World()
2087 {
2088 
2089 # Create the WORLD fragment file name,
2090 # add file to list of output GDML fragments,
2091 # and open it
2092  $WORLD = "dune10kt_v2_World" . $suffix . ".gdml";
2093  push (@gdmlFiles, $WORLD);
2094  $WORLD = ">" . $WORLD;
2095  open(WORLD) or die("Could not open file $WORLD for writing");
2096 
2097 
2098 # The standard XML prefix and starting the gdml
2099  print WORLD <<EOF;
2100 <?xml version='1.0'?>
2101 <gdml>
2102 EOF
2103 
2104 
2105 # All the World solids.
2106 print WORLD <<EOF;
2107 <solids>
2108  <box name="World" lunit="cm"
2109  x="@{[$DetEncWidth+2*$RockThickness]}"
2110  y="@{[$DetEncHeight+2*$RockThickness]}"
2111  z="@{[$DetEncLength+2*$RockThickness]}"/>
2112 </solids>
2113 EOF
2114 
2115 # World structure
2116 print WORLD <<EOF;
2117 <structure>
2118  <volume name="volWorld" >
2119  <materialref ref="DUSEL_Rock"/>
2120  <solidref ref="World"/>
2121 
2122  <physvol>
2123  <volumeref ref="volDetEnclosure"/>
2124  <position name="posDetEnclosure" unit="cm" x="@{[$OriginXSet]}" y="@{[$OriginYSet]}" z="@{[$OriginZSet]}"/>
2125  </physvol>
2126 
2127  </volume>
2128 </structure>
2129 </gdml>
2130 EOF
2131 
2132 # make_gdml.pl will take care of <setup/>
2133 
2134 close(WORLD);
2135 }
2136 
2137 
2138 
2139 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2140 #++++++++++++++++++++++++++++++++++++ write_fragments ++++++++++++++++++++++++++++++++++++
2141 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2142 
2143 sub write_fragments()
2144 {
2145  # This subroutine creates an XML file that summarizes the the subfiles output
2146  # by the other sub routines - it is the input file for make_gdml.pl which will
2147  # give the final desired GDML file. Specify its name with the output option.
2148  # (you can change the name when running make_gdml)
2149 
2150  # This code is taken straigh from the similar MicroBooNE generate script, Thank you.
2151 
2152  if ( ! defined $output )
2153  {
2154  $output = "-"; # write to STDOUT
2155  }
2156 
2157  # Set up the output file.
2158  $OUTPUT = ">" . $output;
2159  open(OUTPUT) or die("Could not open file $OUTPUT");
2160 
2161  print OUTPUT <<EOF;
2162 <?xml version='1.0'?>
2163 
2164 <!-- Input to Geometry/gdml/make_gdml.pl; define the GDML fragments
2165  that will be zipped together to create a detector description.
2166  -->
2167 
2168 <config>
2169 
2170  <constantfiles>
2171 
2172  <!-- These files contain GDML <constant></constant>
2173  blocks. They are read in separately, so they can be
2174  interpreted into the remaining GDML. See make_gdml.pl for
2175  more information.
2176  -->
2177 
2178 EOF
2179 
2180  foreach $filename (@defFiles)
2181  {
2182  print OUTPUT <<EOF;
2183  <filename> $filename </filename>
2184 EOF
2185  }
2186 
2187  print OUTPUT <<EOF;
2188 
2189  </constantfiles>
2190 
2191  <gdmlfiles>
2192 
2193  <!-- The GDML file fragments to be zipped together. -->
2194 
2195 EOF
2196 
2197  foreach $filename (@gdmlFiles)
2198  {
2199  print OUTPUT <<EOF;
2200  <filename> $filename </filename>
2201 EOF
2202  }
2203 
2204  print OUTPUT <<EOF;
2205 
2206  </gdmlfiles>
2207 
2208 </config>
2209 EOF
2210 
2211  close(OUTPUT);
2212 }
2213 
2214 
2215 
2216 # run the sub routines that generate the fragments
2217 
2218 gen_Define(); # generates definitions at beginning of GDML
2219 gen_Materials(); # generates materials to be used
2220 
2221 
2222  gen_TPC( $TPCInner_x, $TPC_y, $TPC_z, 'Inner');
2223  gen_TPC( $TPCOuter_x, $TPC_y, $TPC_z, 'Outer');
2224 
2225 close $wout;
2226 
2227 gen_Cryostat(); # places (2*nAPAWide x nAPAHigh x nAPALong) volTPC,
2228  # half rotated 180 about Y
2229 gen_Enclosure(); # places two cryostats and concrete volumes
2230 
2231 gen_World(); # places the enclosure among DUSEL Rock
2232 
2233 
2234 write_fragments(); # writes the XML input for make_gdml.pl
2235  # which zips together the final GDML
2236 exit;