5 # First attempt to make a GDML fragment generator for the DUNE vertical drift
6 # 10kt detector geometry with 3 views: +/- Xdeg for induction and 90 deg collection
7 # The lower chamber is not added yet.
8 # !!!NOTE!!!: the readout is on a positive Y plane (drift along horizontal X)
9 # due to current reco limitations)
10 # No photon detectors declared
11 # Simplified treatment of inter-module dead spaces
13 # Created: Thu Oct 1 16:45:27 CEST 2020
14 # Vyacheslav Galymov <vgalymov@ipnl.in2p3.fr>
17 # VG: Added defs to enable use in the refactored sim framework
18 # VG: 23.02.21 Adjust plane dimensions to fit a given number of ch per side
19 # VG: 23.02.21 Group CRUs in CRPs
20 # VG: 02.03.21 The length for the ROP is force to be the lenght
21 # given by nch_collection x pitch_collection
23 #################################################################################
25 # Each subroutine generates a fragment GDML file, and the last subroutine
26 # creates an XML file that make_gdml.pl will use to appropriately arrange
27 # the fragment GDML files to create the final desired DUNE GDML file,
28 # to be named by make_gdml output command
30 ##################################################################################
38 Math::BigFloat->precision(-16);
41 GetOptions( "help|h" => \$help,
42 "suffix|s:s" => \$suffix,
43 "output|o:s" => \$output,
44 "wires|w:s" => \$wires,
45 "workspace|k:s" => \$wkspc);
47 my $FieldCage_switch="off";
48 my $Cathode_switch="off";
52 # If the user requested help, print the usage notes and exit.
57 if ( ! defined $suffix )
59 # The user didn't supply a suffix, so append nothing to the file
65 # Otherwise, stick a "-" before the suffix, so that a suffix of
66 # "test" applied to filename.gdml becomes "filename-test.gdml".
67 $suffix = "-" . $suffix;
76 elsif ( $workspace != 0 )
78 print "\t\tCreating smaller workspace geometry.\n";
81 # set wires on to be the default, unless given an input by the user
82 $wires_on = 1; # 1=on, 0=off
92 ##################################################################
93 ############## Parameters for One Readout Panel ##################
95 # parameters for 1.5 x 1.7 sub-unit Charge Readout Module / Unit
96 #$widthPCBActive = 169.0; # cm
97 #$lengthPCBActive = 150.0; # cm
99 # views and channel counts
100 %nChans = ('Ind1', 298, 'Ind1Bot', 100, 'Ind2', 298, 'Col', 304);
101 $nViews = keys %nChans;
102 #print "$nViews %nChans\n";
104 # first induction view
105 $wirePitchU = 0.7335; # cm
106 $wireAngleU = 150.0; # deg
108 # second induction view
109 $wirePitchV = 0.7335; # cm
110 $wireAngleV = 30.0; # deg
113 # last collection view
114 $wirePitchZ = 0.489; # cm
116 # force length to be equal to collection nch x pitch
117 $lengthPCBActive = $wirePitchZ * $nChans{'Col'};
118 $widthPCBActive = 167.7006;
121 $borderCRM = 0.0; # border space aroud each CRM
123 $widthCRM_active = $widthPCBActive;
124 $lengthCRM_active = $lengthPCBActive;
126 $widthCRM = $widthPCBActive + 2 * $borderCRM;
127 $lengthCRM = $lengthPCBActive + 2 * $borderCRM;
129 $borderCRP = 0.5; # cm
131 # number of CRMs in y and z
135 # create a smaller geometry
136 if( $workspace == 1 )
142 # create a smaller geometry
143 if( $workspace == 2 )
149 # create a smaller geometry
150 if( $workspace == 3 )
157 # calculate tpc area based on number of CRMs and their dimensions
158 # each CRP should have a 2x2 CRMs
159 $widthTPCActive = $nCRM_x * $widthCRM + $nCRM_x * $borderCRP; # around 1200 for full module
160 $lengthTPCActive = $nCRM_z * $lengthCRM + $nCRM_z * $borderCRP; # around 6000 for full module
162 # active volume dimensions
163 $driftTPCActive = 650.0;
165 # model anode strips as wires of some diameter
167 $ReadoutPlane = $nViews * $padWidth; # 3 readout planes (no space b/w)!
169 ##################################################################
170 ############## Parameters for TPC and inner volume ###############
172 # inner volume dimensions of the cryostat
177 # width of gas argon layer on top
178 $HeightGaseousAr = 100;
180 if( $workspace != 0 )
182 #active tpc + 1.0 m buffer on each side
183 $Argon_x = $driftTPCActive + $HeightGaseousAr + $ReadoutPlane + 100;
184 $Argon_y = $widthTPCActive + 200;
185 $Argon_z = $lengthTPCActive + 200;
189 # size of liquid argon buffer
190 $xLArBuffer = $Argon_x - $driftTPCActive - $HeightGaseousAr - $ReadoutPlane;
191 $yLArBuffer = 0.5 * ($Argon_y - $widthTPCActive);
192 $zLArBuffer = 0.5 * ($Argon_z - $lengthTPCActive);
195 $SteelThickness = 0.12; # membrane
197 $Cryostat_x = $Argon_x + 2*$SteelThickness;
198 $Cryostat_y = $Argon_y + 2*$SteelThickness;
199 $Cryostat_z = $Argon_z + 2*$SteelThickness;
201 ##################################################################
202 ############## DetEnc and World relevant parameters #############
203 ##################################################################
204 ############## DetEnc and World relevant parameters #############
206 $SteelSupport_x = 100;
207 $SteelSupport_y = 100;
208 $SteelSupport_z = 100;
210 $FracMassOfSteel = 0.5; #The steel support is not a solid block, but a mixture of air and steel
211 $FracMassOfAir = 1 - $FracMassOfSteel;
214 $SpaceSteelSupportToWall = 100;
215 $SpaceSteelSupportToCeiling = 100;
217 $DetEncX = $Cryostat_x
218 + 2*($SteelSupport_x + $FoamPadding) + $SpaceSteelSupportToCeiling;
220 $DetEncY = $Cryostat_y
221 + 2*($SteelSupport_y + $FoamPadding) + 2*$SpaceSteelSupportToWall;
223 $DetEncZ = $Cryostat_z
224 + 2*($SteelSupport_z + $FoamPadding) + 2*$SpaceSteelSupportToWall;
226 $posCryoInDetEnc_x = - $DetEncX/2 + $SteelSupport_x + $FoamPadding + $Cryostat_x/2;
229 $RockThickness = 4000;
231 # We want the world origin to be vertically centered on active TPC
232 # This is to be added to the x and y position of every volume in volWorld
234 $OriginXSet = $DetEncX/2.0
239 - $driftTPCActive/2.0;
241 $OriginYSet = $DetEncY/2.0
242 - $SpaceSteelSupportToWall
247 - $widthTPCActive/2.0;
249 # We want the world origin to be at the very front of the fiducial volume.
250 # move it to the front of the enclosure, then back it up through the concrete/foam,
251 # then through the Cryostat shell, then through the upstream dead LAr (including the
252 # dead LAr on the edge of the TPC)
253 # This is to be added to the z position of every volume in volWorld
255 $OriginZSet = $DetEncZ/2.0
256 - $SpaceSteelSupportToWall
263 ##################################################################
264 ############## Field Cage Parameters ###############
265 $FieldShaperLongTubeLength = $lengthTPCActive;
266 $FieldShaperShortTubeLength = $widthTPCActive;
267 $FieldShaperInnerRadius = 1.485;
268 $FieldShaperOuterRadius = 1.685;
269 $FieldShaperTorRad = 1.69;
271 $FieldShaperLength = $FieldShaperLongTubeLength + 2*$FieldShaperOuterRadius+ 2*$FieldShaperTorRad;
272 $FieldShaperWidth = $FieldShaperShortTubeLength + 2*$FieldShaperOuterRadius+ 2*$FieldShaperTorRad;
274 $FieldShaperSeparation = 5.0;
275 $NFieldShapers = ($driftTPCActive/$FieldShaperSeparation) - 1;
277 $FieldCageSizeX = $FieldShaperSeparation*$NFieldShapers+2;
278 $FieldCageSizeY = $FieldShaperWidth+2;
279 $FieldCageSizeZ = $FieldShaperLength+2;
282 #+++++++++++++++++++++++++ End defining variables ++++++++++++++++++++++++++
285 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
286 #+++++++++++++++++++++++++++++++++++++++++ usage +++++++++++++++++++++++++++++++++++++++++
287 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
291 print "Usage: $0 [-h|--help] [-o|--output <fragments-file>] [-s|--suffix <string>]\n";
292 print " if -o is omitted, output goes to STDOUT; <fragments-file> is input to make_gdml.pl\n";
293 print " -s <string> appends the string to the file names; useful for multiple detector versions\n";
294 print " -h prints this message, then quits\n";
301 # Create the <define> fragment file name,
302 # add file to list of fragments,
304 $DEF = $basename."_Ext" . $suffix . ".gdml";
305 push (@gdmlFiles, $DEF);
307 open(DEF) or die("Could not open file $DEF for writing");
310 <?xml version='1.0'?>
313 <color name="magenta" R="0.0" G="1.0" B="0.0" A="1.0" />
314 <color name="green" R="0.0" G="1.0" B="0.0" A="1.0" />
315 <color name="red" R="1.0" G="0.0" B="0.0" A="1.0" />
316 <color name="blue" R="0.0" G="0.0" B="1.0" A="1.0" />
317 <color name="yellow" R="1.0" G="1.0" B="0.0" A="1.0" />
324 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
325 #++++++++++++++++++++++++++++++++++++++ gen_Define +++++++++++++++++++++++++++++++++++++++
326 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
331 # Create the <define> fragment file name,
332 # add file to list of fragments,
334 $DEF = $basename."_Def" . $suffix . ".gdml";
335 push (@gdmlFiles, $DEF);
337 open(DEF) or die("Could not open file $DEF for writing");
341 <?xml version='1.0'?>
351 <position name="posCryoInDetEnc" unit="cm" x="$posCryoInDetEnc_x" y="0" z="0"/>
352 <position name="posCenter" unit="cm" x="0" y="0" z="0"/>
353 <rotation name="rUWireAboutX" unit="deg" x="$wireAngleU" y="0" z="0"/>
354 <rotation name="rVWireAboutX" unit="deg" x="$wireAngleV" y="0" z="0"/>
355 <rotation name="rPlus90AboutX" unit="deg" x="90" y="0" z="0"/>
356 <rotation name="rPlus90AboutY" unit="deg" x="0" y="90" z="0"/>
357 <rotation name="rPlus90AboutXPlus90AboutY" unit="deg" x="90" y="90" z="0"/>
358 <rotation name="rMinus90AboutX" unit="deg" x="270" y="0" z="0"/>
359 <rotation name="rMinus90AboutY" unit="deg" x="0" y="270" z="0"/>
360 <rotation name="rMinus90AboutYMinus90AboutX" unit="deg" x="270" y="270" z="0"/>
361 <rotation name="rPlus180AboutX" unit="deg" x="180" y="0" z="0"/>
362 <rotation name="rPlus180AboutY" unit="deg" x="0" y="180" z="0"/>
363 <rotation name="rPlus180AboutXPlus180AboutY" unit="deg" x="180" y="180" z="0"/>
364 <rotation name="rIdentity" unit="deg" x="0" y="0" z="0"/>
371 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
372 #+++++++++++++++++++++++++++++++++++++ gen_Materials +++++++++++++++++++++++++++++++++++++
373 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
378 # Create the <materials> fragment file name,
379 # add file to list of output GDML fragments,
381 $MAT = $basename."_Materials" . $suffix . ".gdml";
382 push (@gdmlFiles, $MAT);
385 open(MAT) or die("Could not open file $MAT for writing");
387 # Add any materials special to this geometry by defining a mulitline string
388 # and passing it to the gdmlMaterials::gen_Materials() function.
390 <!-- preliminary values -->
391 <material name="AirSteelMixture" formula="AirSteelMixture">
392 <D value=" 0.001205*(1-$FracMassOfSteel) + 7.9300*$FracMassOfSteel " unit="g/cm3"/>
393 <fraction n="$FracMassOfSteel" ref="STEEL_STAINLESS_Fe7Cr2Ni"/>
394 <fraction n="$FracMassOfAir" ref="Air"/>
396 <material name="vm2000" formula="vm2000">
397 <D value="1.2" unit="g/cm3"/>
398 <composite n="2" ref="carbon"/>
399 <composite n="4" ref="hydrogen"/>
403 # add the general materials used anywere
404 print MAT gdmlMaterials::gen_Materials( $asmix );
410 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
411 #++++++++++++++++++++++++++++++++++++++++ gen_TPC ++++++++++++++++++++++++++++++++++++++++
412 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
413 # line clip on the rectangle boundary
424 if( abs( nx ) < tol ){
425 push( @endpts, ($x0, 0) );
426 push( @endpts, ($x0, $rcw) );
429 if( abs( ny ) < tol ){
430 push( @endpts, (0, $y0) );
431 push( @endpts, ($rcl, $y0) );
435 # left border at x = 0
436 my $y = $y0 - $x0 * $ny/$nx;
437 if( $y >= 0 && $y <= $rcw ){
438 push( @endpts, (0, $y) );
441 # right border at x = l
442 $y = $y0 + ($rcl-$x0) * $ny/$nx;
443 if( $y >= 0 && $y <= $rcw ){
444 push( @endpts, ($rcl, $y) );
445 if( scalar(@endpts) == 4 ){
450 # bottom border at y = 0
451 my $x = $x0 - $y0 * $nx/$ny;
452 if( $x >= 0 && $x <= $rcl ){
453 push( @endpts, ($x, 0) );
454 if( scalar(@endpts) == 4 ){
459 # top border at y = w
460 $x = $x0 + ($rcw-$y0)* $nx/$ny;
461 if( $x >= 0 && $x <= $rcl ){
462 push( @endpts, ($x, $rcw) );
470 my $length = $_[0]; #
473 my $nchb = $_[3]; # nch per bottom side
475 my $theta = $_[5]; # deg
478 $theta = $theta * pi()/180.0;
479 my @dirw = (cos($theta), sin($theta));
480 my @dirp = (cos($theta - pi()/2), sin($theta - pi()/2));
484 if( $alpha > pi()/2 ){
485 $alpha = pi() - $alpha;
487 my $dX = $pitch / sin( $alpha );
488 my $dY = $pitch / sin( pi()/2 - $alpha );
490 $length = $dX * $nchb;
493 $width = $dY * ($nch - $nchb);
504 #print "origin : @orig\n";
505 #print "pitch dir : @dirp\n";
506 #print "wire dir : @dirw\n";
507 #print "$length x $width cm2\n";
511 my $offset = $pitch/2;
512 foreach my $ch (0..$nch-1){
513 #print "Processing $ch\n";
515 # calculate reference point for this strip
517 $wcn[0] = $orig[0] + $offset * $dirp[0];
518 $wcn[1] = $orig[1] + $offset * $dirp[1];
520 # line clip on the rectangle boundary
521 @endpts = lineClip( $wcn[0], $wcn[1], $dirw[0], $dirw[1], $length, $width );
523 if( scalar(@endpts) != 4 ){
524 print "Could not find end points for wire $ch : @endpts\n";
525 $offset = $offset + $pitch;
529 # re-center on the mid-point
530 $endpts[0] -= $length/2;
531 $endpts[2] -= $length/2;
532 $endpts[1] -= $width/2;
533 $endpts[3] -= $width/2;
535 # calculate the strip center in the rectangle of CRU
536 $wcn[0] = ($endpts[0] + $endpts[2])/2;
537 $wcn[1] = ($endpts[1] + $endpts[3])/2;
539 # calculate the length
540 my $dx = $endpts[0] - $endpts[2];
541 my $dy = $endpts[1] - $endpts[3];
542 my $wlen = sqrt($dx**2 + $dy**2);
544 # put all info together
545 my @wire = ($ch, $wcn[0], $wcn[1], $wlen);
546 push( @wire, @endpts );
547 push( @winfo, \@wire);
548 $offset = $offset + $pitch;
558 my $TPCActive_x = $driftTPCActive;
559 my $TPCActive_y = $widthCRM_active;
560 my $TPCActive_z = $lengthCRM_active;
563 my $TPC_x = $TPCActive_x + $ReadoutPlane;
564 my $TPC_y = $widthCRM;
565 my $TPC_z = $lengthCRM;
567 print " TPC dimensions : $TPC_x x $TPC_y x $TPC_z\n";
569 $TPC = $basename."_TPC" . $suffix . ".gdml";
570 push (@gdmlFiles, $TPC);
572 open(TPC) or die("Could not open file $TPC for writing");
574 # The standard XML prefix and starting the gdml
576 <?xml version='1.0'?>
580 # compute wires for 1st induction
583 if( $wires_on == 1 ){
584 @winfoU = gen_Wires( $TPCActive_z, 0, # force length
585 $nChans{'Ind1'}, $nChans{'Ind1Bot'},
586 $wirePitchU, $wireAngleU, $padWidth );
587 @winfoV = gen_Wires( $TPCActive_z, 0, # force length
588 $nChans{'Ind2'}, $nChans{'Ind1Bot'},
589 $wirePitchV, $wireAngleV, $padWidth );
593 # All the TPC solids save the wires.
604 <box name="CRMUPlane"
609 <box name="CRMVPlane"
614 <box name="CRMZPlane"
619 <box name="CRMActive"
626 #++++++++++++++++++++++++++++ Wire Solids ++++++++++++++++++++++++++++++
629 foreach my $wire (@winfoU) {
630 my $wid = $wire->[0];
631 my $wln = $wire->[3];
633 <tube name="CRMWireU$wid"
637 aunit="deg" lunit="cm"/>
641 foreach my $wire (@winfoV) {
642 my $wid = $wire->[0];
643 my $wln = $wire->[3];
645 <tube name="CRMWireV$wid"
649 aunit="deg" lunit="cm"/>
655 <tube name="CRMWireZ"
659 aunit="deg" lunit="cm"/>
667 # Begin structure and create wire logical volumes
670 <volume name="volTPCActive">
671 <materialref ref="LAr"/>
672 <solidref ref="CRMActive"/>
673 <auxiliary auxtype="SensDet" auxvalue="SimEnergyDeposit"/>
674 <auxiliary auxtype="StepLimit" auxunit="cm" auxvalue="0.5208*cm"/>
675 <auxiliary auxtype="Efield" auxunit="V/cm" auxvalue="500*V/cm"/>
676 <colorref ref="blue"/>
682 foreach my $wire (@winfoU)
684 my $wid = $wire->[0];
686 <volume name="volTPCWireU$wid">
687 <materialref ref="Copper_Beryllium_alloy25"/>
688 <solidref ref="CRMWireU$wid"/>
693 foreach my $wire (@winfoV)
695 my $wid = $wire->[0];
697 <volume name="volTPCWireV$wid">
698 <materialref ref="Copper_Beryllium_alloy25"/>
699 <solidref ref="CRMWireV$wid"/>
705 <volume name="volTPCWireZ">
706 <materialref ref="Copper_Beryllium_alloy25"/>
707 <solidref ref="CRMWireZ"/>
711 # 1st induction plane
713 <volume name="volTPCPlaneU">
714 <materialref ref="LAr"/>
715 <solidref ref="CRMUPlane"/>
717 if ($wires_on==1) # add wires to U plane
719 # the coordinates were computed with a corner at (0,0)
720 # so we need to move to plane coordinates
721 my $offsetZ = 0; #-0.5 * $TPCActive_z;
722 my $offsetY = 0; #-0.5 * $TPCActive_y;
724 foreach my $wire (@winfoU) {
725 my $wid = $wire->[0];
726 my $zpos = $wire->[1] + $offsetZ;
727 my $ypos = $wire->[2] + $offsetY;
730 <volumeref ref="volTPCWireU$wid"/>
731 <position name="posWireU$wid" unit="cm" x="0" y="$ypos" z="$zpos"/>
732 <rotationref ref="rUWireAboutX"/>
741 # 2nd induction plane
743 <volume name="volTPCPlaneV">
744 <materialref ref="LAr"/>
745 <solidref ref="CRMVPlane"/>
748 if ($wires_on==1) # add wires to V plane (plane with wires reading y position)
750 # the coordinates were computed with a corner at (0,0)
751 # so we need to move to plane coordinates
752 my $offsetZ = 0; #-0.5 * $TPCActive_z;
753 my $offsetY = 0; #-0.5 * $TPCActive_y;
755 foreach my $wire (@winfoV) {
756 my $wid = $wire->[0];
757 my $zpos = $wire->[1] + $offsetZ;
758 my $ypos = $wire->[2] + $offsetY;
761 <volumeref ref="volTPCWireV$wid"/>
762 <position name="posWireV$wid" unit="cm" x="0" y="$ypos" z="$zpos"/>
763 <rotationref ref="rVWireAboutX"/>
774 <volume name="volTPCPlaneZ">
775 <materialref ref="LAr"/>
776 <solidref ref="CRMZPlane"/>
778 if ($wires_on==1) # add wires to Z plane (plane with wires reading z position)
780 for($i=0;$i<$nChans{'Col'};++$i)
782 #my $zpos = -0.5 * $TPCActive_z + ($i+0.5)*$wirePitchZ + 0.5*$padWidth;
783 my $zpos = ($i + 0.5 - $nChans{'Col'}/2)*$wirePitchZ;
784 if( (0.5 * $TPCActive_z - abs($zpos)) < 0 ){
785 die "Cannot place wire $i in view Z, as plane is too small\n";
789 <volumeref ref="volTPCWireZ"/>
790 <position name="posWireZ$i" unit="cm" x="0" y="0" z="$zpos"/>
791 <rotationref ref="rPlus90AboutX"/>
801 $posUplane[0] = 0.5*$TPC_x - 2.5*$padWidth;
805 $posVplane[0] = 0.5*$TPC_x - 1.5*$padWidth;
809 $posZplane[0] = 0.5*$TPC_x - 0.5*$padWidth;
813 $posTPCActive[0] = -$ReadoutPlane/2;
814 $posTPCActive[1] = 0;
815 $posTPCActive[2] = 0;
818 #wrap up the TPC file
820 <volume name="volTPC">
821 <materialref ref="LAr"/>
822 <solidref ref="CRM"/>
824 <volumeref ref="volTPCPlaneU"/>
825 <position name="posPlaneU" unit="cm"
826 x="$posUplane[0]" y="$posUplane[1]" z="$posUplane[2]"/>
827 <rotationref ref="rIdentity"/>
830 <volumeref ref="volTPCPlaneV"/>
831 <position name="posPlaneY" unit="cm"
832 x="$posVplane[0]" y="$posVplane[1]" z="$posVplane[2]"/>
833 <rotationref ref="rIdentity"/>
836 <volumeref ref="volTPCPlaneZ"/>
837 <position name="posPlaneZ" unit="cm"
838 x="$posZplane[0]" y="$posZplane[1]" z="$posZplane[2]"/>
839 <rotationref ref="rIdentity"/>
842 <volumeref ref="volTPCActive"/>
843 <position name="posActive" unit="cm"
844 x="$posTPCActive[0]" y="$posTPCAtive[1]" z="$posTPCActive[2]"/>
845 <rotationref ref="rIdentity"/>
858 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
859 #++++++++++++++++++++++++++++++++++++++ gen_FieldCage ++++++++++++++++++++++++++++++++++++
860 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
864 $FieldCage = $basename."_FieldCage" . $suffix . ".gdml";
865 push (@gdmlFiles, $FieldCage);
866 $FieldCage = ">" . $FieldCage;
867 open(FieldCage) or die("Could not open file $FieldCage for writing");
869 # The standard XML prefix and starting the gdml
870 print FieldCage <<EOF;
871 <?xml version='1.0'?>
874 # The printing solids used in the Field Cage
875 #print "lengthTPCActive : $lengthTPCActive \n";
876 #print "widthTPCActive : $widthTPCActive \n";
879 print FieldCage <<EOF;
881 <torus name="FieldShaperCorner" rmin="$FieldShaperInnerRadius" rmax="$FieldShaperOuterRadius" rtor="$FieldShaperTorRad" deltaphi="90" startphi="0" aunit="deg" lunit="cm"/>
882 <tube name="FieldShaperLongtube" rmin="$FieldShaperInnerRadius" rmax="$FieldShaperOuterRadius" z="$FieldShaperLongTubeLength" deltaphi="360" startphi="0" aunit="deg" lunit="cm"/>
883 <tube name="FieldShaperShorttube" rmin="$FieldShaperInnerRadius" rmax="$FieldShaperOuterRadius" z="$FieldShaperShortTubeLength" deltaphi="360" startphi="0" aunit="deg" lunit="cm"/>
885 <union name="FSunion1">
886 <first ref="FieldShaperLongtube"/>
887 <second ref="FieldShaperCorner"/>
888 <position name="esquinapos1" unit="cm" x="@{[-$FieldShaperTorRad]}" y="0" z="@{[0.5*$FieldShaperLongTubeLength]}"/>
889 <rotation name="rot1" unit="deg" x="90" y="0" z="0" />
892 <union name="FSunion2">
893 <first ref="FSunion1"/>
894 <second ref="FieldShaperShorttube"/>
895 <position name="esquinapos2" unit="cm" x="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[+0.5*$FieldShaperLongTubeLength+$FieldShaperTorRad]}"/>
896 <rotation name="rot2" unit="deg" x="0" y="90" z="0" />
899 <union name="FSunion3">
900 <first ref="FSunion2"/>
901 <second ref="FieldShaperCorner"/>
902 <position name="esquinapos3" unit="cm" x="@{[-$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[0.5*$FieldShaperLongTubeLength]}"/>
903 <rotation name="rot3" unit="deg" x="90" y="270" z="0" />
906 <union name="FSunion4">
907 <first ref="FSunion3"/>
908 <second ref="FieldShaperLongtube"/>
909 <position name="esquinapos4" unit="cm" x="@{[-$FieldShaperShortTubeLength-2*$FieldShaperTorRad]}" y="0" z="0"/>
912 <union name="FSunion5">
913 <first ref="FSunion4"/>
914 <second ref="FieldShaperCorner"/>
915 <position name="esquinapos5" unit="cm" x="@{[-$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength]}"/>
916 <rotation name="rot5" unit="deg" x="90" y="180" z="0" />
919 <union name="FSunion6">
920 <first ref="FSunion5"/>
921 <second ref="FieldShaperShorttube"/>
922 <position name="esquinapos6" unit="cm" x="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength-$FieldShaperTorRad]}"/>
923 <rotation name="rot6" unit="deg" x="0" y="90" z="0" />
926 <union name="FieldShaperSolid">
927 <first ref="FSunion6"/>
928 <second ref="FieldShaperCorner"/>
929 <position name="esquinapos7" unit="cm" x="@{[-$FieldShaperTorRad]}" y="0" z="@{[-0.5*$FieldShaperLongTubeLength]}"/>
930 <rotation name="rot7" unit="deg" x="90" y="90" z="0" />
936 print FieldCage <<EOF;
939 <volume name="volFieldShaper">
940 <materialref ref="Al2O3"/>
941 <solidref ref="FieldShaperSolid"/>
947 print FieldCage <<EOF;
956 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
957 #++++++++++++++++++++++++++++++++++++++ gen_Cryostat +++++++++++++++++++++++++++++++++++++
958 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
963 # Create the cryostat fragment file name,
964 # add file to list of output GDML fragments,
966 $CRYO = $basename."_Cryostat" . $suffix . ".gdml";
967 push (@gdmlFiles, $CRYO);
969 open(CRYO) or die("Could not open file $CRYO for writing");
972 # The standard XML prefix and starting the gdml
974 <?xml version='1.0'?>
978 # All the cryostat solids.
981 <box name="Cryostat" lunit="cm"
986 <box name="ArgonInterior" lunit="cm"
991 <box name="GaseousArgon" lunit="cm"
996 <subtraction name="SteelShell">
997 <first ref="Cryostat"/>
998 <second ref="ArgonInterior"/>
1004 # Cryostat structure
1007 <volume name="volSteelShell">
1008 <materialref ref="STEEL_STAINLESS_Fe7Cr2Ni" />
1009 <solidref ref="SteelShell" />
1011 <volume name="volGaseousArgon">
1012 <materialref ref="ArGas"/>
1013 <solidref ref="GaseousArgon"/>
1019 <volume name="volCryostat">
1020 <materialref ref="LAr" />
1021 <solidref ref="Cryostat" />
1023 <volumeref ref="volGaseousArgon"/>
1024 <position name="posGaseousArgon" unit="cm" x="@{[$Argon_x/2-$HeightGaseousAr/2]}" y="0" z="0"/>
1027 <volumeref ref="volSteelShell"/>
1028 <position name="posSteelShell" unit="cm" x="0" y="0" z="0"/>
1032 if ($tpc_on==1) # place TPC inside croysotat offsetting each pair of CRMs by borderCRP
1034 $posX = $Argon_x/2 - $HeightGaseousAr - 0.5*($driftTPCActive + $ReadoutPlane);
1036 my $posZ = -0.5*$Argon_z + $zLArBuffer + 0.5*$lengthCRM;
1037 for(my $ii=0;$ii<$nCRM_z;$ii++)
1040 $posZ += $borderCRP;
1042 $posZ += $borderCRP;
1045 my $posY = -0.5*$Argon_y + $yLArBuffer + 0.5*$widthCRM;
1046 for(my $jj=0;$jj<$nCRM_x;$jj++)
1049 $posY += $borderCRP;
1051 $posY += $borderCRP;
1056 <volumeref ref="volTPC"/>
1057 <position name="posTPC\-$idx" unit="cm"
1058 x="$posX" y="$posY" z="$posZ"/>
1065 $posZ += $lengthCRM;
1069 #The +50 in the x positions must depend on some other parameter
1070 if ( $FieldCage_switch eq "on" ) {
1071 for ( $i=0; $i<$NFieldShapers; $i=$i+1 ) { # pmts with coating
1072 $posX = $Argon_x/2 - $HeightGaseousAr - 0.5*($driftTPCActive + $ReadoutPlane);
1075 <volumeref ref="volFieldShaper"/>
1076 <position name="posFieldShaper$i" unit="cm" x="@{[-$OriginXSet+50+($i-$NFieldShapers*0.5)*$FieldShaperSeparation]}" y="@{[-0.5*$FieldShaperShortTubeLength-$FieldShaperTorRad]}" z="0" />
1077 <rotation name="rotFS$i" unit="deg" x="0" y="0" z="90" />
1084 $CathodePosX =-$OriginXSet+50+(-1-$NFieldShapers*0.5)*$FieldShaperSeparation;
1087 if ( $Cathode_switch eq "on" )
1091 <volumeref ref="volGroundGrid"/>
1092 <position name="posGroundGrid01" unit="cm" x="$CathodePosX" y="@{[-$CathodePosY]}" z="@{[$CathodePosZ]}"/>
1093 <rotation name="rotGG01" unit="deg" x="0" y="0" z="90" />
1111 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1112 #+++++++++++++++++++++++++++++++++++++ gen_Enclosure +++++++++++++++++++++++++++++++++++++
1113 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1118 # Create the detector enclosure fragment file name,
1119 # add file to list of output GDML fragments,
1121 $ENCL = $basename."_DetEnclosure" . $suffix . ".gdml";
1122 push (@gdmlFiles, $ENCL);
1123 $ENCL = ">" . $ENCL;
1124 open(ENCL) or die("Could not open file $ENCL for writing");
1127 # The standard XML prefix and starting the gdml
1129 <?xml version='1.0'?>
1134 # All the detector enclosure solids.
1138 <box name="FoamPadBlock" lunit="cm"
1139 x="@{[$Cryostat_x + 2*$FoamPadding]}"
1140 y="@{[$Cryostat_y + 2*$FoamPadding]}"
1141 z="@{[$Cryostat_z + 2*$FoamPadding]}" />
1143 <subtraction name="FoamPadding">
1144 <first ref="FoamPadBlock"/>
1145 <second ref="Cryostat"/>
1146 <positionref ref="posCenter"/>
1149 <box name="SteelSupportBlock" lunit="cm"
1150 x="@{[$Cryostat_x + 2*$FoamPadding + 2*$SteelSupport_x]}"
1151 y="@{[$Cryostat_y + 2*$FoamPadding + 2*$SteelSupport_y]}"
1152 z="@{[$Cryostat_z + 2*$FoamPadding + 2*$SteelSupport_z]}" />
1154 <subtraction name="SteelSupport">
1155 <first ref="SteelSupportBlock"/>
1156 <second ref="FoamPadBlock"/>
1157 <positionref ref="posCenter"/>
1160 <box name="DetEnclosure" lunit="cm"
1169 # Detector enclosure structure
1172 <volume name="volFoamPadding">
1173 <materialref ref="fibrous_glass"/>
1174 <solidref ref="FoamPadding"/>
1177 <volume name="volSteelSupport">
1178 <materialref ref="AirSteelMixture"/>
1179 <solidref ref="SteelSupport"/>
1182 <volume name="volDetEnclosure">
1183 <materialref ref="Air"/>
1184 <solidref ref="DetEnclosure"/>
1187 <volumeref ref="volFoamPadding"/>
1188 <positionref ref="posCryoInDetEnc"/>
1191 <volumeref ref="volSteelSupport"/>
1192 <positionref ref="posCryoInDetEnc"/>
1195 <volumeref ref="volCryostat"/>
1196 <positionref ref="posCryoInDetEnc"/>
1215 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1216 #+++++++++++++++++++++++++++++++++++++++ gen_World +++++++++++++++++++++++++++++++++++++++
1217 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1222 # Create the WORLD fragment file name,
1223 # add file to list of output GDML fragments,
1225 $WORLD = $basename."_World" . $suffix . ".gdml";
1226 push (@gdmlFiles, $WORLD);
1227 $WORLD = ">" . $WORLD;
1228 open(WORLD) or die("Could not open file $WORLD for writing");
1231 # The standard XML prefix and starting the gdml
1233 <?xml version='1.0'?>
1238 # All the World solids.
1241 <box name="World" lunit="cm"
1242 x="@{[$DetEncX+2*$RockThickness]}"
1243 y="@{[$DetEncY+2*$RockThickness]}"
1244 z="@{[$DetEncZ+2*$RockThickness]}"/>
1251 <volume name="volWorld" >
1252 <materialref ref="DUSEL_Rock"/>
1253 <solidref ref="World"/>
1256 <volumeref ref="volDetEnclosure"/>
1257 <position name="posDetEnclosure" unit="cm" x="$OriginXSet" y="$OriginYSet" z="$OriginZSet"/>
1265 # make_gdml.pl will take care of <setup/>
1272 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1273 #++++++++++++++++++++++++++++++++++++ write_fragments ++++++++++++++++++++++++++++++++++++
1274 #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1276 sub write_fragments()
1278 # This subroutine creates an XML file that summarizes the the subfiles output
1279 # by the other sub routines - it is the input file for make_gdml.pl which will
1280 # give the final desired GDML file. Specify its name with the output option.
1281 # (you can change the name when running make_gdml)
1283 # This code is taken straigh from the similar MicroBooNE generate script, Thank you.
1285 if ( ! defined $output )
1287 $output = "-"; # write to STDOUT
1290 # Set up the output file.
1291 $OUTPUT = ">" . $output;
1292 open(OUTPUT) or die("Could not open file $OUTPUT");
1295 <?xml version='1.0'?>
1297 <!-- Input to Geometry/gdml/make_gdml.pl; define the GDML fragments
1298 that will be zipped together to create a detector description.
1305 <!-- These files contain GDML <constant></constant>
1306 blocks. They are read in separately, so they can be
1307 interpreted into the remaining GDML. See make_gdml.pl for
1313 foreach $filename (@defFiles)
1316 <filename> $filename </filename>
1326 <!-- The GDML file fragments to be zipped together. -->
1330 foreach $filename (@gdmlFiles)
1333 <filename> $filename </filename>
1348 print "Some of the principal parameters for this TPC geometry (unit cm unless noted otherwise)\n";
1349 print " CRM active area : $widthCRM_active x $lengthCRM_active\n";
1350 print " CRM total area : $widthCRM x $lengthCRM\n";
1351 print " Wire pitch in U, V, Z : $wirePitchU, $wirePitchV, $wirePitchZ\n";
1352 print " TPC active volume : $driftTPCActive x $widthTPCActive x $lengthTPCActive\n";
1353 print " Argon volume : ($Argon_x, $Argon_y, $Argon_z) \n";
1354 print " Argon buffer : ($xLArBuffer, $yLArBuffer, $zLArBuffer) \n";
1355 print " Detector enclosure : $DetEncX x $DetEncY x $DetEncZ\n";
1356 print " TPC Origin : ($OriginXSet, $OriginYSet, $OriginZSet) \n";
1357 print " Field Cage : $FieldCage_switch \n";
1358 print " Cathode : $Cathode_switch \n";
1359 print " Workspace : $workspace \n";
1360 print " Wires : $wires_on \n";
1362 # run the sub routines that generate the fragments
1363 if ( $FieldCage_switch eq "on" ) { gen_FieldCage(); }
1364 #if ( $Cathode_switch eq "on" ) { gen_Cathode(); } #Cathode for now has the same geometry as the Ground Grid
1366 gen_Extend(); # generates the GDML color extension for the refactored geometry
1367 gen_Define(); # generates definitions at beginning of GDML
1368 gen_Materials(); # generates materials to be used
1369 gen_TPC(); # generate TPC for a given unit CRM
1372 gen_World(); # places the enclosure among DUSEL Rock
1373 write_fragments(); # writes the XML input for make_gdml.pl
1374 # which zips together the final GDML
1375 print "--- done\n\n\n";