18#include "BDSComponentFactory.hh"
20#include "BDSException.hh"
21#include "BDSFieldInfo.hh"
22#include "BDSFieldInfoExtra.hh"
23#include "BDSFieldType.hh"
24#include "BDSIntegratorType.hh"
25#include "BDSMaterials.hh"
26#include "BDSMuonCooler.hh"
27#include "BDSMuonCoolerBuilder.hh"
28#include "BDSMuonCoolerStructs.hh"
29#include "BDSParser.hh"
31#include "parser/coolingchannel.h"
32#include "parser/element.h"
35#include "G4ThreeVector.hh"
38#include "CLHEP/Units/SystemOfUnits.h"
51 G4double horizontalWidth,
54 G4double designRigidity)
56 G4double elementRadius = horizontalWidth * 0.5;
58 G4String definitionName = definition.
name;
72 std::vector<BDS::MuonCoolerDipoleInfo> dipoleInfos = BDS::BuildMuonCoolerDipoleInfos(definition);
76 std::vector<BDS::MuonCoolerCavityInfo> cavityInfos = BDS::BuildMuonCoolerCavityInfos(definition);
80 BDS::CheckMuonCoolerCavityInfosForOverlaps(definitionName,
90 BDS::CheckMuonCoolerAbsorberInfoForOverlaps(definitionName,
99 BDSFieldInfo* outerFieldRecipe = BDS::BuildMuonCoolerFieldRecipe(definitionName,
101 definition.integrator,
102 definition.magneticFieldModel,
103 definition.electricFieldModel,
104 definition.dipoleFieldModel,
128 std::vector<BDS::MuonCoolerCoilInfo> result;
131 G4int nCoils = definition.nCoils;
132 std::vector<std::string> coilParamNames = {
"coilInnerRadius",
133 "coilRadialThickness",
137 std::vector<const std::list<double>*> coilVars = {&(definition.coilInnerRadius),
138 &(definition.coilRadialThickness),
139 &(definition.coilLengthZ),
140 &(definition.coilCurrent),
141 &(definition.coilOffsetZ)};
142 std::vector<std::vector<double> > coilVarsV;
149 std::vector<G4Material*> coilMaterials;
152 definition.coilMaterial,
157 for (G4int i = 0; i < nCoils; i++)
160 coilVarsV[1][i] * CLHEP::m,
161 coilVarsV[2][i] * CLHEP::m,
162 coilVarsV[3][i] * CLHEP::ampere,
163 coilVarsV[4][i] * CLHEP::m,
165 definition.onAxisTolerance * CLHEP::tesla,
169 result.push_back(info);
172 if (definition.mirrorCoils)
174 result.reserve(2*result.size());
175 std::copy(result.rbegin(), result.rend(), std::back_inserter(result));
176 for (G4int j = (G4int)result.size() - 1; j > nCoils - 1; j--)
177 {result[j].offsetZ *= -1;}
184 const G4String& elementName,
185 const std::vector<BDS::SquareCheck>& coilSquares,
186 G4double elementChordLength,
187 G4double elementRadius)
194 for (G4int i = 0; i < (G4int)coilSquares.size(); i++)
196 for (G4int j = i+1; j < (G4int)coilSquares.size(); j++)
200 if (coilSquares[i].Overlaps(coilSquares[j]))
202 G4String msg =
"error in definition \"" + definitionName +
"\": coil #" + std::to_string(i);
203 msg +=
" overlaps with coil #" + std::to_string(j) +
"\n" + coilSquares[i].Str() +
"\n" + coilSquares[j].Str();
210 G4double halfLength = 0.5*elementChordLength;
211 for (G4int i = 0; i < (G4int)coilSquares.size(); i++)
213 if (std::abs(coilSquares[i].z1) > halfLength || std::abs(coilSquares[i].z2) > halfLength)
215 G4String msg =
"error in definition \"" + definitionName +
"\": coil #" + std::to_string(i);
216 msg +=
" lies outside +- the half length (" + std::to_string(halfLength) +
" mm) of the element \"" + elementName +
"\"\n";
217 msg += coilSquares[i].Str();
220 if (coilSquares[i].r2 >= elementRadius)
222 G4String msg =
"error in definition \"" + definitionName +
"\": coil #" + std::to_string(i);
223 msg +=
" outer radius (" + std::to_string(coilSquares[i].r2) +
" mm) is greater than 1/2 the horizontalWidth of the element \"" + elementName +
"\"\n";
224 msg += elementName +
": horizontalWidth = " + std::to_string(elementRadius) +
" mm\n";
225 msg +=
"Coil cross-section: " + coilSquares[i].Str();
231std::vector<BDS::MuonCoolerDipoleInfo> BDS::BuildMuonCoolerDipoleInfos(
const GMAD::CoolingChannel& definition)
233 std::vector<BDS::MuonCoolerDipoleInfo> result;
236 G4int nDipoles = definition.nDipoles;
237 std::vector<std::string> dipoleParamNames = {
"dipoleAperture",
239 "dipoleFieldStrength",
240 "dipoleEngeCoefficient",
242 std::vector<const std::list<double>*> dipoleVars = {&(definition.dipoleAperture),
243 &(definition.dipoleLengthZ),
244 &(definition.dipoleFieldStrength),
245 &(definition.dipoleEngeCoefficient),
246 &(definition.dipoleOffsetZ)};
247 std::vector<std::vector<double> > dipoleVarsV;
256 for (G4int i = 0; i < nDipoles; i++)
259 dipoleVarsV[1][i] * CLHEP::m,
260 dipoleVarsV[2][i] * CLHEP::tesla,
262 dipoleVarsV[4][i] * CLHEP::m
264 result.push_back(info);
274 std::vector<BDS::MuonCoolerAbsorberInfo> result;
276 G4int nAbsorbers = definition.nAbsorbers;
277 std::vector<std::string> absParamNames = {
"absorberOffsetZ",
278 "absorberCylinderLength",
279 "absorberCylinderRadius",
280 "absorberWedgeOpeningAngle",
281 "absorberWedgeHeight",
282 "absorberWedgeRotationAngle",
283 "absorberWedgeOffsetX",
284 "absorberWedgeOffsetY",
285 "absorberWedgeApexToBase"};
286 std::vector<const std::list<double>*> absVars = {&(definition.absorberOffsetZ),
287 &(definition.absorberCylinderLength),
288 &(definition.absorberCylinderRadius),
289 &(definition.absorberWedgeOpeningAngle),
290 &(definition.absorberWedgeHeight),
291 &(definition.absorberWedgeRotationAngle),
292 &(definition.absorberWedgeOffsetX),
293 &(definition.absorberWedgeOffsetY),
294 &(definition.absorberWedgeApexToBase)};
295 std::vector<std::vector<double> > absVarsV;
301 absVarsV.reserve(absVars.size());
304 const auto typeListSize = definition.absorberType.size();
305 if (definition.absorberType.empty() || (typeListSize != 1 && (G4int)typeListSize != nAbsorbers))
307 G4String msg =
"error in coolingchannel definition \"" + definition.
name +
"\"\n";
308 msg +=
"number of \"absorberType\" doesn't match nAbsorbers (" + std::to_string(nAbsorbers) +
") or isn't 1";
313 const std::set<std::string> absorberTypes = {
"wedge",
"cylinder"};
314 std::vector<std::string> absorberTypeV = {definition.absorberType.begin(), definition.absorberType.end()};
315 if (absorberTypeV.size() == 1)
317 for (G4int i = 1; i < nAbsorbers; i++)
318 {absorberTypeV.push_back(absorberTypeV[0]);}
320 for (G4int i = 0; i < (G4int)absorberTypeV.size(); i++)
322 auto search = absorberTypes.find(absorberTypeV[i]);
323 if (search == absorberTypes.end())
325 G4String msg =
"unknown type of absorber: \"" + absorberTypeV[i] +
"\" at index " + std::to_string(i);
326 msg +=
"\nin definition \"" + definition.
name +
"\"";
331 std::vector<G4Material*> absorberMaterials;
334 definition.absorberMaterial,
339 for (G4int i = 0; i < nAbsorbers; i++)
341 G4double dx = absVarsV[6][i] * CLHEP::m;
342 G4double dy = absVarsV[7][i] * CLHEP::m;
343 G4double dz = absVarsV[0][i] * CLHEP::m;
345 absVarsV[1][i] * CLHEP::m,
346 absVarsV[2][i] * CLHEP::m,
347 absVarsV[3][i] * CLHEP::rad,
348 absVarsV[4][i] * CLHEP::m,
349 absVarsV[5][i] * CLHEP::rad,
350 G4ThreeVector(dx,dy,dz),
351 absVarsV[8][i] * CLHEP::m,
354 result.push_back(info);
360void BDS::CheckMuonCoolerAbsorberInfoForOverlaps(
const G4String& ,
362 const std::vector<BDS::MuonCoolerAbsorberInfo>& ,
363 const std::vector<BDS::SquareCheck>& ,
364 const std::vector<BDS::SquareCheck>& ,
369std::vector<BDS::MuonCoolerCavityInfo> BDS::BuildMuonCoolerCavityInfos(
const GMAD::CoolingChannel& definition)
371 std::vector<BDS::MuonCoolerCavityInfo> result;
373 G4int nRFCavities = definition.nRFCavities;
374 std::vector<std::string> rfParamNames = {
"rfOffsetZ",
384 std::vector<const std::list<double>*> rfVars = {&(definition.rfOffsetZ),
385 &(definition.rfLength),
386 &(definition.rfVoltage),
387 &(definition.rfPhase),
388 &(definition.rfFrequency),
389 &(definition.rfWindowThickness),
390 &(definition.rfWindowRadius),
391 &(definition.rfCavityRadius),
392 &(definition.rfCavityThickness),
393 &(definition.rfTimeOffset)};
394 std::vector<std::vector<double> > rfVarsV;
400 std::vector<G4Material*> windowMaterials;
403 definition.rfWindowMaterial,
406 std::vector<G4Material*> cavityMaterials;
409 definition.rfCavityMaterial,
412 std::vector<G4Material*> cavityVacuumMaterials;
414 "rfCavityVaccumMaterial",
415 definition.rfCavityVacuumMaterial,
417 cavityVacuumMaterials);
420 for (G4int i = 0; i < nRFCavities; i++)
423 rfVarsV[1][i] * CLHEP::m,
424 rfVarsV[2][i] * CLHEP::megavolt / CLHEP::meter,
425 rfVarsV[3][i] * CLHEP::rad,
426 rfVarsV[4][i] * CLHEP::hertz,
427 cavityVacuumMaterials[i],
428 rfVarsV[5][i] * CLHEP::m,
430 rfVarsV[6][i] * CLHEP::m,
432 rfVarsV[7][i] * CLHEP::m,
433 rfVarsV[8][i] * CLHEP::m,
434 rfVarsV[9][i] * CLHEP::ns
436 result.push_back(info);
442void BDS::CheckMuonCoolerCavityInfosForOverlaps(
const G4String& ,
444 const std::vector<BDS::SquareCheck>& ,
445 const std::vector<BDS::SquareCheck>& ,
452 std::vector<BDS::SquareCheck> squares;
453 squares.reserve(coilInfos.size());
454 for (
auto& info : coilInfos)
457 info.offsetZ+0.5*info.fullLengthZ,
459 info.innerRadius+info.radialThickness});
466 std::vector<BDS::SquareCheck> squares;
467 squares.reserve(cavityInfos.size());
481 const std::vector<
const std::list<double>*>& params,
482 const std::vector<std::string>& paramNames,
483 G4int nExpectedParams,
484 std::vector<std::vector<double>>& paramsV)
487 paramsV.reserve(params.size());
489 {paramsV.emplace_back(std::vector<double>{std::cbegin(*l), std::cend(*l)});}
492 for (G4int i = 0; i < (G4int) paramsV.size(); i++)
494 auto& v = paramsV[i];
495 if (((G4int) v.size() != nExpectedParams && v.size() != 1) || v.empty())
497 G4String msg =
"error in coolingchannel definition \"" + definitionName +
"\"\n";
498 msg +=
"number of " + paramNames[i] +
" doesn't match expected number (" + std::to_string(nExpectedParams) +
") or isn't 1";
505 for (G4int j = 1; j < nExpectedParams; j++)
512 const G4String& variableName,
513 const std::list<std::string>& materialNames,
514 G4int nExpectedParams,
515 std::vector<G4Material*>& materials)
518 if (materialNames.empty() || (materialNames.size() != 1 && (G4int)materialNames.size() != nExpectedParams))
520 G4String msg =
"error in coolingchannel definition \"" + definitionName +
"\"\n";
521 msg +=
"number of \"" + variableName +
"\" doesn't match expected number (" + std::to_string(nExpectedParams) +
") or isn't 1";
525 materials.reserve(nExpectedParams);
527 if (materialNames.size() == 1)
529 G4String materialName = G4String(materialNames.front());
531 for (G4int i = 0; i < nExpectedParams; i++)
532 {materials.push_back(material);}
536 std::vector<std::string> materialNamesV = {std::begin(materialNames), std::end(materialNames)};
537 for (G4int i = 0; i < (G4int)materialNamesV.size(); i++)
540 materials[i] = material;
545BDSFieldInfo* BDS::BuildMuonCoolerFieldRecipe(
const G4String& definitionName,
546 G4double designRigidity,
547 const G4String& integrator,
548 const G4String& magneticFieldModel,
549 const G4String& electricFieldModel,
550 const G4String& dipoleFieldModel,
551 const std::vector<BDS::MuonCoolerCoilInfo>& coilInfos,
552 const std::vector<BDS::MuonCoolerDipoleInfo>& dipoleInfos,
553 const std::vector<BDS::MuonCoolerCavityInfo>& cavityInfos)
563 auto result =
new BDSFieldInfo(BDSFieldType::muoncooler, designRigidity, it);
564 result->SetNameOfParserDefinition(definitionName);
565 result->SetExtraInfo(ei);
570 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.