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) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "BDSBeamPipeFactoryBase.hh"
19#include "BDSBeamPipeFactoryLHCDetailed.hh"
20#include "BDSBeamPipe.hh"
21#include "BDSColours.hh"
22#include "BDSExtent.hh"
23#include "BDSGlobalConstants.hh"
24#include "BDSMaterials.hh"
25#include "BDSSDType.hh"
26
27#include "globals.hh" // geant4 globals / types
28#include "G4Box.hh"
29#include "G4CutTubs.hh"
30#include "G4IntersectionSolid.hh"
31#include "G4LogicalVolume.hh"
32#include "G4Material.hh"
33#include "G4PVPlacement.hh"
34#include "G4SubtractionSolid.hh"
35#include "G4ThreeVector.hh"
36#include "G4Tubs.hh"
37#include "G4VisAttributes.hh"
38#include "G4VSolid.hh"
39
40#include <cmath>
41#include <set>
42#include <utility> // for std::pair
43
44BDSBeamPipeFactoryLHCDetailed::BDSBeamPipeFactoryLHCDetailed()
45{
46 coldBoreThickness = 1.5*CLHEP::mm;
47 coolingPipeThickness = 0.53*CLHEP::mm;
48 coolingPipeRadius = 3.7*CLHEP::mm*0.5; // will be overwritten if needs be to fit inside beampipe
49 coolingPipeOffset = 0.0; //initialised only
50 copperSkinThickness = 75*CLHEP::um;
52}
53
55{
57 BDSBeamPipeFactoryBase::CleanUp();
58}
59
61{
62 copperSkinSolid = nullptr; // the copper skin
63 screenSolid = nullptr; // the beam screen (first bit of aperture)
64 coolingPipeSolid = nullptr; // small cooling pipe above and below beam screen
65 copperSkinLV = nullptr;
66 screenLV = nullptr;
67 coolingPipeLV = nullptr;
68 copperSkinPV = nullptr;
69 screenPV = nullptr;
70 coolingPipeTopPV = nullptr;
71 coolingPipeBottomPV = nullptr;
72
74}
75
77{
78 vacRadius = 0, vacBoxX = 0, vacBoxY = 0;
79
80 cuInnerRadius = 0, cuInnerBoxX = 0, cuInnerBoxY = 0;
81 cuOuterRadius = 0, cuOuterBoxX = 0, cuOuterBoxY = 0;
82
83 bsInnerRadius = 0, bsInnerBoxX = 0, bsInnerBoxY = 0;
84 bsOuterRadius = 0, bsOuterBoxX = 0, bsOuterBoxY = 0;
85
86 cbInnerRadius = 0, cbOuterRadius = 0;
87
89
90 vacHalfLength = 0;
91 halfLength = 0;
92
94 verticalOrientation = true; // arbitrary, will be overwritten
95 buildCoolingPipe = true;
96}
97
98
100{
101 return coolingPipeRadius + coolingPipeThickness + 2*lengthSafety;
102}
103
105 G4double aper2,
106 G4double aper3,
107 G4double beamPipeThickness,
108 G4double length)
109{
110 // vacuum volume
111 vacRadius = aper3;
112 vacBoxX = aper1;
113 vacBoxY = aper2;
114
115 // copper skin geometrical parameters
116 cuInnerRadius = vacRadius + 1*CLHEP::um;
117 cuInnerBoxX = vacBoxX + 1*CLHEP::um;
118 cuInnerBoxY = vacBoxY + 1*CLHEP::um;
119 cuOuterRadius = cuInnerRadius + copperSkinThickness;
120 cuOuterBoxX = cuInnerBoxX + copperSkinThickness;
121 cuOuterBoxY = cuInnerBoxY + copperSkinThickness;
122
123 // beam screen geometrical parameters
124 bsInnerRadius = cuOuterRadius + 1*CLHEP::um;
125 bsInnerBoxX = cuOuterBoxX + 1*CLHEP::um;
126 bsInnerBoxY = cuOuterBoxY + 1*CLHEP::um;
127 bsOuterRadius = bsInnerRadius + beamPipeThickness;
128 bsOuterBoxX = bsInnerBoxX + beamPipeThickness;
129 bsOuterBoxY = bsInnerBoxY + beamPipeThickness;
130
131 // cold bore geometrical parameters
132 cbInnerRadius = bsOuterRadius + 1*CLHEP::um;
133 cbOuterRadius = cbInnerRadius + coldBoreThickness;
134
135 // container geometrical parameters
136 containerRadius = cbOuterRadius + 1*CLHEP::um;
137
138 // general length variable (to avoid mistakes)
139 vacHalfLength = length*0.5 - lengthSafety;
140 halfLength = length*0.5 - 1*CLHEP::um;
141
142 // cooling pipe geometrical parameters
143 G4double fullWidthOfCoolingPipe = coolingPipeRadius + coolingPipeThickness + 1*CLHEP::um;
144 if (aper1 > aper2)
145 {
146 coolingPipeOffset = bsOuterBoxY + fullWidthOfCoolingPipe;
147 verticalOrientation = false;
148 }
149 else
150 {
151 coolingPipeOffset = bsOuterBoxX + fullWidthOfCoolingPipe;
152 verticalOrientation = true;
153 }
154
155 G4double valueToCompare;
157 {valueToCompare = bsOuterBoxX;}
158 else
159 {valueToCompare = bsInnerBoxY;}
160
161 G4double gapForCoolingPipe = std::abs(cbInnerRadius - valueToCompare);
162 if (gapForCoolingPipe < fullWidthOfCoolingPipe + 1*CLHEP::um)
163 {buildCoolingPipe = false;}
164}
165
166
168 G4double length,
169 G4double aper1,
170 G4double aper2,
171 G4double aper3,
172 G4double /*aper4*/,
173 G4Material* vacuumMaterial,
174 G4double beamPipeThickness,
175 G4Material* beamPipeMaterial,
176 const G4String& /*pointsFileIn*/,
177 const G4String& /*pointsUnitIn*/)
178{
179 // clean up after last usage
180 CleanUp();
181
182 // we override the material of the beam pipe
183 beamPipeMaterial = BDSMaterials::Instance()->GetMaterial("stainless_steel_316LN_2K");
184
185 // calculate geometrical parameters
186 CalculateGeometricalParameters(aper1, aper2, aper3, beamPipeThickness, length);
187
188 // build the solids
189 //vacuum cylindrical solid (circular cross-section)
190 G4VSolid* vacCylSolid = new G4Tubs(name + "_vacuum_cylinder", // name
191 0, // inner radius
192 vacRadius, // outer radius
193 vacHalfLength, // half length
194 0, // rotation start angle
195 CLHEP::twopi); // rotation finish angle
196 //vacuum box solid (rectangular cross-section)
197 G4VSolid* vacRectSolid = new G4Box(name + "_vacuum_box", // name
198 vacBoxX, // x half width
199 vacBoxY, // y half width
200 length); // z full width (long for unambiguous intersection)
201 allSolids.insert(vacCylSolid);
202 allSolids.insert(vacRectSolid);
203
204 //intersection of both of these gives the desired shape
205 vacuumSolid = new G4IntersectionSolid(name + "_vacuum_solid", // name
206 vacCylSolid, // solid 1
207 vacRectSolid); // solid 2
208
209
210 //copper skin layer to beamscreen
211 //copper skin inner edge for subtraction (actually just like vacuum + lengthSafety)
212 G4VSolid* cuInnerCylSolid = new G4Tubs(name + "_cu_inner_cylinder", // name
213 0, // inner radius
214 cuInnerRadius, // outer radius
215 1.5*length, // length big for unambiguous subtraction (but < outerlength)
216 0, // rotation start angle
217 CLHEP::twopi); // rotation finish angle
218 //screen inner edge box solid (rectangular cross-section)
219 G4VSolid* cuInnerRectSolid = new G4Box(name + "_cu_inner_box", // name
220 cuInnerBoxX, // x half width
221 cuInnerBoxY, // y half width
222 1.7*length); // z long for unambiguous intersection
223 //screen inner intersection - 1.5*length long which is > half length for unambiguous subtraction later
224 G4VSolid* cuInnerSolid = new G4IntersectionSolid(name + "_cu_inner_solid", // name
225 cuInnerCylSolid, // solid 1
226 cuInnerRectSolid); // solid 2
227
228 // screen outer edge for subtraction (actually just like vacuum + lengthSafety)
229 // halfLength is vacLength - 1um
230 G4VSolid* cuOuterCylSolid = new G4Tubs(name + "_cu_outer_cylinder", // name
231 0, // inner radius (0 for unambiguous subtraction)
232 cuOuterRadius, // outer radius
233 halfLength, // half length
234 0, // rotation start angle
235 CLHEP::twopi); // rotation finish angle
236 //screen outer edge box solid (rectangular cross-section)
237 G4VSolid* cuOuterRectSolid = new G4Box(name + "_cu_outer_box", // name
238 cuOuterBoxX, // x half width
239 cuOuterBoxY, // y half width
240 length); // z full width (long for unambiguous intersection)
241 G4VSolid* cuOuterSolid = new G4IntersectionSolid(name + "_cu_outer_solid", // name
242 cuOuterCylSolid, // solid 1
243 cuOuterRectSolid); // solid 2
244 copperSkinSolid = new G4SubtractionSolid(name + "_copper_skin_solid",// name
245 cuOuterSolid, // this
246 cuInnerSolid); // minus this
247 allSolids.insert(cuInnerCylSolid);
248 allSolids.insert(cuInnerRectSolid);
249 allSolids.insert(cuInnerSolid);
250 allSolids.insert(cuOuterCylSolid);
251 allSolids.insert(cuOuterRectSolid);
252 allSolids.insert(cuOuterSolid);
253 allSolids.insert(copperSkinSolid);
254
255 //beampipe cylindrical solid (circular cross-section)
256 //beampipe inner edge for subtraction (actually just like vacuum + lengthSafety)
257 //using large margin of 1um here to avoid misplacement errors with compound booleans in geant4 (empirical solution)
258 G4VSolid* screenInnerCylSolid = new G4Tubs(name + "_screen_inner_cylinder", // name
259 0, // inner radius
260 bsInnerRadius, // outer radius
261 1.5*length, // length big for unambiguous subtraction (but < outerlength)
262 0, // rotation start angle
263 CLHEP::twopi); // rotation finish angle
264 //screen inner edge box solid (rectangular cross-section)
265 //using large margin of 1um here to avoid misplacement errors with compound booleans in geant4 (empirical solution)
266 G4VSolid* screenInnerRectSolid = new G4Box(name + "_screen_inner_box", // name
267 bsInnerBoxX, // x half width
268 bsInnerBoxY, // y half width
269 1.7*length); // z long for unambiguous intersection
270 //screen inner intersection - 1.5*length long which is > half length for unambiguous subtraction later
271 G4VSolid* screenInnerSolid = new G4IntersectionSolid(name + "_screen_inner_solid", // name
272 screenInnerCylSolid, // solid 1
273 screenInnerRectSolid); // solid 2
274
275 //screen outer edge for subtraction (actually just like vacuum + lengthSafety)x
276 G4VSolid* screenOuterCylSolid = new G4Tubs(name + "_screen_outer_cylinder",// name
277 0, // inner radius (0 for unambiguous subtraction)
278 bsOuterRadius, // outer radius
279 halfLength, // half length
280 0, // rotation start angle
281 CLHEP::twopi); // rotation finish angle
282 //screen outer edge box solid (rectangular cross-section)
283 G4VSolid* screenOuterRectSolid = new G4Box(name + "_screen_outer_box", // name
284 bsOuterBoxX, // x half width
285 bsOuterBoxY, // y half width
286 length); // z full width (long for unambiguous intersection)
287 G4VSolid* screenOuterSolid = new G4IntersectionSolid(name + "_screen__outersolid", // name
288 screenOuterCylSolid, // solid 1
289 screenOuterRectSolid); // solid 2
290 screenSolid = new G4SubtractionSolid(name + "_screen_solid",// name
291 screenOuterSolid, // this
292 screenInnerSolid); // minus this
293 allSolids.insert(screenInnerCylSolid);
294 allSolids.insert(screenInnerRectSolid);
295 allSolids.insert(screenInnerSolid);
296 allSolids.insert(screenOuterCylSolid);
297 allSolids.insert(screenOuterRectSolid);
298 allSolids.insert(screenOuterSolid);
299 allSolids.insert(screenSolid);
300
302 {
303 coolingPipeSolid = new G4Tubs(name + "_cooling_pipe_solid", // name
304 coolingPipeRadius, // inner radius
305 coolingPipeRadius + coolingPipeThickness, // outer radius
306 halfLength, // half length
307 0, // rotation start angle
308 CLHEP::twopi); // rotation finish angle
309
310 allSolids.insert(coolingPipeSolid);
311 }
312
313 // beampipe - ("coldbore") circular cross-section and sits outisde screen and cooling pipe
314 beamPipeSolid = new G4Tubs(name + "_beampipe_solid", // name
315 cbInnerRadius, // inner radius
316 cbOuterRadius, // outer radius
317 halfLength, // half length
318 0, // rotation start angle
319 CLHEP::twopi); // rotation finish angle
320
321 //container cylindrical solid (circular cross-section)
322 // 'length' is correct full length of object
323 containerSolid = new G4Tubs(name + "_container_cylinder", // name
324 0, // inner radius
325 containerRadius, // outer radius
326 length*0.5, // half length
327 0, // rotation start angle
328 CLHEP::twopi); // rotation finish angle
329
330 //container cylindrical solid (circular cross-section)
331 containerSubtractionSolid = new G4Tubs(name + "_subtraction_cylinder", // name
332 0, // inner radius
333 containerRadius + lengthSafety, // outer radius
334 2*length, // long length for unambiguous subtraction
335 0, // rotation start angle
336 CLHEP::twopi); // rotation finish angle
337
338 return CommonFinalConstruction(name, vacuumMaterial, beamPipeMaterial, length, containerRadius);
339}
340
342 G4double length,
343 const G4ThreeVector& inputFaceNormalIn,
344 const G4ThreeVector& outputFaceNormalIn,
345 G4double aper1,
346 G4double aper2,
347 G4double aper3,
348 G4double /*aper4*/,
349 G4Material* vacuumMaterial,
350 G4double beamPipeThickness,
351 G4Material* beamPipeMaterial,
352 const G4String& /*pointsFileIn*/,
353 const G4String& /*pointsUnitIn*/)
354{
355 // clean up after last usage
356 CleanUp();
357
358 // calculate geometrical parameters
359 CalculateGeometricalParameters(aper1, aper2, aper3, beamPipeThickness, length);
360
361 inputFaceNormal = inputFaceNormalIn;
362 outputFaceNormal = outputFaceNormalIn;
363
364 G4double contRadius = CreateGeneralAngledSolids(name, length, inputFaceNormal,
366
367 return CommonFinalConstruction(name, vacuumMaterial, beamPipeMaterial,
368 length, contRadius);
369}
370
372 G4Material* vacuumMaterial,
373 G4Material* beamPipeMaterial,
374 G4double length,
375 G4double contRadius)
376{
378 beamPipeMaterial, length);
379
380 // record extents
381 BDSExtent ext = BDSExtent(contRadius, contRadius, length*0.5);
382
383 // build the BDSBeamPipe instance and return it
384 BDSBeamPipe* aPipe = BuildBeamPipeAndRegisterVolumes(ext,contRadius);
385
386 // register sensitive volumes
388 {
389 aPipe->RegisterSensitiveVolume(screenLV, BDSSDType::energydep);
390 aPipe->RegisterSensitiveVolume(copperSkinLV, BDSSDType::energydep);
392 {aPipe->RegisterSensitiveVolume(coolingPipeLV, BDSSDType::energydep);}
393 }
394
395 return aPipe;
396}
397
399 G4Material* vacuumMaterialIn,
400 G4Material* beamPipeMaterialIn)
401{
402 BDSBeamPipeFactoryBase::BuildLogicalVolumes(name,vacuumMaterialIn,beamPipeMaterialIn);
403
404 // get materials
405 G4Material* copper2k = BDSMaterials::Instance()->GetMaterial("cu_2k");
406
407 copperSkinLV = new G4LogicalVolume(copperSkinSolid,
408 copper2k,
409 name + "_copper_lv");
410
411 screenLV = new G4LogicalVolume(screenSolid,
412 beamPipeMaterialIn,
413 name + "_screen_lv");
414
416 {
417 coolingPipeLV = new G4LogicalVolume(coolingPipeSolid,
418 beamPipeMaterialIn,
419 name + "_cooling_pipe_lv");
420 allLogicalVolumes.insert(coolingPipeLV);
421 }
422 allLogicalVolumes.insert(copperSkinLV);
423 allLogicalVolumes.insert(screenLV);
424}
425
426void BDSBeamPipeFactoryLHCDetailed::SetVisAttributes(G4Material* beamPipeMaterialIn,
427 G4Material* vacuumMateiralIn)
428{
429 BDSBeamPipeFactoryBase::SetVisAttributes(beamPipeMaterialIn, vacuumMateiralIn);
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}
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.
static BDSColours * Instance()
singleton pattern
Definition BDSColours.cc:32
Holder for +- extents in 3 dimensions.
Definition BDSExtent.hh:38
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.
G4Material * GetMaterial(G4String material) const
Get material by name.