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