BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSBeamPipeFactoryLHCDetailed.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2022.
4
5This file is part of BDSIM.
6
7BDSIM is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published
9by the Free Software Foundation version 3 of the License.
10
11BDSIM is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "BDSBeamPipeFactoryBase.hh"
20#include "BDSBeamPipeFactoryLHCDetailed.hh"
21#include "BDSBeamPipe.hh"
22#include "BDSColours.hh"
23#include "BDSExtent.hh"
24#include "BDSGlobalConstants.hh"
25#include "BDSMaterials.hh"
26#include "BDSSDType.hh"
27
28#include "globals.hh" // geant4 globals / types
29#include "G4Box.hh"
30#include "G4CutTubs.hh"
31#include "G4IntersectionSolid.hh"
32#include "G4LogicalVolume.hh"
33#include "G4Material.hh"
34#include "G4PVPlacement.hh"
35#include "G4SubtractionSolid.hh"
36#include "G4ThreeVector.hh"
37#include "G4Tubs.hh"
38#include "G4VisAttributes.hh"
39#include "G4VSolid.hh"
40
41#include <cmath>
42#include <set>
43#include <utility> // for std::pair
44
45BDSBeamPipeFactoryLHCDetailed::BDSBeamPipeFactoryLHCDetailed()
46{
47 coldBoreThickness = 1.5*CLHEP::mm;
48 coolingPipeThickness = 0.53*CLHEP::mm;
49 coolingPipeRadius = 3.7*CLHEP::mm*0.5; // will be overwritten if needs be to fit inside beampipe
50 coolingPipeOffset = 0.0; //initialised only
51 copperSkinThickness = 75*CLHEP::um;
53}
54
56{
58 BDSBeamPipeFactoryBase::CleanUp();
59}
60
62{
63 copperSkinSolid = nullptr; // the copper skin
64 screenSolid = nullptr; // the beam screen (first bit of aperture)
65 coolingPipeSolid = nullptr; // small cooling pipe above and below beam screen
66 copperSkinLV = nullptr;
67 screenLV = nullptr;
68 coolingPipeLV = nullptr;
69 copperSkinPV = nullptr;
70 screenPV = nullptr;
71 coolingPipeTopPV = nullptr;
72 coolingPipeBottomPV = nullptr;
73
75}
76
78{
79 vacRadius = 0, vacBoxX = 0, vacBoxY = 0;
80
81 cuInnerRadius = 0, cuInnerBoxX = 0, cuInnerBoxY = 0;
82 cuOuterRadius = 0, cuOuterBoxX = 0, cuOuterBoxY = 0;
83
84 bsInnerRadius = 0, bsInnerBoxX = 0, bsInnerBoxY = 0;
85 bsOuterRadius = 0, bsOuterBoxX = 0, bsOuterBoxY = 0;
86
87 cbInnerRadius = 0, cbOuterRadius = 0;
88
90
91 vacHalfLength = 0;
92 halfLength = 0;
93
95 verticalOrientation = true; // arbitrary, will be overwritten
96 buildCoolingPipe = true;
97}
98
99
101{
102 return coolingPipeRadius + coolingPipeThickness + 2*lengthSafety;
103}
104
106 G4double aper2,
107 G4double aper3,
108 G4double beamPipeThickness,
109 G4double length)
110{
111 // vacuum volume
112 vacRadius = aper3;
113 vacBoxX = aper1;
114 vacBoxY = aper2;
115
116 // copper skin geometrical parameters
117 cuInnerRadius = vacRadius + 1*CLHEP::um;
118 cuInnerBoxX = vacBoxX + 1*CLHEP::um;
119 cuInnerBoxY = vacBoxY + 1*CLHEP::um;
120 cuOuterRadius = cuInnerRadius + copperSkinThickness;
121 cuOuterBoxX = cuInnerBoxX + copperSkinThickness;
122 cuOuterBoxY = cuInnerBoxY + copperSkinThickness;
123
124 // beam screen geometrical parameters
125 bsInnerRadius = cuOuterRadius + 1*CLHEP::um;
126 bsInnerBoxX = cuOuterBoxX + 1*CLHEP::um;
127 bsInnerBoxY = cuOuterBoxY + 1*CLHEP::um;
128 bsOuterRadius = bsInnerRadius + beamPipeThickness;
129 bsOuterBoxX = bsInnerBoxX + beamPipeThickness;
130 bsOuterBoxY = bsInnerBoxY + beamPipeThickness;
131
132 // cold bore geometrical parameters
133 cbInnerRadius = bsOuterRadius + 1*CLHEP::um;
134 cbOuterRadius = cbInnerRadius + coldBoreThickness;
135
136 // container geometrical parameters
137 containerRadius = cbOuterRadius + 1*CLHEP::um;
138
139 // general length variable (to avoid mistakes)
140 vacHalfLength = length*0.5 - lengthSafety;
141 halfLength = length*0.5 - 1*CLHEP::um;
142
143 // cooling pipe geometrical parameters
144 G4double fullWidthOfCoolingPipe = coolingPipeRadius + coolingPipeThickness + 1*CLHEP::um;
145 if (aper1 > aper2)
146 {
147 coolingPipeOffset = bsOuterBoxY + fullWidthOfCoolingPipe;
148 verticalOrientation = false;
149 }
150 else
151 {
152 coolingPipeOffset = bsOuterBoxX + fullWidthOfCoolingPipe;
153 verticalOrientation = true;
154 }
155
156 G4double valueToCompare;
158 {valueToCompare = bsOuterBoxX;}
159 else
160 {valueToCompare = bsInnerBoxY;}
161
162 G4double gapForCoolingPipe = std::abs(cbInnerRadius - valueToCompare);
163 if (gapForCoolingPipe < fullWidthOfCoolingPipe + 1*CLHEP::um)
164 {buildCoolingPipe = false;}
165}
166
167
169 G4double length,
170 G4double aper1,
171 G4double aper2,
172 G4double aper3,
173 G4double /*aper4*/,
174 G4Material* vacuumMaterial,
175 G4double beamPipeThickness,
176 G4Material* beamPipeMaterial,
177 const G4String& /*pointsFileIn*/,
178 const G4String& /*pointsUnitIn*/)
179{
180 // clean up after last usage
181 CleanUp();
182
183 // we override the material of the beam pipe
184 beamPipeMaterial = BDSMaterials::Instance()->GetMaterial("stainless_steel_316LN_2K");
185
186 // calculate geometrical parameters
187 CalculateGeometricalParameters(aper1, aper2, aper3, beamPipeThickness, length);
188
189 // build the solids
190 //vacuum cylindrical solid (circular cross-section)
191 G4VSolid* vacCylSolid = new G4Tubs(name + "_vacuum_cylinder", // name
192 0, // inner radius
193 vacRadius, // outer radius
194 vacHalfLength, // half length
195 0, // rotation start angle
196 CLHEP::twopi); // rotation finish angle
197 //vacuum box solid (rectangular cross-section)
198 G4VSolid* vacRectSolid = new G4Box(name + "_vacuum_box", // name
199 vacBoxX, // x half width
200 vacBoxY, // y half width
201 length); // z full width (long for unambiguous intersection)
202 allSolids.insert(vacCylSolid);
203 allSolids.insert(vacRectSolid);
204
205 //intersection of both of these gives the desired shape
206 vacuumSolid = new G4IntersectionSolid(name + "_vacuum_solid", // name
207 vacCylSolid, // solid 1
208 vacRectSolid); // solid 2
209
210
211 //copper skin layer to beamscreen
212 //copper skin inner edge for subtraction (actually just like vacuum + lengthSafety)
213 G4VSolid* cuInnerCylSolid = new G4Tubs(name + "_cu_inner_cylinder", // name
214 0, // inner radius
215 cuInnerRadius, // outer radius
216 1.5*length, // length big for unambiguous subtraction (but < outerlength)
217 0, // rotation start angle
218 CLHEP::twopi); // rotation finish angle
219 //screen inner edge box solid (rectangular cross-section)
220 G4VSolid* cuInnerRectSolid = new G4Box(name + "_cu_inner_box", // name
221 cuInnerBoxX, // x half width
222 cuInnerBoxY, // y half width
223 1.7*length); // z long for unambiguous intersection
224 //screen inner intersection - 1.5*length long which is > half length for unambiguous subtraction later
225 G4VSolid* cuInnerSolid = new G4IntersectionSolid(name + "_cu_inner_solid", // name
226 cuInnerCylSolid, // solid 1
227 cuInnerRectSolid); // solid 2
228
229 // screen outer edge for subtraction (actually just like vacuum + lengthSafety)
230 // halfLength is vacLength - 1um
231 G4VSolid* cuOuterCylSolid = new G4Tubs(name + "_cu_outer_cylinder", // name
232 0, // inner radius (0 for unambiguous subtraction)
233 cuOuterRadius, // outer radius
234 halfLength, // half length
235 0, // rotation start angle
236 CLHEP::twopi); // rotation finish angle
237 //screen outer edge box solid (rectangular cross-section)
238 G4VSolid* cuOuterRectSolid = new G4Box(name + "_cu_outer_box", // name
239 cuOuterBoxX, // x half width
240 cuOuterBoxY, // y half width
241 length); // z full width (long for unambiguous intersection)
242 G4VSolid* cuOuterSolid = new G4IntersectionSolid(name + "_cu_outer_solid", // name
243 cuOuterCylSolid, // solid 1
244 cuOuterRectSolid); // solid 2
245 copperSkinSolid = new G4SubtractionSolid(name + "_copper_skin_solid",// name
246 cuOuterSolid, // this
247 cuInnerSolid); // minus this
248 allSolids.insert(cuInnerCylSolid);
249 allSolids.insert(cuInnerRectSolid);
250 allSolids.insert(cuInnerSolid);
251 allSolids.insert(cuOuterCylSolid);
252 allSolids.insert(cuOuterRectSolid);
253 allSolids.insert(cuOuterSolid);
254 allSolids.insert(copperSkinSolid);
255
256 //beampipe cylindrical solid (circular cross-section)
257 //beampipe inner edge for subtraction (actually just like vacuum + lengthSafety)
258 //using large margin of 1um here to avoid misplacement errors with compound booleans in geant4 (empirical solution)
259 G4VSolid* screenInnerCylSolid = new G4Tubs(name + "_screen_inner_cylinder", // name
260 0, // inner radius
261 bsInnerRadius, // outer radius
262 1.5*length, // length big for unambiguous subtraction (but < outerlength)
263 0, // rotation start angle
264 CLHEP::twopi); // rotation finish angle
265 //screen inner edge box solid (rectangular cross-section)
266 //using large margin of 1um here to avoid misplacement errors with compound booleans in geant4 (empirical solution)
267 G4VSolid* screenInnerRectSolid = new G4Box(name + "_screen_inner_box", // name
268 bsInnerBoxX, // x half width
269 bsInnerBoxY, // y half width
270 1.7*length); // z long for unambiguous intersection
271 //screen inner intersection - 1.5*length long which is > half length for unambiguous subtraction later
272 G4VSolid* screenInnerSolid = new G4IntersectionSolid(name + "_screen_inner_solid", // name
273 screenInnerCylSolid, // solid 1
274 screenInnerRectSolid); // solid 2
275
276 //screen outer edge for subtraction (actually just like vacuum + lengthSafety)x
277 G4VSolid* screenOuterCylSolid = new G4Tubs(name + "_screen_outer_cylinder",// name
278 0, // inner radius (0 for unambiguous subtraction)
279 bsOuterRadius, // outer radius
280 halfLength, // half length
281 0, // rotation start angle
282 CLHEP::twopi); // rotation finish angle
283 //screen outer edge box solid (rectangular cross-section)
284 G4VSolid* screenOuterRectSolid = new G4Box(name + "_screen_outer_box", // name
285 bsOuterBoxX, // x half width
286 bsOuterBoxY, // y half width
287 length); // z full width (long for unambiguous intersection)
288 G4VSolid* screenOuterSolid = new G4IntersectionSolid(name + "_screen__outersolid", // name
289 screenOuterCylSolid, // solid 1
290 screenOuterRectSolid); // solid 2
291 screenSolid = new G4SubtractionSolid(name + "_screen_solid",// name
292 screenOuterSolid, // this
293 screenInnerSolid); // minus this
294 allSolids.insert(screenInnerCylSolid);
295 allSolids.insert(screenInnerRectSolid);
296 allSolids.insert(screenInnerSolid);
297 allSolids.insert(screenOuterCylSolid);
298 allSolids.insert(screenOuterRectSolid);
299 allSolids.insert(screenOuterSolid);
300 allSolids.insert(screenSolid);
301
303 {
304 coolingPipeSolid = new G4Tubs(name + "_cooling_pipe_solid", // name
305 coolingPipeRadius, // inner radius
306 coolingPipeRadius + coolingPipeThickness, // outer radius
307 halfLength, // half length
308 0, // rotation start angle
309 CLHEP::twopi); // rotation finish angle
310
311 allSolids.insert(coolingPipeSolid);
312 }
313
314 // beampipe - ("coldbore") circular cross-section and sits outisde screen and cooling pipe
315 beamPipeSolid = new G4Tubs(name + "_beampipe_solid", // name
316 cbInnerRadius, // inner radius
317 cbOuterRadius, // outer radius
318 halfLength, // half length
319 0, // rotation start angle
320 CLHEP::twopi); // rotation finish angle
321
322 //container cylindrical solid (circular cross-section)
323 // 'length' is correct full length of object
324 containerSolid = new G4Tubs(name + "_container_cylinder", // name
325 0, // inner radius
326 containerRadius, // outer radius
327 length*0.5, // half length
328 0, // rotation start angle
329 CLHEP::twopi); // rotation finish angle
330
331 //container cylindrical solid (circular cross-section)
332 containerSubtractionSolid = new G4Tubs(name + "_subtraction_cylinder", // name
333 0, // inner radius
334 containerRadius + lengthSafety, // outer radius
335 2*length, // long length for unambiguous subtraction
336 0, // rotation start angle
337 CLHEP::twopi); // rotation finish angle
338
339 return CommonFinalConstruction(name, vacuumMaterial, beamPipeMaterial, length, containerRadius);
340}
341
343 G4double length,
344 const G4ThreeVector& inputFaceNormalIn,
345 const G4ThreeVector& outputFaceNormalIn,
346 G4double aper1,
347 G4double aper2,
348 G4double aper3,
349 G4double /*aper4*/,
350 G4Material* vacuumMaterial,
351 G4double beamPipeThickness,
352 G4Material* beamPipeMaterial,
353 const G4String& /*pointsFileIn*/,
354 const G4String& /*pointsUnitIn*/)
355{
356 // clean up after last usage
357 CleanUp();
358
359 // calculate geometrical parameters
360 CalculateGeometricalParameters(aper1, aper2, aper3, beamPipeThickness, length);
361
362 inputFaceNormal = inputFaceNormalIn;
363 outputFaceNormal = outputFaceNormalIn;
364
365 G4double contRadius = CreateGeneralAngledSolids(name, length, inputFaceNormal,
367
368 return CommonFinalConstruction(name, vacuumMaterial, beamPipeMaterial,
369 length, contRadius);
370}
371
373 G4Material* vacuumMaterial,
374 G4Material* beamPipeMaterial,
375 G4double length,
376 G4double contRadius)
377{
379 beamPipeMaterial, length);
380
381 // record extents
382 BDSExtent ext = BDSExtent(contRadius, contRadius, length*0.5);
383
384 // build the BDSBeamPipe instance and return it
385 BDSBeamPipe* aPipe = BuildBeamPipeAndRegisterVolumes(ext,contRadius);
386
387 // register sensitive volumes
389 {
390 aPipe->RegisterSensitiveVolume(screenLV, BDSSDType::energydep);
391 aPipe->RegisterSensitiveVolume(copperSkinLV, BDSSDType::energydep);
393 {aPipe->RegisterSensitiveVolume(coolingPipeLV, BDSSDType::energydep);}
394 }
395
396 return aPipe;
397}
398
400 G4Material* vacuumMaterialIn,
401 G4Material* beamPipeMaterialIn)
402{
403 BDSBeamPipeFactoryBase::BuildLogicalVolumes(name,vacuumMaterialIn,beamPipeMaterialIn);
404
405 // get materials
406 G4Material* copper2k = BDSMaterials::Instance()->GetMaterial("cu_2k");
407
408 copperSkinLV = new G4LogicalVolume(copperSkinSolid,
409 copper2k,
410 name + "_copper_lv");
411
412 screenLV = new G4LogicalVolume(screenSolid,
413 beamPipeMaterialIn,
414 name + "_screen_lv");
415
417 {
418 coolingPipeLV = new G4LogicalVolume(coolingPipeSolid,
419 beamPipeMaterialIn,
420 name + "_cooling_pipe_lv");
421 allLogicalVolumes.insert(coolingPipeLV);
422 }
423 allLogicalVolumes.insert(copperSkinLV);
424 allLogicalVolumes.insert(screenLV);
425}
426
427void BDSBeamPipeFactoryLHCDetailed::SetVisAttributes(G4Material* beamPipeMaterialIn)
428{
430
431 // copper skin
432 G4VisAttributes* cuVisAttr = new G4VisAttributes(*BDSColours::Instance()->GetColour("LHCcopperskin"));
433 cuVisAttr->SetForceLineSegmentsPerCircle(nSegmentsPerCircle);
434 cuVisAttr->SetVisibility(true);
435 allVisAttributes.insert(cuVisAttr);
436
437 // beampipe
438 G4VisAttributes* pipeVisAttr = new G4VisAttributes(*BDSColours::Instance()->GetColour("beampipe"));
439 pipeVisAttr->SetVisibility(true);
440 pipeVisAttr->SetForceLineSegmentsPerCircle(nSegmentsPerCircle);
441 allVisAttributes.insert(pipeVisAttr);
442
443 copperSkinLV->SetVisAttributes(cuVisAttr);
444 screenLV->SetVisAttributes(pipeVisAttr);
446 {coolingPipeLV->SetVisAttributes(pipeVisAttr);}
447}
448
450{
452 // get the user limits from the vacuum volume
453 // ownership registration done in base class method so no need to register it
454 auto ul = vacuumLV->GetUserLimits();
455
456 copperSkinLV->SetUserLimits(ul);
457 screenLV->SetUserLimits(ul);
459 {coolingPipeLV->SetUserLimits(ul);}
460}
461
463{
465
466 copperSkinPV = new G4PVPlacement(nullptr, // no rotation
467 G4ThreeVector(), // position
468 copperSkinLV, // lv to be placed
469 name + "_copper_skin_pv", // name
470 containerLV, // mother lv to be placed in
471 false, // no boolean operation
472 0, // copy number
473 checkOverlaps); // whether to check overlaps
474
475 screenPV = new G4PVPlacement(nullptr, // no rotation
476 G4ThreeVector(), // position
477 screenLV, // lv to be placed
478 name + "_screen_pv", // name
479 containerLV, // mother lv to be placed in
480 false, // no boolean operation
481 0, // copy number
482 checkOverlaps); // whether to check overlaps
483
484 allPhysicalVolumes.insert(copperSkinPV);
485 allPhysicalVolumes.insert(screenPV);
486
488 {
489 G4ThreeVector coolingPipeTopPosition;
490 G4ThreeVector coolingPipeBottomPosition;
492 { // horizontal shape -> vertical displacement for pipes
493 coolingPipeTopPosition = G4ThreeVector(0,coolingPipeOffset,0);
494 coolingPipeBottomPosition = G4ThreeVector(0,-coolingPipeOffset,0);
495 }
496 else
497 { // vertical shape -> horizontal displacement for pipes
498 coolingPipeTopPosition = G4ThreeVector(coolingPipeOffset,0,0);
499 coolingPipeBottomPosition = G4ThreeVector(-coolingPipeOffset,0,0);
500 }
501
502 coolingPipeTopPV = new G4PVPlacement(nullptr, // no rotation
503 coolingPipeTopPosition, // position
504 coolingPipeLV, // lv to be placed
505 name + "_cooling_pipe_top_pv",// name
506 containerLV, // mother lv to be placed in
507 false, // no boolean operation
508 0, // copy number
509 checkOverlaps); // whether to check overlaps
510
511 coolingPipeBottomPV = new G4PVPlacement(nullptr, // no rotation
512 coolingPipeBottomPosition, // position
513 coolingPipeLV, // lv to be placed
514 name + "_cooling_pipe_bottom_pv", // name
515 containerLV, // mother lv to be placed in
516 false, // no boolean operation
517 0, // copy number
518 checkOverlaps); // whether to check overlaps
519
520 allPhysicalVolumes.insert(coolingPipeTopPV);
521 allPhysicalVolumes.insert(coolingPipeBottomPV);
522 }
523}
524
528 G4double length,
529 const G4ThreeVector& inputface,
530 const G4ThreeVector& outputface)
531{
532 // build the solids
533 //vacuum cylindrical solid (circular cross-section)
534 G4VSolid* vacCylSolid = new G4CutTubs(name + "_vacuum_cylinder", // name
535 0, // inner radius
536 vacRadius, // outer radius
537 vacHalfLength, // half length
538 0, // rotation start angle
539 CLHEP::twopi, // rotation finish angle
540 inputface, // input face normal
541 outputface); // output face normal
542 //vacuum box solid (rectangular cross-section)
543 G4VSolid* vacRectSolid = new G4Box(name + "_vacuum_box", // name
544 vacBoxX, // x half width
545 vacBoxY, // y half width
546 length); // z full width (long for unambiguous intersection)
547 //intersection of both of these gives the desired shape
548 vacuumSolid = new G4IntersectionSolid(name + "_vacuum_solid", // name
549 vacCylSolid, // solid 1
550 vacRectSolid); // solid 2
551 allSolids.insert(vacCylSolid);
552 allSolids.insert(vacRectSolid);
553
554 //copper skin layer to beamscreen
555 //copper skin inner edge for subtraction (actually just like vacuum + lengthSafety)
556 G4VSolid* cuInnerCylSolid = new G4CutTubs(name + "_cu_inner_cylinder", // name
557 0, // inner radius
558 cuInnerRadius, // outer radius
559 1.5*length, // length big for unambiguous subtraction (but < outerlength)
560 0, // rotation start angle
561 CLHEP::twopi, // rotation finish angle
562 inputface, // input face normal
563 outputface); // output face normal
564 //screen inner edge box solid (rectangular cross-section)
565 G4VSolid* cuInnerRectSolid = new G4Box(name + "_cu_inner_box", // name
566 cuInnerBoxX, // x half width
567 cuInnerBoxY, // y half width
568 1.7*length); // z long for unambiguous intersection
569 //screen inner intersection - 1.5*length long which is > half length for unambiguous subtraction later
570 G4VSolid* cuInnerSolid = new G4IntersectionSolid(name + "_cu_inner_solid", // name
571 cuInnerCylSolid, // solid 1
572 cuInnerRectSolid); // solid 2
573
574 //screen outer edge for subtraction (actually just like vacuum + lengthSafety)x
575 G4VSolid* cuOuterCylSolid = new G4CutTubs(name + "_cu_outer_cylinder", // name
576 0, // inner radius (0 for unambiguous subtraction)
577 cuOuterRadius, // outer radius
578 halfLength, // half length
579 0, // rotation start angle
580 CLHEP::twopi, // rotation finish angle
581 inputface, // input face normal
582 outputface); // output face normal
583 //screen outer edge box solid (rectangular cross-section)
584 G4VSolid* cuOuterRectSolid = new G4Box(name + "_cu_outer_box", // name
585 cuOuterBoxX, // x half width
586 cuOuterBoxY, // y half width
587 length); // z full width (long for unambiguous intersection)
588 G4VSolid* cuOuterSolid = new G4IntersectionSolid(name + "_cu_outer_solid", // name
589 cuOuterCylSolid, // solid 1
590 cuOuterRectSolid); // solid 2
591 copperSkinSolid = new G4SubtractionSolid(name + "_copper_skin_solid",// name
592 cuOuterSolid, // this
593 cuInnerSolid); // minus this
594 allSolids.insert(cuInnerCylSolid);
595 allSolids.insert(cuInnerRectSolid);
596 allSolids.insert(cuInnerSolid);
597 allSolids.insert(cuOuterCylSolid);
598 allSolids.insert(cuOuterRectSolid);
599 allSolids.insert(cuOuterSolid);
600 allSolids.insert(copperSkinSolid);
601
602 //beampipe cylindrical solid (circular cross-section)
603 //beampipe inner edge for subtraction (actually just like vacuum + lengthSafety)
604 G4VSolid* screenInnerCylSolid = new G4CutTubs(name + "_screen_inner_cylinder", // name
605 0, // inner radius
606 bsInnerRadius, // outer radius
607 1.5*length, // length big for unambiguous subtraction (but < outerlength)
608 0, // rotation start angle
609 CLHEP::twopi, // rotation finish angle
610 inputface, // input face normal
611 outputface); // output face normal
612 //screen inner edge box solid (rectangular cross-section)
613 G4VSolid* screenInnerRectSolid = new G4Box(name + "_screen_inner_box", // name
614 bsInnerBoxX, // x half width
615 bsInnerBoxY, // y half width
616 1.7*length); // z long for unambiguous intersection
617 //screen inner intersection - 1.5*length long which is > half length for unambiguous subtraction later
618 G4VSolid* screenInnerSolid = new G4IntersectionSolid(name + "_screen_inner_solid", // name
619 screenInnerCylSolid, // solid 1
620 screenInnerRectSolid); // solid 2
621
622 //screen outer edge for subtraction (actually just like vacuum + lengthSafety)x
623 G4VSolid* screenOuterCylSolid = new G4CutTubs(name + "_screen_outer_cylinder",// name
624 0, // inner radius (0 for unambiguous subtraction)
625 bsOuterRadius, // outer radius
626 halfLength, // half length
627 0, // rotation start angle
628 CLHEP::twopi, // rotation finish angle
629 inputface, // input face normal
630 outputface); // output face normal
631 //screen outer edge box solid (rectangular cross-section)
632 G4VSolid* screenOuterRectSolid = new G4Box(name + "_screen_outer_box", // name
633 bsOuterBoxX, // x half width
634 bsOuterBoxY, // y half width
635 length); // z full width (long for unambiguous intersection)
636 G4VSolid* screenOuterSolid = new G4IntersectionSolid(name + "_pipe_outer_solid", // name
637 screenOuterCylSolid, // solid 1
638 screenOuterRectSolid); // solid 2
639
640 screenSolid = new G4SubtractionSolid(name + "_screen_solid",// name
641 screenOuterSolid, // this
642 screenInnerSolid); // minus this
643
644 allSolids.insert(screenInnerCylSolid);
645 allSolids.insert(screenInnerRectSolid);
646 allSolids.insert(screenInnerSolid);
647 allSolids.insert(screenOuterCylSolid);
648 allSolids.insert(screenOuterRectSolid);
649 allSolids.insert(screenOuterSolid);
650 allSolids.insert(screenSolid);
651
653 {
654 coolingPipeSolid = new G4CutTubs(name + "_cooling_pipe_solid", // name
655 coolingPipeRadius, // inner radius
656 coolingPipeRadius + coolingPipeThickness, // outer radius
657 halfLength, // half length
658 0, // rotation start angle
659 CLHEP::twopi, // rotation finish angle
660 inputface, // input face normal
661 outputface); // output face normal
662
663 allSolids.insert(coolingPipeSolid);
664 }
665
666 // beampipe - ("coldbore") circular cross-section and sits outisde screen and cooling pipe
667 beamPipeSolid = new G4CutTubs(name + "_beampipe_solid", // name
668 cbInnerRadius, // inner radius
669 cbOuterRadius, // outer radius
670 halfLength, // half length
671 0, // rotation start angle
672 CLHEP::twopi, // rotation finish angle
673 inputface, // input face normal
674 outputface); // output face normal
675
676 //container cylindrical solid (circular cross-section)
677 // 'length' is correct full length of object
678 containerSolid = new G4CutTubs(name + "_container_cylinder", // name
679 0, // inner radius
680 containerRadius, // outer radius
681 length*0.5, // half length
682 0, // rotation start angle
683 CLHEP::twopi, // rotation finish angle
684 inputface, // input face normal
685 outputface); // output face normal
686
687 //container cylindrical solid (circular cross-section)
688 containerSubtractionSolid = new G4Tubs(name + "_subtraction_cylinder", // name
689 0, // inner radius
690 containerRadius + lengthSafety, // outer radius
691 2*length, // long length for unambiguous subtraction
692 0, // rotation start angle
693 CLHEP::twopi); // rotation finish angle
694
695 // return the container radius as everything is calculated in this function
696 return containerRadius;
697}
virtual void SetVisAttributes(G4Material *beamPipeMaterialIn)
Set visual attributes.
G4ThreeVector outputFaceNormal
For recording the face normals in the finished pipe component.
virtual void BuildLogicalVolumes(const G4String &nameIn, G4Material *vacuumMaterialIn, G4Material *beamPipeMaterialIn)
build logical volumes
G4ThreeVector inputFaceNormal
For recording the face normals in the finished pipe component.
void CommonConstruction(const G4String &nameIn, G4Material *vacuumMaterialIn, G4Material *beamPipeMaterialIn, G4double length)
finalise beampipe construction
BDSBeamPipe * BuildBeamPipeAndRegisterVolumes(BDSExtent extent, G4double containerRadius, G4bool containerIsCircular=false)
build beampipe and register logical volumes
virtual void PlaceComponents(const G4String &nameIn)
Place volumes.
G4bool sensitiveBeamPipe
Whether the beam pipe will record energy deposition.
G4VSolid * containerSubtractionSolid
Longer (in length) version of container solid for unambiguous subtraction.
virtual void SetUserLimits(G4double length)
Set user limits.
G4double GetFullWidthOfCoolingPipe()
Access cooling pipe information from factory for parameter tests.
virtual void SetVisAttributes(G4Material *beamPipeMaterialIn)
Set visual attributes.
void InitialiseGeometricalParameters()
Utility function to initialise the geometry parameters.
BDSBeamPipe * CommonFinalConstruction(const G4String &name, G4Material *vacuumMaterial, G4Material *beamPipeMaterial, G4double length, G4double containerRadius)
G4bool buildCoolingPipe
Whether to build the cooling pipes on either side.
virtual void BuildLogicalVolumes(const G4String &nameIn, G4Material *vacuumMaterialIn, G4Material *beamPipeMaterialIn)
build logical volumes
G4double cbInnerRadius
Cold bore geometrical parameters.
G4double vacHalfLength
General length variable (to avoid mistakes)
G4double coolingPipeOffset
Cooling pipe geometrical parameters.
virtual void PlaceComponents(const G4String &nameIn)
Place volumes.
G4double containerRadius
Container geometrical parameters.
G4double coldBoreThickness
Parameters that control the design.
virtual BDSBeamPipe * CreateBeamPipe(const G4String &nameIn, G4double lengthIn, G4double aper1=0, G4double aper2=0, G4double aper3=0, G4double aper4=0, G4Material *vacuumMaterialIn=nullptr, G4double beamPipeThicknessIn=0, G4Material *beamPipeMaterialIn=nullptr, const G4String &pointsFileIn="", const G4String &pointsUnitIn="")
create a flat ended beampipe
G4double cuInnerRadius
Copper skin geometrical parameters.
G4double bsInnerRadius
Beam screen geometrical parameters.
virtual void CleanUp()
Clean up extra pointers particular to this factory before use.
G4double CreateGeneralAngledSolids(const G4String &name, G4double length, const G4ThreeVector &inputface, const G4ThreeVector &outputface)
virtual void SetUserLimits(G4double length)
Set user limits.
void CalculateGeometricalParameters(G4double aper1, G4double aper2, G4double aper3, G4double beamPipeThickness, G4double length)
A holder class for a piece of beam pipe geometry.
Definition: BDSBeamPipe.hh:45
static BDSColours * Instance()
singleton pattern
Definition: BDSColours.cc:33
Holder for +- extents in 3 dimensions.
Definition: BDSExtent.hh:39
G4bool checkOverlaps
Cache of global constants variable.
G4double nSegmentsPerCircle
Cache of global constants variable.
G4double lengthSafety
Cache of global constants variable.
void RegisterSensitiveVolume(G4LogicalVolume *sensitiveVolume, BDSSDType sensitivityType)
static BDSMaterials * Instance()
Singleton pattern access.
Definition: BDSMaterials.cc:38
G4Material * GetMaterial(G4String material) const
Get material by name.