19#include "BDSTunnelBuilder.hh"
21#include "BDSBeamline.hh"
22#include "BDSBeamlineElement.hh"
24#include "BDSException.hh"
25#include "BDSGlobalConstants.hh"
26#include "BDSTiltOffset.hh"
27#include "BDSTunnelFactory.hh"
28#include "BDSTunnelInfo.hh"
29#include "BDSTunnelSection.hh"
30#include "BDSUtilities.hh"
34#include "CLHEP/Units/SystemOfUnits.h"
38BDSTunnelBuilder::BDSTunnelBuilder(G4double tunnelMaxSegmentLengthIn):
39 displacementTolerance(50*CLHEP::cm),
41 maxLength(tunnelMaxSegmentLengthIn),
42 maxAngle(100*CLHEP::mrad),
43 minLength(10*CLHEP::m)
45 if (maxLength < 1*CLHEP::m)
46 {
throw BDSException(__METHOD_NAME__,
"\"tunnelMaxSegmentLength\" must be >= 1m");}
47 if (maxLength <= minLength)
48 {minLength = 0.5*maxLength;}
51BDSTunnelBuilder::~BDSTunnelBuilder()
61 const G4double& halfWidth)
const
63 G4double sectionLength = 0;
64 G4double cumulativeAngle = 0;
66 G4double cumulativeX = 0;
68 sectionLength = ((*proposedEnd)->GetReferencePositionEnd() - (*proposedStart)->GetReferencePositionStart()).mag();
70 for (; it != proposedEnd; ++it)
72 cumulativeAngle += (*it)->GetAngle();
73 cumulativeX += std::cos((*it)->GetTilt()) * std::sin((*it)->GetAngle());
77 G4bool result =
false;
79 G4bool lengthTest =
false;
83 G4bool angleTest =
false;
84 if (std::abs(cumulativeAngle) >
maxAngle)
87 G4bool nItemsTest =
false;
91 G4bool dispXTest =
false;
95 result = lengthTest || angleTest || nItemsTest || dispXTest;
98 G4bool lengthTestFail = sectionLength <
minLength;
101 if (lengthTestFail && result && angleIsFinite)
109 G4double s = 1.5*halfWidth * std::abs(cumulativeAngle);
110 G4bool willOverlapFaces = sectionLength < 1.2*s;
111 if (willOverlapFaces)
115 G4cout << __METHOD_NAME__ <<
"testing cumulative parameters" << G4endl;
116 G4cout <<
"Cumulative Length (mm): " << sectionLength <<
" > " <<
maxLength <<
" test-> " << BDS::BoolToString(lengthTest) << G4endl;
117 G4cout <<
"Cumulative Angle (rad): " << cumulativeAngle <<
" > " <<
maxAngle <<
" test-> " << BDS::BoolToString(angleTest) << G4endl;
118 G4cout <<
"# of items: " << nItems <<
" > " <<
maxItems <<
" test-> " << BDS::BoolToString(nItemsTest) << G4endl;
120 <<
" test-> " << BDS::BoolToString(dispXTest) << G4endl;
121 G4cout <<
"Length: " << sectionLength <<
" < " <<
minLength <<
" test-> " << BDS::BoolToString(lengthTestFail) << G4endl;
122 G4cout <<
"Overlap Faces: " << s <<
" < " << sectionLength <<
" test-> " << BDS::BoolToString(willOverlapFaces) << G4endl;
123 G4cout <<
"Result: " << BDS::BoolToString(result) << G4endl;
137 G4int nTunnelSections = 0;
160 defaultModel->thickness,
161 defaultModel->soilThickness,
162 defaultModel->material,
163 defaultModel->soilMaterial,
164 defaultModel->buildFloor,
165 defaultModel->floorOffset,
178 for (; it != flatBeamline->
end(); ++it)
181 G4cout << __METHOD_NAME__ <<
"iterator at: " << (*it)->GetPlacementName() << G4endl;
182 G4cout << __METHOD_NAME__ <<
"start iterator at: " << (*startElement)->GetPlacementName() << G4endl;
183 G4cout << __METHOD_NAME__ <<
"end iterator at: " << (*endElement)->GetPlacementName() << G4endl;
185 G4bool breakIt =
BreakTunnel(startElement, endElement, halfWidth);
187 G4bool isEnd = (it == (flatBeamline->
end() - 1));
194 G4cout <<
"End of beam line - forcing break in tunnel" << G4endl;
195 G4cout <<
"End element for tunnel set to: " << (*endElement)->GetPlacementName() << G4endl;
196 G4cout <<
"Start element is: " << (*startElement)->GetPlacementName() << G4endl;
202 if (breakIt || isEnd)
205 std::string name =
"tunnel_" + std::to_string(nTunnelSections);
208 G4ThreeVector startPoint = (*startElement)->GetReferencePositionStart();
209 G4ThreeVector startOffsetLocal = G4ThreeVector(offsetX, offsetY, 0);
211 G4RotationMatrix* startRot =
new G4RotationMatrix(*(*startElement)->GetReferenceRotationStart());
212 G4ThreeVector startOffsetGlobal = startOffsetLocal.transform(*startRot);
213 startPoint += startOffsetGlobal;
219 G4ThreeVector endPoint = (*endElement)->GetReferencePositionEnd();
220 G4ThreeVector endOffsetLocal = G4ThreeVector(offsetX, offsetY, 0);
221 G4RotationMatrix* endRot =
new G4RotationMatrix(*(*endElement)->GetReferenceRotationEnd());
222 G4ThreeVector endOffsetGlobal = endOffsetLocal.transform(*endRot);
223 endPoint += endOffsetGlobal;
225 G4double sStart = (*startElement)->GetSPositionStart();
226 G4double sEnd = (*endElement)->GetSPositionEnd();
227 G4double sMid = 0.5*(sStart + sEnd);
231 G4ThreeVector midPoint = 0.5*(startPoint + endPoint);
238 G4ThreeVector delta = midPoint - startPoint;
239 G4ThreeVector newUnitZ = delta.unit();
241 G4ThreeVector unitXPrevious = G4ThreeVector(1,0,0).transform(*startRot);
242 G4ThreeVector newUnitY = newUnitZ.cross(unitXPrevious).unit();
244 G4ThreeVector unitYPrevious = G4ThreeVector(0,1,0).transform(*startRot);
245 G4ThreeVector newUnitX = unitYPrevious.cross(newUnitZ).unit();
248 G4RotationMatrix* rotationMiddle =
new G4RotationMatrix(newUnitX, newUnitY, newUnitZ);
251 G4double segmentLength = (endPoint - startPoint).mag() - 1*CLHEP::um;
255 G4ThreeVector unitZStart = G4ThreeVector(0,0,1).transform(*startRot);
256 G4ThreeVector unitZEnd = G4ThreeVector(0,0,1).transform(*endRot);
258 G4ThreeVector unitZDiff = unitZEnd - unitZStart;
259 G4bool isAngled = unitZDiff.mag() > 1e-30;
262 G4cout << __METHOD_NAME__ <<
"determined tunnel segment to have the following parameters:" << G4endl;
263 G4cout <<
"Start element name: " << (*startElement)->GetPlacementName() << G4endl;
264 G4cout <<
"End element name: " << (*endElement)->GetPlacementName() << G4endl;
265 G4cout <<
"Start point (global): " << startPoint << G4endl;
266 G4cout <<
"End point (global): " << endPoint << G4endl;
267 G4cout <<
"Input and output unit Z: " << unitZStart <<
" " << unitZEnd << G4endl;
268 G4cout <<
"Has a finite angle: " << isAngled << G4endl;
269 G4cout <<
"Section length: " << segmentLength << G4endl;
270 G4cout <<
"Rotation start: " << *startRot << G4endl;
271 G4cout <<
"Rotation middle: " << *rotationMiddle << G4endl;
272 G4cout <<
"Rotation end: " << *endRot << G4endl;
288 G4RotationMatrix* middleInverse =
new G4RotationMatrix(*rotationMiddle);
289 middleInverse->invert();
290 G4RotationMatrix* inputFaceRotation =
new G4RotationMatrix((*startRot) * (*middleInverse));
291 G4ThreeVector inputFace = G4ThreeVector(0,0,-1).transform(*inputFaceRotation);
292 G4RotationMatrix* outputFaceRotation =
new G4RotationMatrix((*endRot) * (*middleInverse));
293 G4ThreeVector outputFace = G4ThreeVector(0,0,1).transform(*outputFaceRotation);
299 G4cout <<
"tunnel segment input face normal determined to be: " << inputFace << G4endl;
300 G4cout <<
"tunnel segment output face normal determined to be: " << outputFace << G4endl;
308 defaultModel->thickness,
309 defaultModel->soilThickness,
310 defaultModel->material,
311 defaultModel->soilMaterial,
312 defaultModel->buildFloor,
313 defaultModel->floorOffset,
317 delete middleInverse;
324 defaultModel->thickness,
325 defaultModel->soilThickness,
326 defaultModel->material,
327 defaultModel->soilMaterial,
328 defaultModel->buildFloor,
329 defaultModel->floorOffset,
338 G4RotationMatrix* startRot2 =
new G4RotationMatrix(*startRot);
339 G4RotationMatrix* midRot2 =
new G4RotationMatrix(*rotationMiddle);
340 G4RotationMatrix* endRot2 =
new G4RotationMatrix(*endRot);
360 nTunnelSections += 1;
365 G4cout << __METHOD_NAME__ <<
"previous tunnel start element: " << (*startElement)->GetPlacementName() << G4endl;
366 G4cout << __METHOD_NAME__ <<
"previous tunnel end element: " << (*endElement)->GetPlacementName() << G4endl;
367 previousEndElement = endElement;
369 startElement = endElement;
371 endElement = startElement;
373 G4cout << __METHOD_NAME__ <<
"new start element: " << (*startElement)->GetPlacementName() << G4endl;
374 G4cout << __METHOD_NAME__ <<
"new tunnel start element: " << (*startElement)->GetPlacementName() << G4endl;
375 G4cout << __METHOD_NAME__ <<
"new tunnel previous end element: " << (*previousEndElement)->GetPlacementName() << G4endl;
383 G4cout << __METHOD_NAME__ <<
"moving to next item in beamline" << G4endl;
A class that holds a fully constructed BDSAcceleratorComponent as well as any information relevant to...
G4ThreeVector GetReferencePositionEnd() const
Accessor.
A vector of BDSBeamlineElement instances - a beamline.
BDSBeamlineElement * back() const
Return a reference to the last element.
void AddBeamlineElement(BDSBeamlineElement *element)
iterator begin()
Iterator mechanics.
void AddComponent(BDSAcceleratorComponent *component, BDSTiltOffset *tiltOffset=nullptr, BDSSamplerInfo *samplerInfo=nullptr)
iterator end()
Iterator mechanics.
BeamlineVector::const_iterator const_iterator
Iterator mechanics.
General exception with possible name of object and message.
G4double MaximumAbsTransverse() const
Return the maximum absolute value considering only x,y.
static BDSGlobalConstants * Instance()
Access method.
A holder for any placement offsets and rotations for a BDSAcceleratorComponent.
BDSBeamline * BuildTunnelSections(const BDSBeamline *flatBeamLine) const
G4double maxAngle
Maximum angle before split.
G4double maxItems
Maximum number of items before split.
G4bool BreakTunnel(BDSBeamline::const_iterator proposedStart, BDSBeamline::const_iterator proposedEnd, const G4double &halfWidth) const
G4double minLength
Minimum length to angle ratio to allow a split.
G4double maxLength
Maximum length before split.
G4double displacementTolerance
A singleton class that provides an interface to all tunnel factories.
BDSTunnelSection * CreateTunnelSectionAngled(BDSTunnelType tunnelType, G4String name, G4double length, G4ThreeVector inputFaceIn, G4ThreeVector outputFaceIn, G4double tunnelThickness, G4double tunnelSoilThickness, G4Material *tunnelMaterial, G4Material *tunnelSoilMaterial, G4bool tunnelFloor, G4double tunnelFloorOffset, G4double tunnel1, G4double tunnel2, G4bool visible=true)
BDSTunnelSection * CreateTunnelSection(BDSTunnelType tunnelType, G4String name, G4double length, G4double tunnelThickness, G4double tunnelSoilThickness, G4Material *tunnelMaterial, G4Material *tunnelSoilMaterial, G4bool tunnelFloor, G4double tunnelFloorOffset, G4double tunnel1, G4double tunnel2, G4bool visible=true)
Create a tunnel section with straight input and output face.
static BDSTunnelFactory * Instance()
singleton pattern
Holder struct of all information required to create a section of tunnel.
G4bool visible
Is the tunnel visible?
G4double aper2
Tunnel aperture / shape parameter 2.
G4double aper1
Tunnel aperture / shape parameter 1.
Class that represents a section of tunnel.
void PrintRotationMatrix(G4RotationMatrix *rm, G4String keyName="unknown")
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())