18#include "BDSAcceleratorComponent.hh"
19#include "BDSAcceleratorComponentRegistry.hh"
20#include "BDSBeamline.hh"
21#include "BDSBeamlineElement.hh"
22#include "BDSExtent.hh"
23#include "BDSCurvilinearBuilder.hh"
24#include "BDSCurvilinearFactory.hh"
25#include "BDSGlobalConstants.hh"
26#include "BDSSimpleComponent.hh"
27#include "BDSSamplerType.hh"
28#include "BDSTiltOffset.hh"
29#include "BDSTunnelInfo.hh"
30#include "BDSUtilities.hh"
31#include "BDSWarning.hh"
34#include "G4ThreeVector.hh"
35#include "G4RotationMatrix.hh"
41BDSCurvilinearBuilder::BDSCurvilinearBuilder()
46 defaultBridgeLength =
paddingLength + 4*globals->LengthSafety();
48 radiusTolerance = 0.8;
49 if (globals->BuildTunnel() || globals->BuildTunnelStraight())
51 BDSExtent tunnelExtent = globals->TunnelInfo()->IndicativeExtent();
52 tunnelExtent = tunnelExtent.
Translate(globals->TunnelOffsetX(), globals->TunnelOffsetY(), 0);
53 G4double maxTunnelR = tunnelExtent.
MaximumAbs();
56 if (globals->CurvilinearDiameterShrunkForBends())
58 G4String message =
"Strong bends necessitate smaller curvilinear geometry than the tunnel size, but\n";
59 message +=
"tunnel hits will need transform for curvilinear coordinates.";
60 BDS::Warning(message);
71BDSCurvilinearBuilder::~BDSCurvilinearBuilder()
77 const G4bool circular)
82 G4bool bonusSections = (!circular && !beamline->
empty());
93 G4String name = (*element)->GetName() +
"_cl_" + std::to_string(i);
121 G4bool isFirst = it == startIt;
122 G4bool isLast = std::next(it) == endIt;
124 G4double minimumSize = 0.1*CLHEP::mm;
125 auto pst = std::prev(it);
127 {previous =
nullptr;}
131 if (previous->
GetArcLength() < minimumSize && pst != startIt)
133 pst = std::prev(pst);
138 auto nxt = std::next(it);
146 nxt = std::next(nxt);
159 G4int numberOfUniqueComponents = 0;
160 G4int beamlineIndex = 0;
163 auto nxt = std::next(element);
171 beamline->
end(), numberOfUniqueComponents,
172 beamlineIndex, crRadius);
189 radiusFromAngleLength *= radiusTolerance;
207 G4double chordLength=0.0, angle=0.0, arcLength=0.0;
209 if (startElement == finishElement)
211 chordLength = (*startElement)->GetChordLength() +
paddingLength;
212 angle = (*startElement)->GetAngle();
213 if (
Angled(*startElement))
221 G4ThreeVector positionStart = (*startElement)->GetReferencePositionStart();
222 G4ThreeVector positionEnd = (*finishElement)->GetReferencePositionEnd();
223 chordLength = (positionEnd - positionStart).mag() +
paddingLength;
225 G4double accumulatedAngle = 0;
226 for (
auto it = startElement; it < finishElement; it++)
227 {accumulatedAngle += (*it)->GetAngle();}
229 angle = accumulatedAngle;
232 G4double meanBendingRadius = 0.5 * chordLength / std::sin(0.5*std::abs(angle));
233 arcLength = meanBendingRadius * std::abs(angle);
247 {to = (*startElement)->GetTiltOffset();}
266 G4int& numberOfUniqueComponents,
267 const G4int beamlineIndex,
272 if ((*element)->AngledOutputFace())
276 G4double width = (*element)->GetAcceleratorComponent()->GetExtent().DX();
277 width = std::min(width, crRadius);
298 G4int& numberOfUniqueComponents)
304 numberOfUniqueComponents++;
309 G4int& numberOfUniqueComponents,
310 G4double suggestedRadius)
314 G4ThreeVector iFNormal = outputFaceNormal;
316 G4ThreeVector oFNormal = outputFaceNormal;
318 G4double width = (*element)->GetAcceleratorComponent()->GetExtent().DX();
319 width = std::min(width, suggestedRadius);
330 numberOfUniqueComponents++;
338 const G4int beamlineIndex)
340 G4bool last = nextElement == end;
345 if (existingTiltOffset)
350 G4ThreeVector unitZ = G4ThreeVector(0,0,1);
351 unitZ = unitZ.transform(*refRotEnd);
354 G4ThreeVector endPosition;
356 {endPosition = (*nextElement)->GetReferencePositionStart();}
358 {endPosition = startPosition + ( (component->
GetChordLength()) * unitZ );}
359 G4ThreeVector midPosition = (startPosition + endPosition) * 0.5;
367 G4double midS = (startS + endS) * 0.5;
370 startPosition, midPosition, endPosition,
371 new G4RotationMatrix(*refRotEnd),
372 new G4RotationMatrix(*refRotEnd),
373 new G4RotationMatrix(*refRotEnd),
374 startPosition, midPosition, endPosition,
375 new G4RotationMatrix(*refRotEnd),
376 new G4RotationMatrix(*refRotEnd),
377 new G4RotationMatrix(*refRotEnd),
392 BDSTiltOffset* existingTiltOffset = (*startElement)->GetTiltOffset();
393 if (existingTiltOffset)
398 if (startElement == finishElement)
427 G4double sStart = (*startElement)->GetSPositionStart();
428 G4double sEnd = (*finishElement)->GetSPositionEnd();
429 G4double sMid = 0.5 * (sEnd + sStart);
430 G4ThreeVector posRefStart = (*startElement)->GetReferencePositionStart();
431 G4ThreeVector posRefEnd = (*finishElement)->GetReferencePositionEnd();
432 G4ThreeVector posRefMid = 0.5 * (posRefStart + posRefEnd);
433 G4RotationMatrix* rotRefStart = (*startElement)->GetReferenceRotationStart();
434 G4RotationMatrix* rotRefEnd = (*finishElement)->GetReferenceRotationEnd();
436 G4ThreeVector delta = posRefMid - posRefStart;
437 G4ThreeVector newUnitZ = delta.unit();
438 G4ThreeVector unitXPrevious = G4ThreeVector(1,0,0).transform(*rotRefStart);
439 G4ThreeVector newUnitY = newUnitZ.cross(unitXPrevious).unit();
440 G4ThreeVector unitYPrevious = G4ThreeVector(0,1,0).transform(*rotRefStart);
441 G4ThreeVector newUnitX = unitYPrevious.cross(newUnitZ).unit();
444 G4RotationMatrix rotRefMid = G4RotationMatrix(newUnitX, newUnitY, newUnitZ);
450 new G4RotationMatrix(*rotRefStart),
451 new G4RotationMatrix(rotRefMid),
452 new G4RotationMatrix(*rotRefEnd),
456 new G4RotationMatrix(*rotRefStart),
457 new G4RotationMatrix(rotRefMid),
458 new G4RotationMatrix(*rotRefEnd),
485 G4ThreeVector unitDir = G4ThreeVector(0,0,1).transform(*rotStart);
496 new G4RotationMatrix(*rotStart),
497 new G4RotationMatrix(*rotStart),
498 new G4RotationMatrix(*rotStart),
502 new G4RotationMatrix(*rotStart),
503 new G4RotationMatrix(*rotStart),
504 new G4RotationMatrix(*rotStart),
526 const G4int lastIndex = lastElement->
GetIndex();
528 G4ThreeVector unitDir = G4ThreeVector(0,0,1).transform(*rotEnd);
539 new G4RotationMatrix(*rotEnd),
540 new G4RotationMatrix(*rotEnd),
541 new G4RotationMatrix(*rotEnd),
545 new G4RotationMatrix(*rotEnd),
546 new G4RotationMatrix(*rotEnd),
547 new G4RotationMatrix(*rotEnd),
void RegisterCurvilinearComponent(BDSAcceleratorComponent *component)
static BDSAcceleratorComponentRegistry * Instance()
Singleton accessor.
Abstract class that represents a component of an accelerator.
virtual G4double GetChordLength() const
G4ThreeVector OutputFaceNormal() const
A class that holds a fully constructed BDSAcceleratorComponent as well as any information relevant to...
G4double GetSynchronousTMiddle() const
Accessor.
G4double GetAngle() const
Accessor.
G4double GetStartMomentum() const
Accessor.
G4ThreeVector GetReferencePositionEnd() const
Accessor.
G4RotationMatrix * GetReferenceRotationStart() const
Accessor.
G4RotationMatrix * GetRotationEnd() const
Accessor.
BDSTiltOffset * GetTiltOffset() const
Accessor.
G4RotationMatrix * GetReferenceRotationEnd() const
Accessor.
G4int GetIndex() const
Accessor.
G4ThreeVector GetReferencePositionMiddle() const
Accessor.
G4double GetSPositionEnd() const
Accessor.
G4RotationMatrix * GetRotationStart() const
Accessor.
G4double GetStartKineticEnergy() const
Accessor.
G4ThreeVector GetReferencePositionStart() const
Accessor.
G4RotationMatrix * GetReferenceRotationMiddle() const
Accessor.
G4double GetSPositionMiddle() const
Accessor.
G4double GetArcLength() const
Accessor.
G4RotationMatrix * GetRotationMiddle() const
Accessor.
G4double GetSPositionStart() const
Accessor.
A vector of BDSBeamlineElement instances - a beamline.
const BDSBeamlineElement * GetLastItem() const
Return a reference to the last element.
static G4double PaddingLength()
Access the padding length between each element added to the beamline.
const BDSBeamlineElement * GetFirstItem() const
Return a reference to the first element.
void AddBeamlineElement(BDSBeamlineElement *element)
G4bool empty() const
Iterator mechanics.
iterator begin()
Iterator mechanics.
iterator end()
Iterator mechanics.
BeamlineVector::const_iterator const_iterator
Iterator mechanics.
BDSBeamlineElement * CreateElementFromComponent(BDSSimpleComponent *component, BDSBeamline::const_iterator startElement, BDSBeamline::const_iterator finishElement, G4int index)
Create the BDSBeamlineElement by wrapping a BDSSimpleComponent.
BDSBeamlineElement * CreateBridgeSection(BDSAcceleratorComponent *defaultBridge, BDSBeamline::const_iterator element, BDSBeamline::const_iterator nextElement, BDSBeamline::const_iterator end, G4int &numberOfUniqueComponents, const G4int beamlineIndex, G4double crRadius)
BDSAcceleratorComponent * CreateStraightBridgeComponent(G4double width, G4int &numberOfUniqueComponents)
BDSBeamlineElement * CreateBridgeElementFromComponent(BDSAcceleratorComponent *component, BDSBeamline::const_iterator element, BDSBeamline::const_iterator nextElement, BDSBeamline::const_iterator end, const G4int beamlineIndex)
G4double curvilinearRadius
Radius for curvilinear geometry.
G4double paddingLength
Length that was used for padding on the beam line we're building with respesct to.
void PreviousAndNext(BDSBeamline::const_iterator it, BDSBeamline::const_iterator startIt, BDSBeamline::const_iterator endIt, const BDSBeamlineElement *&previous, const BDSBeamlineElement *&next) const
G4double CurvilinearRadius(const BDSBeamlineElement *el) const
BDSBeamline * BuildCurvilinearBeamLine1To1(BDSBeamline const *const beamline, const G4bool circular)
Build a beam line of curvilinear geometry based on another beam line.
BDSAcceleratorComponent * CreateAngledBridgeComponent(BDSBeamline::const_iterator element, G4int &numberOfUniqueComponents, G4double suggestedRadius)
Create a unique accelerator component for an element with angled faces.
G4bool Angled(BDSBeamlineElement const *const element) const
Simple interrogation function to determine if an element has a finite angle or not.
BDSBeamline * BuildCurvilinearBridgeBeamLine(BDSBeamline const *const beamline)
Build bridging volumes to join the curvilinear ones.
BDSCurvilinearFactory * factory
Factory to build curvilinear geometry.
BDSBeamlineElement * CreateBonusSectionStart(BDSBeamline const *const beamline)
Create a small section to extend a linear beam line.
BDSAcceleratorComponent * CreateDefaultBridgeComponent()
G4double bonusChordLength
Length of any possible bonus section added to beginning and end.
BDSBeamlineElement * CreateBonusSectionEnd(BDSBeamline const *const beamline)
Create a small section to extend a linear beam line.
BDSBeamlineElement * CreateCurvilinearElement(const G4String &elementName, BDSBeamline::const_iterator startElement, BDSBeamline::const_iterator finishElement, G4int index, G4double crRadius)
Factory to create curvilinear geometry for parallel world.
BDSSimpleComponent * CreateCurvilinearVolume(const G4String &name, G4double chordLength, G4double radius)
Build a straight curvilinear volume.
Holder for +- extents in 3 dimensions.
BDSExtent Translate(const G4ThreeVector &offset) const
Provide a new copy of this extent with an offset applied.
G4double MaximumAbs() const
Return the maximum absolute value considering all dimensions.
A class that holds global options and constants.
static BDSGlobalConstants * Instance()
Access method.
A BDSAcceleratorComponent wrapper for BDSGeometryComponent.
A holder for any placement offsets and rotations for a BDSAcceleratorComponent.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())