19#include "BDSComponentFactory.hh"
21#include "BDSException.hh"
22#include "BDSFieldInfo.hh"
23#include "BDSFieldInfoExtra.hh"
24#include "BDSFieldType.hh"
25#include "BDSIntegratorType.hh"
26#include "BDSMaterials.hh"
27#include "BDSMuonCooler.hh"
28#include "BDSMuonCoolerBuilder.hh"
29#include "BDSMuonCoolerStructs.hh"
30#include "BDSParser.hh"
32#include "parser/coolingchannel.h"
33#include "parser/element.h"
36#include "G4ThreeVector.hh"
39#include "CLHEP/Units/SystemOfUnits.h"
52 G4double horizontalWidth,
55 G4double designRigidity)
57 G4double elementRadius = horizontalWidth * 0.5;
59 G4String definitionName = definition.
name;
73 std::vector<BDS::MuonCoolerDipoleInfo> dipoleInfos = BDS::BuildMuonCoolerDipoleInfos(definition);
77 std::vector<BDS::MuonCoolerCavityInfo> cavityInfos = BDS::BuildMuonCoolerCavityInfos(definition);
81 BDS::CheckMuonCoolerCavityInfosForOverlaps(definitionName,
91 BDS::CheckMuonCoolerAbsorberInfoForOverlaps(definitionName,
100 BDSFieldInfo* outerFieldRecipe = BDS::BuildMuonCoolerFieldRecipe(definitionName,
102 definition.integrator,
103 definition.magneticFieldModel,
104 definition.electricFieldModel,
105 definition.dipoleFieldModel,
129 std::vector<BDS::MuonCoolerCoilInfo> result;
132 G4int nCoils = definition.nCoils;
133 std::vector<std::string> coilParamNames = {
"coilInnerRadius",
134 "coilRadialThickness",
138 std::vector<const std::list<double>*> coilVars = {&(definition.coilInnerRadius),
139 &(definition.coilRadialThickness),
140 &(definition.coilLengthZ),
141 &(definition.coilCurrent),
142 &(definition.coilOffsetZ)};
143 std::vector<std::vector<double> > coilVarsV;
150 std::vector<G4Material*> coilMaterials;
153 definition.coilMaterial,
158 for (G4int i = 0; i < nCoils; i++)
161 coilVarsV[1][i] * CLHEP::m,
162 coilVarsV[2][i] * CLHEP::m,
163 coilVarsV[3][i] * CLHEP::ampere,
164 coilVarsV[4][i] * CLHEP::m,
166 definition.onAxisTolerance * CLHEP::tesla,
170 result.push_back(info);
173 if (definition.mirrorCoils)
175 result.reserve(2*result.size());
176 std::copy(result.rbegin(), result.rend(), std::back_inserter(result));
177 for (G4int j = (G4int)result.size() - 1; j > nCoils - 1; j--)
178 {result[j].offsetZ *= -1;}
185 const G4String& elementName,
186 const std::vector<BDS::SquareCheck>& coilSquares,
187 G4double elementChordLength,
188 G4double elementRadius)
195 for (G4int i = 0; i < (G4int)coilSquares.size(); i++)
197 for (G4int j = i+1; j < (G4int)coilSquares.size(); j++)
201 if (coilSquares[i].Overlaps(coilSquares[j]))
203 G4String msg =
"error in definition \"" + definitionName +
"\": coil #" + std::to_string(i);
204 msg +=
" overlaps with coil #" + std::to_string(j) +
"\n" + coilSquares[i].Str() +
"\n" + coilSquares[j].Str();
211 G4double halfLength = 0.5*elementChordLength;
212 for (G4int i = 0; i < (G4int)coilSquares.size(); i++)
214 if (std::abs(coilSquares[i].z1) > halfLength || std::abs(coilSquares[i].z2) > halfLength)
216 G4String msg =
"error in definition \"" + definitionName +
"\": coil #" + std::to_string(i);
217 msg +=
" lies outside +- the half length (" + std::to_string(halfLength) +
" mm) of the element \"" + elementName +
"\"\n";
218 msg += coilSquares[i].Str();
221 if (coilSquares[i].r2 >= elementRadius)
223 G4String msg =
"error in definition \"" + definitionName +
"\": coil #" + std::to_string(i);
224 msg +=
" outer radius (" + std::to_string(coilSquares[i].r2) +
" mm) is greater than 1/2 the horizontalWidth of the element \"" + elementName +
"\"\n";
225 msg += elementName +
": horizontalWidth = " + std::to_string(elementRadius) +
" mm\n";
226 msg +=
"Coil cross-section: " + coilSquares[i].Str();
232std::vector<BDS::MuonCoolerDipoleInfo> BDS::BuildMuonCoolerDipoleInfos(
const GMAD::CoolingChannel& definition)
234 std::vector<BDS::MuonCoolerDipoleInfo> result;
237 G4int nDipoles = definition.nDipoles;
238 std::vector<std::string> dipoleParamNames = {
"dipoleAperture",
240 "dipoleFieldStrength",
241 "dipoleEngeCoefficient",
243 std::vector<const std::list<double>*> dipoleVars = {&(definition.dipoleAperture),
244 &(definition.dipoleLengthZ),
245 &(definition.dipoleFieldStrength),
246 &(definition.dipoleEngeCoefficient),
247 &(definition.dipoleOffsetZ)};
248 std::vector<std::vector<double> > dipoleVarsV;
257 for (G4int i = 0; i < nDipoles; i++)
260 dipoleVarsV[1][i] * CLHEP::m,
261 dipoleVarsV[2][i] * CLHEP::tesla,
263 dipoleVarsV[4][i] * CLHEP::m
265 result.push_back(info);
275 std::vector<BDS::MuonCoolerAbsorberInfo> result;
277 G4int nAbsorbers = definition.nAbsorbers;
278 std::vector<std::string> absParamNames = {
"absorberOffsetZ",
279 "absorberCylinderLength",
280 "absorberCylinderRadius",
281 "absorberWedgeOpeningAngle",
282 "absorberWedgeHeight",
283 "absorberWedgeRotationAngle",
284 "absorberWedgeOffsetX",
285 "absorberWedgeOffsetY",
286 "absorberWedgeApexToBase"};
287 std::vector<const std::list<double>*> absVars = {&(definition.absorberOffsetZ),
288 &(definition.absorberCylinderLength),
289 &(definition.absorberCylinderRadius),
290 &(definition.absorberWedgeOpeningAngle),
291 &(definition.absorberWedgeHeight),
292 &(definition.absorberWedgeRotationAngle),
293 &(definition.absorberWedgeOffsetX),
294 &(definition.absorberWedgeOffsetY),
295 &(definition.absorberWedgeApexToBase)};
296 std::vector<std::vector<double> > absVarsV;
302 absVarsV.reserve(absVars.size());
305 const auto typeListSize = definition.absorberType.size();
306 if (definition.absorberType.empty() || (typeListSize != 1 && (G4int)typeListSize != nAbsorbers))
308 G4String msg =
"error in coolingchannel definition \"" + definition.
name +
"\"\n";
309 msg +=
"number of \"absorberType\" doesn't match nAbsorbers (" + std::to_string(nAbsorbers) +
") or isn't 1";
314 const std::set<std::string> absorberTypes = {
"wedge",
"cylinder"};
315 std::vector<std::string> absorberTypeV = {definition.absorberType.begin(), definition.absorberType.end()};
316 if (absorberTypeV.size() == 1)
318 for (G4int i = 1; i < nAbsorbers; i++)
319 {absorberTypeV.push_back(absorberTypeV[0]);}
321 for (G4int i = 0; i < (G4int)absorberTypeV.size(); i++)
323 auto search = absorberTypes.find(absorberTypeV[i]);
324 if (search == absorberTypes.end())
326 G4String msg =
"unknown type of absorber: \"" + absorberTypeV[i] +
"\" at index " + std::to_string(i);
327 msg +=
"\nin definition \"" + definition.
name +
"\"";
332 std::vector<G4Material*> absorberMaterials;
335 definition.absorberMaterial,
340 for (G4int i = 0; i < nAbsorbers; i++)
342 G4double dx = absVarsV[6][i] * CLHEP::m;
343 G4double dy = absVarsV[7][i] * CLHEP::m;
344 G4double dz = absVarsV[0][i] * CLHEP::m;
346 absVarsV[1][i] * CLHEP::m,
347 absVarsV[2][i] * CLHEP::m,
348 absVarsV[3][i] * CLHEP::rad,
349 absVarsV[4][i] * CLHEP::m,
350 absVarsV[5][i] * CLHEP::rad,
351 G4ThreeVector(dx,dy,dz),
352 absVarsV[8][i] * CLHEP::m,
355 result.push_back(info);
361void BDS::CheckMuonCoolerAbsorberInfoForOverlaps(
const G4String& ,
363 const std::vector<BDS::MuonCoolerAbsorberInfo>& ,
364 const std::vector<BDS::SquareCheck>& ,
365 const std::vector<BDS::SquareCheck>& ,
370std::vector<BDS::MuonCoolerCavityInfo> BDS::BuildMuonCoolerCavityInfos(
const GMAD::CoolingChannel& definition)
372 std::vector<BDS::MuonCoolerCavityInfo> result;
374 G4int nRFCavities = definition.nRFCavities;
375 std::vector<std::string> rfParamNames = {
"rfOffsetZ",
385 std::vector<const std::list<double>*> rfVars = {&(definition.rfOffsetZ),
386 &(definition.rfLength),
387 &(definition.rfVoltage),
388 &(definition.rfPhase),
389 &(definition.rfFrequency),
390 &(definition.rfWindowThickness),
391 &(definition.rfWindowRadius),
392 &(definition.rfCavityRadius),
393 &(definition.rfCavityThickness),
394 &(definition.rfTimeOffset)};
395 std::vector<std::vector<double> > rfVarsV;
401 std::vector<G4Material*> windowMaterials;
404 definition.rfWindowMaterial,
407 std::vector<G4Material*> cavityMaterials;
410 definition.rfCavityMaterial,
413 std::vector<G4Material*> cavityVacuumMaterials;
415 "rfCavityVaccumMaterial",
416 definition.rfCavityVacuumMaterial,
418 cavityVacuumMaterials);
421 for (G4int i = 0; i < nRFCavities; i++)
424 rfVarsV[1][i] * CLHEP::m,
425 rfVarsV[2][i] * CLHEP::megavolt / CLHEP::meter,
426 rfVarsV[3][i] * CLHEP::rad,
427 rfVarsV[4][i] * CLHEP::hertz,
428 cavityVacuumMaterials[i],
429 rfVarsV[5][i] * CLHEP::m,
431 rfVarsV[6][i] * CLHEP::m,
433 rfVarsV[7][i] * CLHEP::m,
434 rfVarsV[8][i] * CLHEP::m,
435 rfVarsV[9][i] * CLHEP::ns
437 result.push_back(info);
443void BDS::CheckMuonCoolerCavityInfosForOverlaps(
const G4String& ,
445 const std::vector<BDS::SquareCheck>& ,
446 const std::vector<BDS::SquareCheck>& ,
453 std::vector<BDS::SquareCheck> squares;
454 squares.reserve(coilInfos.size());
455 for (
auto& info : coilInfos)
458 info.offsetZ+0.5*info.fullLengthZ,
460 info.innerRadius+info.radialThickness});
467 std::vector<BDS::SquareCheck> squares;
468 squares.reserve(cavityInfos.size());
482 const std::vector<
const std::list<double>*>& params,
483 const std::vector<std::string>& paramNames,
484 G4int nExpectedParams,
485 std::vector<std::vector<double>>& paramsV)
488 paramsV.reserve(params.size());
490 {paramsV.emplace_back(std::vector<double>{std::cbegin(*l), std::cend(*l)});}
493 for (G4int i = 0; i < (G4int) paramsV.size(); i++)
495 auto& v = paramsV[i];
496 if (((G4int) v.size() != nExpectedParams && v.size() != 1) || v.empty())
498 G4String msg =
"error in coolingchannel definition \"" + definitionName +
"\"\n";
499 msg +=
"number of " + paramNames[i] +
" doesn't match expected number (" + std::to_string(nExpectedParams) +
") or isn't 1";
506 for (G4int j = 1; j < nExpectedParams; j++)
513 const G4String& variableName,
514 const std::list<std::string>& materialNames,
515 G4int nExpectedParams,
516 std::vector<G4Material*>& materials)
519 if (materialNames.empty() || (materialNames.size() != 1 && (G4int)materialNames.size() != nExpectedParams))
521 G4String msg =
"error in coolingchannel definition \"" + definitionName +
"\"\n";
522 msg +=
"number of \"" + variableName +
"\" doesn't match expected number (" + std::to_string(nExpectedParams) +
") or isn't 1";
526 materials.reserve(nExpectedParams);
528 if (materialNames.size() == 1)
530 G4String materialName = G4String(materialNames.front());
532 for (G4int i = 0; i < nExpectedParams; i++)
533 {materials.push_back(material);}
537 std::vector<std::string> materialNamesV = {std::begin(materialNames), std::end(materialNames)};
538 for (G4int i = 0; i < (G4int)materialNamesV.size(); i++)
541 materials[i] = material;
546BDSFieldInfo* BDS::BuildMuonCoolerFieldRecipe(
const G4String& definitionName,
547 G4double designRigidity,
548 const G4String& integrator,
549 const G4String& magneticFieldModel,
550 const G4String& electricFieldModel,
551 const G4String& dipoleFieldModel,
552 const std::vector<BDS::MuonCoolerCoilInfo>& coilInfos,
553 const std::vector<BDS::MuonCoolerDipoleInfo>& dipoleInfos,
554 const std::vector<BDS::MuonCoolerCavityInfo>& cavityInfos)
564 auto result =
new BDSFieldInfo(BDSFieldType::muoncooler, designRigidity, it);
565 result->SetNameOfParserDefinition(definitionName);
566 result->SetExtraInfo(ei);
571 e.AppendToMessage(
"\nProblem with field in coolingchannel definition \"" + definitionName +
"\"");
Holder class for all information required to describe a beam pipe model.
General exception with possible name of object and message.
All info required to build complete field of any type.
static BDSMaterials * Instance()
Singleton pattern access.
G4Material * GetMaterial(G4String material) const
Get material by name.
Cooling channel parameters.
std::string name
Object name.
void MuonParamsToMaterials(const G4String &definitionName, const G4String &variableName, const std::list< std::string > &materialNames, G4int nExpectedParams, std::vector< G4Material * > &materials)
BDSFieldType DetermineFieldType(G4String fieldType)
Function that gives corresponding enum value for string (case-insensitive)
BDSMuonCooler * BuildMuonCooler(const G4String &elementName, G4double chordLength, G4double horizontalWidth, const GMAD::CoolingChannel &definition, BDSBeamPipeInfo *beamPipeInfo, G4double designRigidity)
void CheckMuonCoolerCoilInfosForOverlaps(const G4String &definitionName, const G4String &elementName, const std::vector< BDS::SquareCheck > &coilSquares, G4double elementChordLength, G4double elementRadius)
BDSIntegratorType DetermineIntegratorType(G4String integratorType)
Function that determines enum from string (case-insensitive).
std::vector< BDS::MuonCoolerCoilInfo > BuildMuonCoolerCoilInfos(const GMAD::CoolingChannel &definition)
void MuonParamsToVector(const G4String &definitionName, const std::vector< const std::list< double > * > ¶ms, const std::vector< std::string > ¶mNames, G4int nExpectedParams, std::vector< std::vector< double > > ¶msV)
std::vector< BDS::SquareCheck > MuonCoolerSquaresFromCoils(const std::vector< BDS::MuonCoolerCoilInfo > &coilInfos)
Utility function to make SquareCheck instances from coil info.
std::vector< BDS::MuonCoolerAbsorberInfo > BuildMuonCoolerAbsorberInfo(const GMAD::CoolingChannel &definition)
No checks for overlaps for dipoles as we don't physically build them yet.
std::vector< BDS::SquareCheck > MuonCoolerSquaresFromCavities(const std::vector< BDS::MuonCoolerCavityInfo > &cavityInfos)
Utility function to make SquareCheck instances from cavity info.
A very simple struct to permit checking un-rotated (i.e. axis-aligned) square overlaps.