19#include "BDSAcceleratorModel.hh"
20#include "BDSColours.hh"
21#include "BDSCrystal.hh"
22#include "BDSCrystalFactory.hh"
23#include "BDSCrystalInfo.hh"
25#include "BDSException.hh"
26#include "BDSGlobalConstants.hh"
27#include "BDSMaterials.hh"
28#include "BDSUtilities.hh"
31#include "G4DisplacedSolid.hh"
32#include "G4ExtrudedSolid.hh"
33#include "G4LogicalVolume.hh"
34#include "G4Material.hh"
35#include "G4RotationMatrix.hh"
37#include "G4ThreeVector.hh"
40#include "G4TwoVector.hh"
42#include "G4UserLimits.hh"
43#include "G4VisAttributes.hh"
44#include "G4Version.hh"
46#include "CLHEP/Units/SystemOfUnits.h"
55#if G4VERSION_NUMBER > 1039
56#include "G4ExtendedMaterial.hh"
57#include "G4CrystalExtension.hh"
58#include "G4CrystalUnitCell.hh"
59#include "G4ChannelingMaterialData.hh"
60#include "G4LogicalCrystalVolume.hh"
63BDSCrystalFactory::BDSCrystalFactory():
73 crystalSolid =
nullptr;
75 placementOffset = G4ThreeVector();
76 placementRotation =
nullptr;
87 case BDSCrystalType::box:
89 case BDSCrystalType::cylinder:
91 case BDSCrystalType::torus:
102 allSolids.insert(crystalSolid);
105#if G4VERSION_NUMBER > 1039
106 G4ExtendedMaterial* crystalMat =
new G4ExtendedMaterial(
"crystal.material", recipe->
material);
108 crystalMat->RegisterExtension(std::unique_ptr<G4CrystalExtension>(
new G4CrystalExtension(crystalMat)));
109 G4CrystalExtension* crystalExtension =
dynamic_cast<G4CrystalExtension*
>(crystalMat->RetrieveExtension(
"crystal"));
111 G4CrystalUnitCell* uCell =
new G4CrystalUnitCell(recipe->sizeA,
118 crystalExtension->SetUnitCell(uCell);
120 crystalMat->RegisterExtension(std::unique_ptr<G4ChannelingMaterialData>(
new G4ChannelingMaterialData(
"channeling")));
122 G4ChannelingMaterialData* crystalChannelingData = (G4ChannelingMaterialData*)crystalMat->RetrieveExtension(
"channeling");
125 {
throw BDSException(__METHOD_NAME__,
"No such crystal data files beginning with: \"" + fileName +
"\"");}
127 G4cout << __METHOD_NAME__ <<
"Raw data path: " << recipe->
data << G4endl;
128 G4cout << __METHOD_NAME__ <<
"Using crystal data: " << fileName << G4endl;
130 crystalChannelingData->SetFilename(fileName);
135 G4double bendingRadius = -recipe->BendingRadiusHorizontal();
136 crystalChannelingData->SetBR(bendingRadius);
138 crystalLV =
new G4LogicalCrystalVolume(crystalSolid,
140 nameIn +
"_crystal_lv",
141 nullptr,
nullptr,
nullptr,
142 true, 0, 0, 0, recipe->miscutAngleY);
144 BDSAcceleratorModel::Instance()->
VolumeSet(
"crystals")->insert(crystalLV);
147 crystalLV =
new G4LogicalVolume(crystalSolid,
149 nameIn +
"_crystal_lv");
151 allLogicalVolumes.insert(crystalLV);
159 G4VisAttributes* crysVisAttr =
new G4VisAttributes(*
BDSColours::Instance()->GetColour(
"crystal"));
160 crysVisAttr->SetVisibility(
true);
161 crysVisAttr->SetForceLineSegmentsPerCircle(200);
162 allVisAttributes.insert(crysVisAttr);
163 crystalLV->SetVisAttributes(crysVisAttr);
173 {allUserLimits.insert(ul);}
174 crystalLV->SetUserLimits(ul);
182 extent, placementOffset, placementRotation);
197 crystalSolid =
new G4Box(nameIn +
"_solid",
204 placementOffset = G4ThreeVector(0, 0, 0);
213 G4double& startAngle,
214 G4double& sweepAngle)
const
216 if (bendingAngle >= 0)
218 startAngle = CLHEP::twopi - 0.5 * bendingAngle;
219 sweepAngle = bendingAngle;
223 startAngle = CLHEP::pi - 0.5*std::abs(bendingAngle);
224 sweepAngle = std::abs(bendingAngle);
229 G4double xBendingRadius,
234 G4double xHi = xBendingRadius - (xBendingRadius - xThickness*0.5)*std::cos(std::abs(xBendingAngle)*0.5);
235 G4double xLow = -(xThickness * 0.5);
236 if (xBendingAngle > 0)
238 std::swap(xHi, xLow);
242 G4double dz = (xBendingRadius + xThickness*0.5) * std::sin(std::abs(xBendingAngle)*0.5);
261 G4double xBR = std::abs(recipe->BendingRadiusHorizontal());
262 G4double thickness = recipe->
lengthX;
269 G4Tubs* rawShape =
new G4Tubs(nameIn +
"_solid",
281 G4RotationMatrix* relativeRotation =
new G4RotationMatrix();
282 relativeRotation->rotateX(-CLHEP::halfpi);
283 G4double bendingRadiusH = recipe->BendingRadiusHorizontal();
284 G4ThreeVector offset(-bendingRadiusH,0,0);
285 crystalSolid =
new G4DisplacedSolid(nameIn +
"_shifted_solid",
291 placementOffset = G4ThreeVector();
300 G4double xBR = std::abs(recipe->BendingRadiusHorizontal());
302 G4double zBR = std::abs(recipe->BendingRadiusVertical());
308 G4double thickness = recipe->
lengthX;
315 G4double angFraction = sweepAngle / (G4double)
nPoints;
316 std::vector<G4TwoVector> points;
318 G4double innerRadius = xBR - thickness*0.5;
319 for (G4int i = 0; i <
nPoints; i++)
321 G4double ang = startAngle + (G4double)i * angFraction;
322 G4double x = innerRadius * std::cos(ang);
323 G4double y = innerRadius * std::sin(ang);
324 points.emplace_back(G4TwoVector(x,y));
326 G4double outerRadius = xBR + thickness*0.5;
327 for (G4int i =
nPoints; i > 0; i--)
329 G4double ang = startAngle + (G4double)i * angFraction;
330 G4double x = outerRadius * std::cos(ang);
331 G4double y = outerRadius * std::sin(ang);
332 points.emplace_back(G4TwoVector(x,y));
335 G4double zStartAngle = CLHEP::twopi - 0.5 * zBA;
336 G4double zSweepAngle = zBA;
341 G4double zAngFraction = zSweepAngle / (G4double)
nPoints;
342 std::vector<G4ExtrudedSolid::ZSection> zSections;
343 for (G4int i = 0; i <
nPoints; i++)
345 G4double zAng = zStartAngle + (G4double)i * zAngFraction;
346 G4double z = zBR * std::sin(zAng);
347 G4double x = zBR - (zBR * std::cos(zAng));
353 xmin = std::min(xmin, x);
354 xmax = std::max(xmax, x);
355 zSections.emplace_back(G4ExtrudedSolid::ZSection(z, G4TwoVector(x, 0), 1));
358 G4ExtrudedSolid* rawShape =
new G4ExtrudedSolid(nameIn +
"_solid",
367 G4RotationMatrix* relativeRotation =
new G4RotationMatrix();
368 relativeRotation->rotateX(-CLHEP::halfpi);
369 G4ThreeVector offset(0,0,0);
370 crystalSolid =
new G4DisplacedSolid(nameIn +
"_shifted_solid",
378 placementOffset = G4ThreeVector(-1*recipe->BendingRadiusHorizontal(), 0, 0);
381 G4double xLow = ext.
XNeg() + xmin;
382 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())