BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSBeamPipeFactoryLHCDetailed.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2023.
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 G4Material* vacuumMateiralIn)
429{
430 BDSBeamPipeFactoryBase::SetVisAttributes(beamPipeMaterialIn, vacuumMateiralIn);
431
432 // copper skin
433 G4VisAttributes* cuVisAttr = new G4VisAttributes(*BDSColours::Instance()->GetColour("LHCcopperskin"));
434 cuVisAttr->SetForceLineSegmentsPerCircle(nSegmentsPerCircle);
435 cuVisAttr->SetVisibility(true);
436 allVisAttributes.insert(cuVisAttr);
437
438 // beampipe
439 G4VisAttributes* pipeVisAttr = new G4VisAttributes(*BDSColours::Instance()->GetColour("beampipe"));
440 pipeVisAttr->SetVisibility(true);
441 pipeVisAttr->SetForceLineSegmentsPerCircle(nSegmentsPerCircle);
442 allVisAttributes.insert(pipeVisAttr);
443
444 copperSkinLV->SetVisAttributes(cuVisAttr);
445 screenLV->SetVisAttributes(pipeVisAttr);
447 {coolingPipeLV->SetVisAttributes(pipeVisAttr);}
448}
449
451{
453 // get the user limits from the vacuum volume
454 // ownership registration done in base class method so no need to register it
455 auto ul = vacuumLV->GetUserLimits();
456
457 copperSkinLV->SetUserLimits(ul);
458 screenLV->SetUserLimits(ul);
460 {coolingPipeLV->SetUserLimits(ul);}
461}
462
464{
466
467 copperSkinPV = new G4PVPlacement(nullptr, // no rotation
468 G4ThreeVector(), // position
469 copperSkinLV, // lv to be placed
470 name + "_copper_skin_pv", // name
471 containerLV, // mother lv to be placed in
472 false, // no boolean operation
473 0, // copy number
474 checkOverlaps); // whether to check overlaps
475
476 screenPV = new G4PVPlacement(nullptr, // no rotation
477 G4ThreeVector(), // position
478 screenLV, // lv to be placed
479 name + "_screen_pv", // name
480 containerLV, // mother lv to be placed in
481 false, // no boolean operation
482 0, // copy number
483 checkOverlaps); // whether to check overlaps
484
485 allPhysicalVolumes.insert(copperSkinPV);
486 allPhysicalVolumes.insert(screenPV);
487
489 {
490 G4ThreeVector coolingPipeTopPosition;
491 G4ThreeVector coolingPipeBottomPosition;
493 { // horizontal shape -> vertical displacement for pipes
494 coolingPipeTopPosition = G4ThreeVector(0,coolingPipeOffset,0);
495 coolingPipeBottomPosition = G4ThreeVector(0,-coolingPipeOffset,0);
496 }
497 else
498 { // vertical shape -> horizontal displacement for pipes
499 coolingPipeTopPosition = G4ThreeVector(coolingPipeOffset,0,0);
500 coolingPipeBottomPosition = G4ThreeVector(-coolingPipeOffset,0,0);
501 }
502
503 coolingPipeTopPV = new G4PVPlacement(nullptr, // no rotation
504 coolingPipeTopPosition, // position
505 coolingPipeLV, // lv to be placed
506 name + "_cooling_pipe_top_pv",// name
507 containerLV, // mother lv to be placed in
508 false, // no boolean operation
509 0, // copy number
510 checkOverlaps); // whether to check overlaps
511
512 coolingPipeBottomPV = new G4PVPlacement(nullptr, // no rotation
513 coolingPipeBottomPosition, // position
514 coolingPipeLV, // lv to be placed
515 name + "_cooling_pipe_bottom_pv", // name
516 containerLV, // mother lv to be placed in
517 false, // no boolean operation
518 0, // copy number
519 checkOverlaps); // whether to check overlaps
520
521 allPhysicalVolumes.insert(coolingPipeTopPV);
522 allPhysicalVolumes.insert(coolingPipeBottomPV);
523 }
524}
525
529 G4double length,
530 const G4ThreeVector& inputface,
531 const G4ThreeVector& outputface)
532{
533 // build the solids
534 //vacuum cylindrical solid (circular cross-section)
535 G4VSolid* vacCylSolid = new G4CutTubs(name + "_vacuum_cylinder", // name
536 0, // inner radius
537 vacRadius, // outer radius
538 vacHalfLength, // half length
539 0, // rotation start angle
540 CLHEP::twopi, // rotation finish angle
541 inputface, // input face normal
542 outputface); // output face normal
543 //vacuum box solid (rectangular cross-section)
544 G4VSolid* vacRectSolid = new G4Box(name + "_vacuum_box", // name
545 vacBoxX, // x half width
546 vacBoxY, // y half width
547 length); // z full width (long for unambiguous intersection)
548 //intersection of both of these gives the desired shape
549 vacuumSolid = new G4IntersectionSolid(name + "_vacuum_solid", // name
550 vacCylSolid, // solid 1
551 vacRectSolid); // solid 2
552 allSolids.insert(vacCylSolid);
553 allSolids.insert(vacRectSolid);
554
555 //copper skin layer to beamscreen
556 //copper skin inner edge for subtraction (actually just like vacuum + lengthSafety)
557 G4VSolid* cuInnerCylSolid = new G4CutTubs(name + "_cu_inner_cylinder", // name
558 0, // inner radius
559 cuInnerRadius, // outer radius
560 1.5*length, // length big for unambiguous subtraction (but < outerlength)
561 0, // rotation start angle
562 CLHEP::twopi, // rotation finish angle
563 inputface, // input face normal
564 outputface); // output face normal
565 //screen inner edge box solid (rectangular cross-section)
566 G4VSolid* cuInnerRectSolid = new G4Box(name + "_cu_inner_box", // name
567 cuInnerBoxX, // x half width
568 cuInnerBoxY, // y half width
569 1.7*length); // z long for unambiguous intersection
570 //screen inner intersection - 1.5*length long which is > half length for unambiguous subtraction later
571 G4VSolid* cuInnerSolid = new G4IntersectionSolid(name + "_cu_inner_solid", // name
572 cuInnerCylSolid, // solid 1
573 cuInnerRectSolid); // solid 2
574
575 //screen outer edge for subtraction (actually just like vacuum + lengthSafety)x
576 G4VSolid* cuOuterCylSolid = new G4CutTubs(name + "_cu_outer_cylinder", // name
577 0, // inner radius (0 for unambiguous subtraction)
578 cuOuterRadius, // outer radius
579 halfLength, // half length
580 0, // rotation start angle
581 CLHEP::twopi, // rotation finish angle
582 inputface, // input face normal
583 outputface); // output face normal
584 //screen outer edge box solid (rectangular cross-section)
585 G4VSolid* cuOuterRectSolid = new G4Box(name + "_cu_outer_box", // name
586 cuOuterBoxX, // x half width
587 cuOuterBoxY, // y half width
588 length); // z full width (long for unambiguous intersection)
589 G4VSolid* cuOuterSolid = new G4IntersectionSolid(name + "_cu_outer_solid", // name
590 cuOuterCylSolid, // solid 1
591 cuOuterRectSolid); // solid 2
592 copperSkinSolid = new G4SubtractionSolid(name + "_copper_skin_solid",// name
593 cuOuterSolid, // this
594 cuInnerSolid); // minus this
595 allSolids.insert(cuInnerCylSolid);
596 allSolids.insert(cuInnerRectSolid);
597 allSolids.insert(cuInnerSolid);
598 allSolids.insert(cuOuterCylSolid);
599 allSolids.insert(cuOuterRectSolid);
600 allSolids.insert(cuOuterSolid);
601 allSolids.insert(copperSkinSolid);
602
603 //beampipe cylindrical solid (circular cross-section)
604 //beampipe inner edge for subtraction (actually just like vacuum + lengthSafety)
605 G4VSolid* screenInnerCylSolid = new G4CutTubs(name + "_screen_inner_cylinder", // name
606 0, // inner radius
607 bsInnerRadius, // outer radius
608 1.5*length, // length big for unambiguous subtraction (but < outerlength)
609 0, // rotation start angle
610 CLHEP::twopi, // rotation finish angle
611 inputface, // input face normal
612 outputface); // output face normal
613 //screen inner edge box solid (rectangular cross-section)
614 G4VSolid* screenInnerRectSolid = new G4Box(name + "_screen_inner_box", // name
615 bsInnerBoxX, // x half width
616 bsInnerBoxY, // y half width
617 1.7*length); // z long for unambiguous intersection
618 //screen inner intersection - 1.5*length long which is > half length for unambiguous subtraction later
619 G4VSolid* screenInnerSolid = new G4IntersectionSolid(name + "_screen_inner_solid", // name
620 screenInnerCylSolid, // solid 1
621 screenInnerRectSolid); // solid 2
622
623 //screen outer edge for subtraction (actually just like vacuum + lengthSafety)x
624 G4VSolid* screenOuterCylSolid = new G4CutTubs(name + "_screen_outer_cylinder",// name
625 0, // inner radius (0 for unambiguous subtraction)
626 bsOuterRadius, // outer radius
627 halfLength, // half length
628 0, // rotation start angle
629 CLHEP::twopi, // rotation finish angle
630 inputface, // input face normal
631 outputface); // output face normal
632 //screen outer edge box solid (rectangular cross-section)
633 G4VSolid* screenOuterRectSolid = new G4Box(name + "_screen_outer_box", // name
634 bsOuterBoxX, // x half width
635 bsOuterBoxY, // y half width
636 length); // z full width (long for unambiguous intersection)
637 G4VSolid* screenOuterSolid = new G4IntersectionSolid(name + "_pipe_outer_solid", // name
638 screenOuterCylSolid, // solid 1
639 screenOuterRectSolid); // solid 2
640
641 screenSolid = new G4SubtractionSolid(name + "_screen_solid",// name
642 screenOuterSolid, // this
643 screenInnerSolid); // minus this
644
645 allSolids.insert(screenInnerCylSolid);
646 allSolids.insert(screenInnerRectSolid);
647 allSolids.insert(screenInnerSolid);
648 allSolids.insert(screenOuterCylSolid);
649 allSolids.insert(screenOuterRectSolid);
650 allSolids.insert(screenOuterSolid);
651 allSolids.insert(screenSolid);
652
654 {
655 coolingPipeSolid = new G4CutTubs(name + "_cooling_pipe_solid", // name
656 coolingPipeRadius, // inner radius
657 coolingPipeRadius + coolingPipeThickness, // outer radius
658 halfLength, // half length
659 0, // rotation start angle
660 CLHEP::twopi, // rotation finish angle
661 inputface, // input face normal
662 outputface); // output face normal
663
664 allSolids.insert(coolingPipeSolid);
665 }
666
667 // beampipe - ("coldbore") circular cross-section and sits outisde screen and cooling pipe
668 beamPipeSolid = new G4CutTubs(name + "_beampipe_solid", // name
669 cbInnerRadius, // inner radius
670 cbOuterRadius, // outer radius
671 halfLength, // half length
672 0, // rotation start angle
673 CLHEP::twopi, // rotation finish angle
674 inputface, // input face normal
675 outputface); // output face normal
676
677 //container cylindrical solid (circular cross-section)
678 // 'length' is correct full length of object
679 containerSolid = new G4CutTubs(name + "_container_cylinder", // name
680 0, // inner radius
681 containerRadius, // outer radius
682 length*0.5, // half length
683 0, // rotation start angle
684 CLHEP::twopi, // rotation finish angle
685 inputface, // input face normal
686 outputface); // output face normal
687
688 //container cylindrical solid (circular cross-section)
689 containerSubtractionSolid = new G4Tubs(name + "_subtraction_cylinder", // name
690 0, // inner radius
691 containerRadius + lengthSafety, // outer radius
692 2*length, // long length for unambiguous subtraction
693 0, // rotation start angle
694 CLHEP::twopi); // rotation finish angle
695
696 // return the container radius as everything is calculated in this function
697 return containerRadius;
698}
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
virtual void SetVisAttributes(G4Material *beamPipeMaterialIn, G4Material *vacuumMaterialIn)
Set visual attributes.
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.
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.
virtual void SetVisAttributes(G4Material *beamPipeMaterialIn, G4Material *vacuumMaterialIn)
Set visual attributes.
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 lengthSafety
Cache of global constants variable.
G4int nSegmentsPerCircle
Cache of global constants variable.
void RegisterSensitiveVolume(G4LogicalVolume *sensitiveVolume, BDSSDType sensitivityType)
static BDSMaterials * Instance()
Singleton pattern access.
Definition: BDSMaterials.cc:39
G4Material * GetMaterial(G4String material) const
Get material by name.