18#include "BDSAcceleratorModel.hh"
19#include "BDSColours.hh"
20#include "BDSCrystal.hh"
21#include "BDSCrystalFactory.hh"
22#include "BDSCrystalInfo.hh"
24#include "BDSException.hh"
25#include "BDSGlobalConstants.hh"
26#include "BDSMaterials.hh"
27#include "BDSUtilities.hh"
30#include "G4DisplacedSolid.hh"
31#include "G4ExtrudedSolid.hh"
32#include "G4LogicalVolume.hh"
33#include "G4Material.hh"
34#include "G4RotationMatrix.hh"
36#include "G4ThreeVector.hh"
39#include "G4TwoVector.hh"
41#include "G4UserLimits.hh"
42#include "G4VisAttributes.hh"
43#include "G4Version.hh"
45#include "CLHEP/Units/SystemOfUnits.h"
54#if G4VERSION_NUMBER > 1039
55#include "G4ExtendedMaterial.hh"
56#include "G4CrystalExtension.hh"
57#include "G4CrystalUnitCell.hh"
58#include "G4ChannelingMaterialData.hh"
59#include "G4LogicalCrystalVolume.hh"
62BDSCrystalFactory::BDSCrystalFactory():
72 crystalSolid =
nullptr;
74 placementOffset = G4ThreeVector();
75 placementRotation =
nullptr;
86 case BDSCrystalType::box:
88 case BDSCrystalType::cylinder:
90 case BDSCrystalType::torus:
101 allSolids.insert(crystalSolid);
104#if G4VERSION_NUMBER > 1039
105 G4ExtendedMaterial* crystalMat =
new G4ExtendedMaterial(nameIn+
"_crystal.material", recipe->
material);
107 crystalMat->RegisterExtension(std::unique_ptr<G4CrystalExtension>(
new G4CrystalExtension(crystalMat)));
108 G4CrystalExtension* crystalExtension =
dynamic_cast<G4CrystalExtension*
>(crystalMat->RetrieveExtension(
"crystal"));
110 G4CrystalUnitCell* uCell =
new G4CrystalUnitCell(recipe->sizeA,
117 crystalExtension->SetUnitCell(uCell);
119 crystalMat->RegisterExtension(std::unique_ptr<G4ChannelingMaterialData>(
new G4ChannelingMaterialData(
"channeling")));
121 G4ChannelingMaterialData* crystalChannelingData = (G4ChannelingMaterialData*)crystalMat->RetrieveExtension(
"channeling");
124 {
throw BDSException(__METHOD_NAME__,
"No such crystal data files beginning with: \"" + fileName +
"\"");}
126 G4cout << __METHOD_NAME__ <<
"Raw data path: " << recipe->
data << G4endl;
127 G4cout << __METHOD_NAME__ <<
"Using crystal data: " << fileName << G4endl;
129 crystalChannelingData->SetFilename(fileName);
134 G4double bendingRadius = -recipe->BendingRadiusHorizontal();
135 crystalChannelingData->SetBR(bendingRadius);
137 crystalLV =
new G4LogicalCrystalVolume(crystalSolid,
139 nameIn +
"_crystal_lv",
140 nullptr,
nullptr,
nullptr,
141 true, 0, 0, 0, recipe->miscutAngleY);
143 BDSAcceleratorModel::Instance()->
VolumeSet(
"crystals")->insert(crystalLV);
146 crystalLV =
new G4LogicalVolume(crystalSolid,
148 nameIn +
"_crystal_lv");
150 allLogicalVolumes.insert(crystalLV);
158 G4VisAttributes* crysVisAttr =
new G4VisAttributes(*
BDSColours::Instance()->GetColour(
"crystal"));
159 crysVisAttr->SetVisibility(
true);
160 crysVisAttr->SetForceLineSegmentsPerCircle(200);
161 allVisAttributes.insert(crysVisAttr);
162 crystalLV->SetVisAttributes(crysVisAttr);
172 {allUserLimits.insert(ul);}
173 crystalLV->SetUserLimits(ul);
181 extent, placementOffset, placementRotation);
196 crystalSolid =
new G4Box(nameIn +
"_solid",
203 placementOffset = G4ThreeVector(0, 0, 0);
212 G4double& startAngle,
213 G4double& sweepAngle)
const
215 if (bendingAngle >= 0)
217 startAngle = CLHEP::twopi - 0.5 * bendingAngle;
218 sweepAngle = bendingAngle;
222 startAngle = CLHEP::pi - 0.5*std::abs(bendingAngle);
223 sweepAngle = std::abs(bendingAngle);
228 G4double xBendingRadius,
233 G4double xHi = xBendingRadius - (xBendingRadius - xThickness*0.5)*std::cos(std::abs(xBendingAngle)*0.5);
234 G4double xLow = -(xThickness * 0.5);
235 if (xBendingAngle > 0)
237 std::swap(xHi, xLow);
241 G4double dz = (xBendingRadius + xThickness*0.5) * std::sin(std::abs(xBendingAngle)*0.5);
260 G4double xBR = std::abs(recipe->BendingRadiusHorizontal());
261 G4double thickness = recipe->
lengthX;
268 G4Tubs* rawShape =
new G4Tubs(nameIn +
"_solid",
280 G4RotationMatrix* relativeRotation =
new G4RotationMatrix();
281 relativeRotation->rotateX(-CLHEP::halfpi);
282 G4double bendingRadiusH = recipe->BendingRadiusHorizontal();
283 G4ThreeVector offset(-bendingRadiusH,0,0);
284 crystalSolid =
new G4DisplacedSolid(nameIn +
"_shifted_solid",
290 placementOffset = G4ThreeVector();
299 G4double xBR = std::abs(recipe->BendingRadiusHorizontal());
301 G4double zBR = std::abs(recipe->BendingRadiusVertical());
307 G4double thickness = recipe->
lengthX;
314 G4double angFraction = sweepAngle / (G4double)
nPoints;
315 std::vector<G4TwoVector> points;
317 G4double innerRadius = xBR - thickness*0.5;
318 for (G4int i = 0; i <
nPoints; i++)
320 G4double ang = startAngle + (G4double)i * angFraction;
321 G4double x = innerRadius * std::cos(ang);
322 G4double y = innerRadius * std::sin(ang);
323 points.emplace_back(G4TwoVector(x,y));
325 G4double outerRadius = xBR + thickness*0.5;
326 for (G4int i =
nPoints; i > 0; i--)
328 G4double ang = startAngle + (G4double)i * angFraction;
329 G4double x = outerRadius * std::cos(ang);
330 G4double y = outerRadius * std::sin(ang);
331 points.emplace_back(G4TwoVector(x,y));
334 G4double zStartAngle = CLHEP::twopi - 0.5 * zBA;
335 G4double zSweepAngle = zBA;
340 G4double zAngFraction = zSweepAngle / (G4double)
nPoints;
341 std::vector<G4ExtrudedSolid::ZSection> zSections;
342 for (G4int i = 0; i <
nPoints; i++)
344 G4double zAng = zStartAngle + (G4double)i * zAngFraction;
345 G4double z = zBR * std::sin(zAng);
346 G4double x = zBR - (zBR * std::cos(zAng));
352 xmin = std::min(xmin, x);
353 xmax = std::max(xmax, x);
354 zSections.emplace_back(G4ExtrudedSolid::ZSection(z, G4TwoVector(x, 0), 1));
357 G4ExtrudedSolid* rawShape =
new G4ExtrudedSolid(nameIn +
"_solid",
366 G4RotationMatrix* relativeRotation =
new G4RotationMatrix();
367 relativeRotation->rotateX(-CLHEP::halfpi);
368 G4ThreeVector offset(0,0,0);
369 crystalSolid =
new G4DisplacedSolid(nameIn +
"_shifted_solid",
377 placementOffset = G4ThreeVector(-1*recipe->BendingRadiusHorizontal(), 0, 0);
380 G4double xLow = ext.
XNeg() + xmin;
381 G4double xHi = ext.
XPos() + xmax;
std::set< G4LogicalVolume * > * VolumeSet(const G4String &name)
Returns pointer to a set of logical volumes. If no set by that name exits, create it.
static BDSColours * Instance()
singleton pattern
void CommonConstruction(const G4String &nameIn, const BDSCrystalInfo *recipe)
Common construction tasks.
const G4int nPoints
Number of points to split torus into.
void CalculateSolidAngles(G4double bendingAngle, G4double &startAngle, G4double &sweepAngle) const
const G4double maxStepFactor
Fraction of length for maximum step in user limits.
BDSCrystal * CreateCrystalBox(const G4String &nameIn, const BDSCrystalInfo *recipe)
Create box geometry for a crystal.
BDSCrystal * CreateCrystalCylinder(const G4String &nameIn, const BDSCrystalInfo *recipe)
Create cylinder geometry for a crystal.
BDSExtent CalculateExtents(G4double bendingAngle, G4double xBendingRadius, G4double xThickness, const BDSCrystalInfo *recipe) const
Produce an extent for a curved crystal.
BDSCrystal * CreateCrystalTorus(const G4String &nameIn, const BDSCrystalInfo *recipe)
Create torus geometry for a cyrstal.
BDSCrystal * CreateCrystal(const G4String &nameIn, const BDSCrystalInfo *recipe)
Main interface to create a crystal.
BDSCrystal * BuildCrystalObject(const BDSCrystalInfo *recipe, const BDSExtent &extent)
build beampipe and register logical volumes
void SetUserLimits(G4double length)
Set user limits.
void SetVisAttributes()
Set visual attributes.
Holder for all information required to create a crystal.
G4String data
Potential data path.
G4double lengthZ
Z dimension.
G4Material * material
Material.
G4double bendingAngleZAxis
Bending angle about Z axis.
G4double lengthX
X dimension.
BDSCrystalType shape
Shape of geometry.
G4double bendingAngleYAxis
Bending angle about Y axis.
G4double lengthY
Y dimension.
An object for both a crystal from a factory.
General exception with possible name of object and message.
Holder for +- extents in 3 dimensions.
G4double XPos() const
Accessor.
G4double ZPos() const
Accessor.
G4double XNeg() const
Accessor.
G4double YNeg() const
Accessor.
G4double YPos() const
Accessor.
G4double ZNeg() const
Accessor.
virtual void FactoryBaseCleanUp()
Empty containers for next use - factories are never deleted so can't rely on scope.
void RegisterUserLimits(G4UserLimits *userLimit)
virtual void ExcludeLogicalVolumeFromBiasing(G4LogicalVolume *lv)
void RegisterVisAttributes(G4VisAttributes *visAttribute)
void RegisterSolid(G4VSolid *solid)
void RegisterSensitiveVolume(G4LogicalVolume *sensitiveVolume, BDSSDType sensitivityType)
static BDSGlobalConstants * Instance()
Access method.
type underlying() const
return underlying value (can be used in switch statement)
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)
G4UserLimits * CreateUserLimits(G4UserLimits *defaultUL, G4double length, G4double fraction=1.6)
G4bool FileExists(const G4String &filename)
Checks if filename exists.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())