BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSFieldLoader.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "BDSArray1DCoords.hh"
19#include "BDSArray1DCoordsTransformed.hh"
20#include "BDSArray2DCoords.hh"
21#include "BDSArray2DCoordsTransformed.hh"
22#include "BDSArray3DCoords.hh"
23#include "BDSArray3DCoordsTransformed.hh"
24#include "BDSArray4DCoords.hh"
25#include "BDSArray4DCoordsTransformed.hh"
26#include "BDSArray2DCoordsRDipole.hh"
27#include "BDSArray2DCoordsRQuad.hh"
28#include "BDSArrayInfo.hh"
29#include "BDSArrayOperatorIndex.hh"
30#include "BDSArrayOperatorIndexFlip.hh"
31#include "BDSArrayOperatorIndexReflect.hh"
32#include "BDSArrayOperatorIndexV.hh"
33#include "BDSArrayOperatorValue.hh"
34#include "BDSArrayOperatorValueFlip.hh"
35#include "BDSArrayOperatorValueReflect.hh"
36#include "BDSArrayOperatorValueReflectDipoleXY.hh"
37#include "BDSArrayOperatorValueReflectDipoleY.hh"
38#include "BDSArrayOperatorValueReflectQuadrupoleXY.hh"
39#include "BDSArrayOperatorValueReflectSolenoidZ.hh"
40#include "BDSArrayOperatorValueV.hh"
41#include "BDSArrayReflectionType.hh"
42#include "BDSDebug.hh"
43#include "BDSException.hh"
44#include "BDSFieldEInterpolated.hh"
45#include "BDSFieldEInterpolated1D.hh"
46#include "BDSFieldEInterpolated2D.hh"
47#include "BDSFieldEInterpolated3D.hh"
48#include "BDSFieldEInterpolated4D.hh"
49#include "BDSFieldEMInterpolated.hh"
50#include "BDSFieldEMInterpolated1D.hh"
51#include "BDSFieldEMInterpolated2D.hh"
52#include "BDSFieldEMInterpolated3D.hh"
53#include "BDSFieldEMInterpolated4D.hh"
54#include "BDSFieldFormat.hh"
55#include "BDSFieldInfo.hh"
56#include "BDSFieldLoader.hh"
57#include "BDSFieldLoaderBDSIM.hh"
58#include "BDSFieldLoaderPoisson.hh"
59#include "BDSFieldMagInterpolated.hh"
60#include "BDSFieldMagInterpolated1D.hh"
61#include "BDSFieldMagInterpolated2D.hh"
62#include "BDSFieldMagInterpolated3D.hh"
63#include "BDSFieldMagInterpolated4D.hh"
64#include "BDSFieldValue.hh"
65#include "BDSInterpolator1D.hh"
66#include "BDSInterpolator1DCubic.hh"
67#include "BDSInterpolator1DLinear.hh"
68#include "BDSInterpolator1DLinearMag.hh"
69#include "BDSInterpolator1DNearest.hh"
70#include "BDSInterpolator2D.hh"
71#include "BDSInterpolator2DCubic.hh"
72#include "BDSInterpolator2DLinear.hh"
73#include "BDSInterpolator2DLinearMag.hh"
74#include "BDSInterpolator2DNearest.hh"
75#include "BDSInterpolator3D.hh"
76#include "BDSInterpolator3DCubic.hh"
77#include "BDSInterpolator3DLinear.hh"
78#include "BDSInterpolator3DLinearMag.hh"
79#include "BDSInterpolator3DNearest.hh"
80#include "BDSInterpolator4D.hh"
81#include "BDSInterpolator4DCubic.hh"
82#include "BDSInterpolator4DLinear.hh"
83#include "BDSInterpolator4DLinearMag.hh"
84#include "BDSInterpolator4DNearest.hh"
85#include "BDSInterpolatorType.hh"
86#include "BDSFieldMagGradient.hh"
87#include "BDSMagnetStrength.hh"
88#include "BDSWarning.hh"
89
90#include "globals.hh" // geant4 types / globals
91#include "G4String.hh"
92
93#include <algorithm>
94#include <array>
95#include <cmath>
96#include <fstream>
97#include <set>
98
99#ifdef USE_GZSTREAM
100#include "src-external/gzstream/gzstream.h"
101#endif
102
104
106{
107 if (!instance)
108 {instance = new BDSFieldLoader();}
109 return instance;
110}
111
114
115BDSFieldLoader::~BDSFieldLoader()
116{
117 DeleteArrays();
118 instance = nullptr;
119}
120
121void BDSFieldLoader::DeleteArrays()
122{
123 for (auto& a : arrays1d)
124 {delete a.second;}
125 for (auto& a : arrays2d)
126 {delete a.second;}
127 for (auto& a : arrays3d)
128 {delete a.second;}
129 for (auto& a : arrays4d)
130 {delete a.second;}
131}
132
134 const BDSMagnetStrength* scalingStrength,
135 const G4String& scalingKey)
136{
137 BFilePathOK(info);
138 G4String filePath = info.MagneticFile();
139 BDSFieldFormat format = info.MagneticFormat();
140 BDSInterpolatorType interpolatorType = info.MagneticInterpolatorType();
141 G4Transform3D transform = info.Transform();
142 G4double bScaling = info.BScaling();
143 BDSArrayReflectionTypeSet reflection = info.MagneticArrayReflectionType();
144 BDSArrayReflectionTypeSet* reflectionPointer = reflection.empty() ? nullptr : &reflection;
145
146 BDSFieldMagInterpolated* result = nullptr;
147 try
148 {
149 switch (format.underlying())
150 {
151 case BDSFieldFormat::bdsim1d:
152 {result = LoadBDSIM1DB(filePath, interpolatorType, transform, bScaling, reflectionPointer); break;}
153 case BDSFieldFormat::bdsim2d:
154 {result = LoadBDSIM2DB(filePath, interpolatorType, transform, bScaling, reflectionPointer); break;}
155 case BDSFieldFormat::bdsim3d:
156 {result = LoadBDSIM3DB(filePath, interpolatorType, transform, bScaling, reflectionPointer); break;}
157 case BDSFieldFormat::bdsim4d:
158 {result = LoadBDSIM4DB(filePath, interpolatorType, transform, bScaling, reflectionPointer); break;}
159 case BDSFieldFormat::poisson2d:
160 {result = LoadPoissonSuperFishB(filePath, interpolatorType, transform, bScaling, reflectionPointer); break;}
161 case BDSFieldFormat::poisson2dquad:
162 {result = LoadPoissonSuperFishBQuad(filePath, interpolatorType, transform, bScaling, reflectionPointer); break;}
163 case BDSFieldFormat::poisson2ddipole:
164 {result = LoadPoissonSuperFishBDipole(filePath, interpolatorType, transform, bScaling, reflectionPointer); break;}
165 default:
166 {break;}
167 }
168 }
169 catch (BDSException& e)
170 {
171 e.AppendToMessage("\nError in field definition \"" + info.NameOfParserDefinition() + "\".");
172 throw e;
173 }
174
175 if (result && info.AutoScale() && scalingStrength)
176 {
177 // prepare temporary recipe for field with cubic interpolation and no scaling
178 // other than units
179 BDSFieldInfo temporaryRecipe = BDSFieldInfo(info);
180 temporaryRecipe.SetAutoScale(false); // prevent recursion
181 temporaryRecipe.SetBScaling(1); // don't affect result with inadvertent scaling
182
183 // enforce cubic interpolation for continuous higher differentials
184 G4int nDimFF = BDS::NDimensionsOfFieldFormat(format);
185 auto magIntType = BDS::InterpolatorTypeSpecificFromAuto(nDimFF, BDSInterpolatorType::cubicauto);
186 temporaryRecipe.SetMagneticInterpolatorType(magIntType);
187
188 // build temporary field object
189 BDSFieldMagInterpolated* tempField = LoadMagField(temporaryRecipe);
190
191 // calculate field gradients and therefore associated strengths for a given rigidity
192 BDSFieldMagGradient calculator;
193 BDSMagnetStrength* calculatedStrengths = calculator.CalculateMultipoles(tempField,
194 5,/*up to 5th order*/
195 info.BRho());
196
197 delete tempField; // clear up
198
199 G4double calculatedNumber = (*calculatedStrengths)[scalingKey];
200 G4double ratio = (*scalingStrength)[scalingKey] / calculatedNumber;
201 if (!std::isnormal(ratio))
202 {
203 G4cout << __METHOD_NAME__ << "invalid ratio detected (" << ratio << ") setting to 1.0" << G4endl;
204 ratio = 1;
205 }
206 G4double newScale = result->Scaling() * ratio;
207 G4cout << "autoScale> Calculated " << scalingKey << " = " << calculatedNumber << G4endl;
208 G4cout << "autoScale> Ratio of supplied strength to calculated map strength: " << ratio << G4endl;
209 G4cout << "autoScale> New overall scaling factor: " << bScaling*ratio << G4endl;
210 result->SetScaling(newScale);
211 delete calculatedStrengths;
212 }
213
214 return result;
215}
216
218{
219 EFilePathOK(info);
220 G4String filePath = info.ElectricFile();
221 BDSFieldFormat format = info.ElectricFormat();
222 BDSInterpolatorType interpolatorType = info.ElectricInterpolatorType();
223 G4Transform3D transform = info.Transform();
224 G4double eScaling = info.EScaling();
225 BDSArrayReflectionTypeSet reflection = info.ElectricArrayReflectionType();
226 BDSArrayReflectionTypeSet* reflectionPointer = reflection.empty() ? nullptr : &reflection;
227
228 BDSFieldEInterpolated* result = nullptr;
229 try
230 {
231 switch (format.underlying())
232 {
233 case BDSFieldFormat::bdsim1d:
234 {result = LoadBDSIM1DE(filePath, interpolatorType, transform, eScaling, reflectionPointer); break;}
235 case BDSFieldFormat::bdsim2d:
236 {result = LoadBDSIM2DE(filePath, interpolatorType, transform, eScaling, reflectionPointer); break;}
237 case BDSFieldFormat::bdsim3d:
238 {result = LoadBDSIM3DE(filePath, interpolatorType, transform, eScaling, reflectionPointer); break;}
239 case BDSFieldFormat::bdsim4d:
240 {result = LoadBDSIM4DE(filePath, interpolatorType, transform, eScaling, reflectionPointer); break;}
241 default:
242 {break;}
243 }
244 }
245 catch (BDSException& e)
246 {
247 e.AppendToMessage(" error in field definition \"" + info.NameOfParserDefinition() + "\"");
248 throw e;
249 }
250 return result;
251}
252
254{
255 BFilePathOK(info);
256 EFilePathOK(info);
257 G4String eFilePath = info.ElectricFile();
258 G4String bFilePath = info.MagneticFile();
259 BDSFieldFormat eFormat = info.ElectricFormat();
260 BDSFieldFormat bFormat = info.MagneticFormat();
263 G4Transform3D transform = info.Transform();
264 G4double eScaling = info.EScaling();
265 G4double bScaling = info.BScaling();
266 BDSArrayReflectionTypeSet bReflection = info.MagneticArrayReflectionType();
267 BDSArrayReflectionTypeSet* bReflectionPointer = bReflection.empty() ? nullptr : &bReflection;
268 BDSArrayReflectionTypeSet eReflection = info.ElectricArrayReflectionType();
269 BDSArrayReflectionTypeSet* eReflectionPointer = eReflection.empty() ? nullptr : &eReflection;
270
271 // As the different dimension interpolators don't inherit each other, it's very
272 // very hard to make a compact polymorphic construction routine here. In future,
273 // if we use delayed construction with setters, we could piece together the BDSFieldEM
274 // one bit at a time. This is more an issue with the number of dimensions than anything.
275 if (bFormat != eFormat)
276 {throw BDSException(__METHOD_NAME__, "different formats for E and B fields are not currently supported for an EM field");}
277
278 BDSFieldEMInterpolated* result = nullptr;
279 try
280 {
281 switch (eFormat.underlying())
282 {
283 case BDSFieldFormat::bdsim1d:
284 {
285 result = LoadBDSIM1DEM(eFilePath, bFilePath, eIntType, bIntType, transform,
286 eScaling, bScaling, eReflectionPointer, bReflectionPointer);
287 break;
288 }
289 case BDSFieldFormat::bdsim2d:
290 {
291 result = LoadBDSIM2DEM(eFilePath, bFilePath, eIntType, bIntType, transform,
292 eScaling, bScaling, eReflectionPointer, bReflectionPointer);
293 break;
294 }
295 case BDSFieldFormat::bdsim3d:
296 {
297 result = LoadBDSIM3DEM(eFilePath, bFilePath, eIntType, bIntType, transform,
298 eScaling, bScaling, eReflectionPointer, bReflectionPointer);
299 break;
300 }
301 case BDSFieldFormat::bdsim4d:
302 {
303 result = LoadBDSIM4DEM(eFilePath, bFilePath, eIntType, bIntType, transform,
304 eScaling, bScaling, eReflectionPointer, bReflectionPointer);
305 break;
306 }
307 default:
308 {break;}
309 }
310 }
311 catch (BDSException& e)
312 {
313 e.AppendToMessage(" error in field definition \"" + info.NameOfParserDefinition() + "\"");
314 throw e;
315 }
316 return result;
317}
318
320{
321 G4String filePath = info.MagneticFile();
322 if (filePath.empty())
323 {
324 G4String msg = "no magneticFile specified in field definition \"" + info.NameOfParserDefinition() + "\"";
325 throw BDSException(__METHOD_NAME__, msg);
326 }
327}
328
330{
331 G4String filePath = info.ElectricFile();
332 if (filePath.empty())
333 {
334 G4String msg = "no electricFile specified in field definition \"" + info.NameOfParserDefinition() + "\"";
335 throw BDSException(__METHOD_NAME__, msg);
336 }
337}
338
340{
341 auto result = arrays1d.find(filePath);
342 if (result != arrays1d.end())
343 {return result->second;}
344 else
345 {return nullptr;}
346}
347
349{
350 auto result = arrays2d.find(filePath);
351 if (result != arrays2d.end())
352 {return result->second;}
353 else
354 {return nullptr;}
355}
356
358{
359 auto result = arrays3d.find(filePath);
360 if (result != arrays3d.end())
361 {return result->second;}
362 else
363 {return nullptr;}
364}
365
367{
368 auto result = arrays4d.find(filePath);
369 if (result != arrays4d.end())
370 {return result->second;}
371 else
372 {return nullptr;}
373}
374
376{
377 BDSArray2DCoords* cached = Get2DCached(filePath);
378 if (cached)
379 {return cached;}
380
381 BDSArray2DCoords* result = nullptr;
382 if (filePath.rfind("gz") != std::string::npos)
383 {
384#ifdef USE_GZSTREAM
386 result = loader.LoadMag2D(filePath);
387#else
388 throw BDSException(__METHOD_NAME__, "Compressed file loading - but BDSIM not compiled with ZLIB.");
389#endif
390 }
391 else
392 {
394 result = loader.LoadMag2D(filePath);
395 }
396 arrays2d[filePath] = result;
397 return result;
398}
399
401{
402 BDSArray1DCoords* cached = Get1DCached(filePath);
403 if (cached)
404 {return cached;}
405
406 // Don't want to template this class and there's no base class pointer
407 // for BDSFieldLoader so unfortunately, there's a wee bit of repetition.
408 BDSArray1DCoords* result = nullptr;
409 if (filePath.rfind("gz") != std::string::npos)
410 {
411#ifdef USE_GZSTREAM
413 result = loader.Load1D(filePath);
414#else
415 throw BDSException(__METHOD_NAME__, "Compressed file loading - but BDSIM not compiled with ZLIB.");
416#endif
417 }
418 else
419 {
421 result = loader.Load1D(filePath);
422 }
423 arrays1d[filePath] = result;
424 return result;
425}
426
428{
429 BDSArray2DCoords* cached = Get2DCached(filePath);
430 if (cached)
431 {return cached;}
432
433 BDSArray2DCoords* result = nullptr;
434 if (filePath.rfind("gz") != std::string::npos)
435 {
436#ifdef USE_GZSTREAM
438 result = loader.Load2D(filePath);
439#else
440 throw BDSException(__METHOD_NAME__, "Compressed file loading - but BDSIM not compiled with ZLIB.");
441#endif
442 }
443 else
444 {
446 result = loader.Load2D(filePath);
447 }
448 arrays2d[filePath] = result;
449 return result;
450}
451
453{
454 BDSArray3DCoords* cached = Get3DCached(filePath);
455 if (cached)
456 {return cached;}
457
458 BDSArray3DCoords* result = nullptr;
459 if (filePath.rfind("gz") != std::string::npos )
460 {
461#ifdef USE_GZSTREAM
463 result = loader.Load3D(filePath);
464#else
465 throw BDSException(__METHOD_NAME__, "Compressed file loading - but BDSIM not compiled with ZLIB.");
466#endif
467 }
468 else
469 {
471 result = loader.Load3D(filePath);
472}
473 arrays3d[filePath] = result;
474 return result;
475}
476
478{
479 BDSArray4DCoords* cached = Get4DCached(filePath);
480 if (cached)
481 {return cached;}
482
483 BDSArray4DCoords* result = nullptr;
484 if (filePath.rfind("gz") != std::string::npos)
485 {
486#ifdef USE_GZSTREAM
488 result = loader.Load4D(filePath);
489#else
490 throw BDSException(__METHOD_NAME__, "Compressed file loading - but BDSIM not compiled with ZLIB.");
491#endif
492 }
493 else
494 {
496 result = loader.Load4D(filePath);
497 }
498 arrays4d[filePath] = result;
499 return result;
500}
501
503 BDSInterpolatorType interpolatorType) const
504{
505 BDSInterpolator1D* result = nullptr;
506 switch (interpolatorType.underlying())
507 {
508 case BDSInterpolatorType::nearest1d:
509 {result = new BDSInterpolator1DNearest(array); break;}
510 case BDSInterpolatorType::linear1d:
511 {result = new BDSInterpolator1DLinear(array); break;}
512 case BDSInterpolatorType::linearmag1d:
513 {result = new BDSInterpolator1DLinearMag(array); break;}
514 case BDSInterpolatorType::cubic1d:
515 {result = new BDSInterpolator1DCubic(array); break;}
516 default:
517 {throw BDSException(__METHOD_NAME__, "Invalid interpolator type for 1D field: " + interpolatorType.ToString()); break;}
518 }
519 return result;
520}
521
523 BDSInterpolatorType interpolatorType) const
524{
525 BDSInterpolator2D* result = nullptr;
526 switch (interpolatorType.underlying())
527 {
528 case BDSInterpolatorType::nearest2d:
529 {result = new BDSInterpolator2DNearest(array); break;}
530 case BDSInterpolatorType::linear2d:
531 {result = new BDSInterpolator2DLinear(array); break;}
532 case BDSInterpolatorType::linearmag2d:
533 {result = new BDSInterpolator2DLinearMag(array); break;}
534 case BDSInterpolatorType::cubic2d:
535 {result = new BDSInterpolator2DCubic(array); break;}
536 default:
537 {throw BDSException(__METHOD_NAME__, "Invalid interpolator type for 2D field: " + interpolatorType.ToString()); break;}
538 }
539 return result;
540}
541
543 BDSInterpolatorType interpolatorType) const
544{
545 BDSInterpolator3D* result = nullptr;
546 switch (interpolatorType.underlying())
547 {
548 case BDSInterpolatorType::nearest3d:
549 {result = new BDSInterpolator3DNearest(array); break;}
550 case BDSInterpolatorType::linear3d:
551 {result = new BDSInterpolator3DLinear(array); break;}
552 case BDSInterpolatorType::linearmag3d:
553 {result = new BDSInterpolator3DLinearMag(array); break;}
554 case BDSInterpolatorType::cubic3d:
555 {result = new BDSInterpolator3DCubic(array); break;}
556 default:
557 {throw BDSException(__METHOD_NAME__, "Invalid interpolator type for 3D field: " + interpolatorType.ToString()); break;}
558 }
559 return result;
560}
561
563 BDSInterpolatorType interpolatorType) const
564{
565 BDSInterpolator4D* result = nullptr;
566 switch (interpolatorType.underlying())
567 {
568 case BDSInterpolatorType::nearest4d:
569 {result = new BDSInterpolator4DNearest(array); break;}
570 case BDSInterpolatorType::linear4d:
571 {result = new BDSInterpolator4DLinear(array); break;}
572 case BDSInterpolatorType::linearmag4d:
573 {result = new BDSInterpolator4DLinearMag(array); break;}
574 case BDSInterpolatorType::cubic4d:
575 {result = new BDSInterpolator4DCubic(array); break;}
576 default:
577 {throw BDSException(__METHOD_NAME__, "Invalid interpolator type for 4D field: " + interpolatorType.ToString()); break;}
578 }
579 return result;
580}
581
582void BDSFieldLoader::CreateOperators(const BDSArrayReflectionTypeSet* reflectionTypes,
583 const BDSArray4DCoords* existingArray,
584 BDSArrayOperatorIndex*& indexOperator,
585 BDSArrayOperatorValue*& valueOperator) const
586{
587 G4String details;
588 G4bool problem = BDS::ProblemWithArrayReflectionCombination(*reflectionTypes, &details);
589 if (problem)
590 {
591 G4String msg = "Invalid combination of array transforms.\n";
592 msg += details;
593 throw BDSException(__METHOD_NAME__, msg); // caught at a higher level to append name of definition
594 }
595
596 auto arrayInfo = BDSArrayInfo(existingArray);
597
598 std::vector<BDSArrayOperatorIndex*> indexOperators;
599 std::vector<BDSArrayOperatorValue*> valueOperators;
600
601 // input xyzt are w.r.t. spatial dimensions - we want to translate that into
602 // whether to operate on the 'x', 'y', 'z', 't' of the array, which may
603 // not truly be xyzt (this is a hangover from the initial design). Think of
604 // it as xyzt (spatial) -> ijkl (array). e.g. 1D array of spatial z -> only
605 // 'x' in the array is filled.
606 // .underlying() gives us an int from the enum
607
608 // flips are combined into 1 operator
609 std::array<G4bool,4> flipIndexOperators = {false, false, false, false};
610 for (auto& reflectionType : *reflectionTypes)
611 {
612 switch (reflectionType.underlying())
613 {
614 case BDSArrayReflectionType::flipx:
615 {flipIndexOperators[existingArray->DimensionIndex(BDSDimensionType::x)] = true; break;}
616 case BDSArrayReflectionType::flipy:
617 {flipIndexOperators[existingArray->DimensionIndex(BDSDimensionType::y)] = true; break;}
618 case BDSArrayReflectionType::flipz:
619 {flipIndexOperators[existingArray->DimensionIndex(BDSDimensionType::z)] = true; break;}
620 case BDSArrayReflectionType::flipt:
621 {flipIndexOperators[existingArray->DimensionIndex(BDSDimensionType::t)] = true; break;}
622 default:
623 {break;}
624 }
625 }
626 G4bool anyFlipIndexOperators = std::any_of(std::begin(flipIndexOperators), std::end(flipIndexOperators), [](bool i){return i;});
627 if (anyFlipIndexOperators)
628 {//nIndexOperatorsRequired
629 indexOperators.emplace_back(new BDSArrayOperatorIndexFlip(flipIndexOperators));
630 valueOperators.emplace_back(new BDSArrayOperatorValueFlip(flipIndexOperators)); // no operation
631 }
632
633 // basic reflections are combined into 1 operator
634 std::array<G4bool,4> reflectIndexOperators = {false, false, false, false};
635 for (auto& reflectionType : *reflectionTypes)
636 {
637 switch (reflectionType.underlying())
638 {
639 case BDSArrayReflectionType::reflectx:
640 {reflectIndexOperators[existingArray->DimensionIndex(BDSDimensionType::x)] = true; break;}
641 case BDSArrayReflectionType::reflecty:
642 {reflectIndexOperators[existingArray->DimensionIndex(BDSDimensionType::y)] = true; break;}
643 case BDSArrayReflectionType::reflectz:
644 {reflectIndexOperators[existingArray->DimensionIndex(BDSDimensionType::z)] = true; break;}
645 case BDSArrayReflectionType::reflectt:
646 {reflectIndexOperators[existingArray->DimensionIndex(BDSDimensionType::t)] = true; break;}
647 default:
648 {break;}
649 }
650 }
651 G4bool anyReflectIndexOperators = std::any_of(std::begin(reflectIndexOperators), std::end(reflectIndexOperators), [](bool i){return i;});
652 if (anyReflectIndexOperators)
653 {//nIndexOperatorsRequired
654 indexOperators.emplace_back(new BDSArrayOperatorIndexReflect(reflectIndexOperators, arrayInfo));
655 valueOperators.emplace_back(new BDSArrayOperatorValueReflect(reflectIndexOperators, arrayInfo));
656 }
657
658 // special reflections
659 for (auto& reflectionType : *reflectionTypes)
660 {
661 switch (reflectionType.underlying())
662 {
663 case BDSArrayReflectionType::reflectxydipole:
664 {
665 indexOperators.emplace_back(new BDSArrayOperatorIndexReflect({true, true, false, false}, arrayInfo));
666 valueOperators.emplace_back(new BDSArrayOperatorValueReflectDipoleXY());
667 break;
668 }
669 case BDSArrayReflectionType::reflectxzdipole:
670 {
671 indexOperators.emplace_back(new BDSArrayOperatorIndexReflect({false, true, false, false}, arrayInfo));
672 valueOperators.emplace_back(new BDSArrayOperatorValueReflectDipoleY());
673 break;
674 }
675 case BDSArrayReflectionType::reflectyzdipole:
676 {
677 indexOperators.emplace_back(new BDSArrayOperatorIndexReflect({true, false, false, false}, arrayInfo));
678 valueOperators.emplace_back(new BDSArrayOperatorValueReflect({true, false, false, false}, arrayInfo));
679 break;
680 }
681 case BDSArrayReflectionType::reflectzsolenoid:
682 {
683 indexOperators.emplace_back(new BDSArrayOperatorIndexReflect({false, false, true, false}, arrayInfo));
684 valueOperators.emplace_back(new BDSArrayOperatorValueReflectSolenoidZ());
685 break;
686 }
687 case BDSArrayReflectionType::reflectxyquadrupole:
688 {
689 indexOperators.emplace_back(new BDSArrayOperatorIndexReflect({true, true, false, false}, arrayInfo));
690 valueOperators.emplace_back(new BDSArrayOperatorValueReflectQuadrupoleXY());
691 break;
692 }
693 default:
694 {break;}
695 }
696 }
697
698 if (indexOperators.size() > 1)
699 {
700 auto indexResult = new BDSArrayOperatorIndexV();
701 for (auto io : indexOperators)
702 {indexResult->push_back(io);}
703 auto valueResult = new BDSArrayOperatorValueV();
704 for (auto vo : valueOperators)
705 {valueResult->push_back(vo);}
706 indexOperator = indexResult;
707 valueOperator = valueResult;
708 }
709 else
710 {
711 indexOperator = indexOperators[0];
712 valueOperator = valueOperators[0];
713 }
714
715 ReportIfProblemWithReflection(arrayInfo, indexOperator->OperatesOnXYZT());
716
717 G4cout << "Array ( index | value ) operator: (" << indexOperator->Name() << " | " << valueOperator->Name() << ")" << G4endl;
718}
719
721 const std::array<G4bool, 4>& operatesOnXYZT,
722 G4double tolerance) const
723{
724 G4String suffix[4] = {"st", "nd", "rd", "th"};
725 for (G4int i = 0; i < 4; i++)
726 {
727 G4double integerPart = 0;
728 if ( (std::modf(std::abs(info.zeroPoint[i]), &integerPart) > tolerance) && operatesOnXYZT[i])
729 {
730 G4String msg = "Array reflection will not work as intended as the axis zero point is not an integer number of \n";
731 msg += "array steps from 0 in the " + std::to_string(i + 1) + suffix[i];
732 msg += " dimension of the array (tolerance 5% of array step size)";
733 BDS::Warning(msg);
734 }
735 }
736}
737
738G4bool BDSFieldLoader::NeedToProvideTransform(const BDSArrayReflectionTypeSet* reflectionTypes) const
739{
740 if (!reflectionTypes)
741 {return false;}
742 else
743 {
744 if (reflectionTypes->empty())
745 {return false;}
746 else
747 {return true;}
748 }
749}
750
751BDSArray1DCoords* BDSFieldLoader::CreateArrayReflected(BDSArray1DCoords* existingArray,
752 const BDSArrayReflectionTypeSet* reflectionTypes) const
753{
754 if (!NeedToProvideTransform(reflectionTypes))
755 {return existingArray;}
756
757 BDSArrayOperatorIndex* indexOperator = nullptr;
758 BDSArrayOperatorValue* valueOperator = nullptr;
759 CreateOperators(reflectionTypes, existingArray, indexOperator, valueOperator);
760 BDSArray1DCoords* result = new BDSArray1DCoordsTransformed(existingArray, indexOperator, valueOperator);
761 return result;
762}
763
764BDSArray2DCoords* BDSFieldLoader::CreateArrayReflected(BDSArray2DCoords* existingArray,
765 const BDSArrayReflectionTypeSet* reflectionTypes) const
766{
767 if (!NeedToProvideTransform(reflectionTypes))
768 {return existingArray;}
769
770 BDSArrayOperatorIndex* indexOperator = nullptr;
771 BDSArrayOperatorValue* valueOperator = nullptr;
772 CreateOperators(reflectionTypes, existingArray, indexOperator, valueOperator);
773 BDSArray2DCoords* result = new BDSArray2DCoordsTransformed(existingArray, indexOperator, valueOperator);
774 return result;
775}
776
777BDSArray3DCoords* BDSFieldLoader::CreateArrayReflected(BDSArray3DCoords* existingArray,
778 const BDSArrayReflectionTypeSet* reflectionTypes) const
779{
780 if (!NeedToProvideTransform(reflectionTypes))
781 {return existingArray;}
782
783 BDSArrayOperatorIndex* indexOperator = nullptr;
784 BDSArrayOperatorValue* valueOperator = nullptr;
785 CreateOperators(reflectionTypes, existingArray, indexOperator, valueOperator);
786 BDSArray3DCoords* result = new BDSArray3DCoordsTransformed(existingArray, indexOperator, valueOperator);
787 return result;
788}
789
790BDSArray4DCoords* BDSFieldLoader::CreateArrayReflected(BDSArray4DCoords* existingArray,
791 const BDSArrayReflectionTypeSet* reflectionTypes) const
792{
793 if (!NeedToProvideTransform(reflectionTypes))
794 {return existingArray;}
795
796 BDSArrayOperatorIndex* indexOperator = nullptr;
797 BDSArrayOperatorValue* valueOperator = nullptr;
798 CreateOperators(reflectionTypes, existingArray, indexOperator, valueOperator);
799 BDSArray4DCoords* result = new BDSArray4DCoordsTransformed(existingArray, indexOperator, valueOperator);
800 return result;
801}
802
804 BDSInterpolatorType interpolatorType,
805 const G4Transform3D& transform,
806 G4double bScaling,
807 const BDSArrayReflectionTypeSet* reflection)
808
809{
810 G4double bScalingUnits = bScaling * CLHEP::tesla;
811 BDSArray1DCoords* array = LoadBDSIM1D(filePath);
812 BDSArray1DCoords* arrayR = CreateArrayReflected(array, reflection);
813 BDSInterpolator1D* ar = CreateInterpolator1D(arrayR, interpolatorType);
814 BDSFieldMagInterpolated* result = new BDSFieldMagInterpolated1D(ar, transform, bScalingUnits);
815 return result;
816}
817
819 BDSInterpolatorType interpolatorType,
820 const G4Transform3D& transform,
821 G4double bScaling,
822 const BDSArrayReflectionTypeSet* reflection)
823{
824 G4double bScalingUnits = bScaling * CLHEP::tesla;
825 BDSArray2DCoords* array = LoadBDSIM2D(filePath);
826 BDSArray2DCoords* arrayR = CreateArrayReflected(array, reflection);
827 BDSInterpolator2D* ar = CreateInterpolator2D(arrayR, interpolatorType);
828 BDSFieldMagInterpolated* result = new BDSFieldMagInterpolated2D(ar, transform, bScalingUnits);
829 return result;
830}
831
833 BDSInterpolatorType interpolatorType,
834 const G4Transform3D& transform,
835 G4double bScaling,
836 const BDSArrayReflectionTypeSet* reflection)
837{
838 G4double bScalingUnits = bScaling * CLHEP::tesla;
839 BDSArray3DCoords* array = LoadBDSIM3D(filePath);
840 BDSArray3DCoords* arrayR = CreateArrayReflected(array, reflection);
841 BDSInterpolator3D* ar = CreateInterpolator3D(arrayR, interpolatorType);
842 BDSFieldMagInterpolated* result = new BDSFieldMagInterpolated3D(ar, transform, bScalingUnits);
843 return result;
844}
845
847 BDSInterpolatorType interpolatorType,
848 const G4Transform3D& transform,
849 G4double bScaling,
850 const BDSArrayReflectionTypeSet* reflection)
851{
852 G4double bScalingUnits = bScaling * CLHEP::tesla;
853 BDSArray4DCoords* array = LoadBDSIM4D(filePath);
854 BDSArray4DCoords* arrayR = CreateArrayReflected(array, reflection);
855 BDSInterpolator4D* ar = CreateInterpolator4D(arrayR, interpolatorType);
856 BDSFieldMagInterpolated* result = new BDSFieldMagInterpolated4D(ar, transform, bScalingUnits);
857 return result;
858}
859
861 BDSInterpolatorType interpolatorType,
862 const G4Transform3D& transform,
863 G4double bScaling,
864 const BDSArrayReflectionTypeSet* reflection)
865{
866 G4double bScalingUnits = bScaling * CLHEP::gauss;
867 BDSArray2DCoords* array = LoadPoissonMag2D(filePath);
868 BDSArray2DCoords* arrayR = CreateArrayReflected(array, reflection);
869 BDSInterpolator2D* ar = CreateInterpolator2D(arrayR, interpolatorType);
870 BDSFieldMagInterpolated* result = new BDSFieldMagInterpolated2D(ar, transform, bScalingUnits);
871 return result;
872}
873
875 BDSInterpolatorType interpolatorType,
876 const G4Transform3D& transform,
877 G4double bScaling,
878 const BDSArrayReflectionTypeSet* /*reflection*/)
879{
880 G4double bScalingUnits = bScaling * CLHEP::gauss;
881 BDSArray2DCoords* array = LoadPoissonMag2D(filePath);
882 //BDSArray2DCoords* arrayR = CreateArrayReflected(array, reflection);
883 if (std::abs(array->XStep() - array->YStep()) > 1e-9)
884 {throw BDSException(__METHOD_NAME__, "asymmetric grid spacing for reflected quadrupole will result in a distorted field map - please regenerate the map with even spatial samples.");}
885 BDSArray2DCoordsRQuad* rArray = new BDSArray2DCoordsRQuad(array);
886 BDSInterpolator2D* ar = CreateInterpolator2D(rArray, interpolatorType);
887 BDSFieldMagInterpolated* result = new BDSFieldMagInterpolated2D(ar, transform, bScalingUnits);
888 return result;
889}
890
892 BDSInterpolatorType interpolatorType,
893 const G4Transform3D& transform,
894 G4double bScaling,
895 const BDSArrayReflectionTypeSet* /*reflection*/)
896{
897 G4double bScalingUnits = bScaling * CLHEP::gauss;
898 BDSArray2DCoords* array = LoadPoissonMag2D(filePath);
899 //BDSArray2DCoords* arrayR = CreateArrayReflected(array, reflection);
901 BDSInterpolator2D* ar = CreateInterpolator2D(rArray, interpolatorType);
902 BDSFieldMagInterpolated* result = new BDSFieldMagInterpolated2D(ar, transform, bScalingUnits);
903 return result;
904}
905
907 BDSInterpolatorType interpolatorType,
908 const G4Transform3D& transform,
909 G4double eScaling,
910 const BDSArrayReflectionTypeSet* reflection)
911{
912 G4double eScalingUnits = eScaling * CLHEP::volt/CLHEP::m;
913 BDSArray1DCoords* array = LoadBDSIM1D(filePath);
914 BDSArray1DCoords* arrayR = CreateArrayReflected(array, reflection);
915 BDSInterpolator1D* ar = CreateInterpolator1D(arrayR, interpolatorType);
916 BDSFieldEInterpolated* result = new BDSFieldEInterpolated1D(ar, transform, eScalingUnits);
917 return result;
918}
919
921 BDSInterpolatorType interpolatorType,
922 const G4Transform3D& transform,
923 G4double eScaling,
924 const BDSArrayReflectionTypeSet* reflection)
925{
926 G4double eScalingUnits = eScaling * CLHEP::volt/CLHEP::m;
927 BDSArray2DCoords* array = LoadBDSIM2D(filePath);
928 BDSArray2DCoords* arrayR = CreateArrayReflected(array, reflection);
929 BDSInterpolator2D* ar = CreateInterpolator2D(arrayR, interpolatorType);
930 BDSFieldEInterpolated* result = new BDSFieldEInterpolated2D(ar, transform, eScalingUnits);
931 return result;
932}
933
935 BDSInterpolatorType interpolatorType,
936 const G4Transform3D& transform,
937 G4double eScaling,
938 const BDSArrayReflectionTypeSet* reflection)
939{
940 G4double eScalingUnits = eScaling * CLHEP::volt/CLHEP::m;
941 BDSArray3DCoords* array = LoadBDSIM3D(filePath);
942 BDSArray3DCoords* arrayR = CreateArrayReflected(array, reflection);
943 BDSInterpolator3D* ar = CreateInterpolator3D(arrayR, interpolatorType);
944 BDSFieldEInterpolated* result = new BDSFieldEInterpolated3D(ar, transform, eScalingUnits);
945 return result;
946}
947
949 BDSInterpolatorType interpolatorType,
950 const G4Transform3D& transform,
951 G4double eScaling,
952 const BDSArrayReflectionTypeSet* reflection)
953{
954 G4double eScalingUnits = eScaling * CLHEP::volt/CLHEP::m;
955 BDSArray4DCoords* array = LoadBDSIM4D(filePath);
956 BDSArray4DCoords* arrayR = CreateArrayReflected(array, reflection);
957 BDSInterpolator4D* ar = CreateInterpolator4D(arrayR, interpolatorType);
958 BDSFieldEInterpolated* result = new BDSFieldEInterpolated4D(ar, transform, eScalingUnits);
959 return result;
960}
961
963 const G4String& bFilePath,
964 BDSInterpolatorType eInterpolatorType,
965 BDSInterpolatorType bInterpolatorType,
966 const G4Transform3D& transform,
967 G4double eScaling,
968 G4double bScaling,
969 const BDSArrayReflectionTypeSet* eReflection,
970 const BDSArrayReflectionTypeSet* bReflection)
971{
972 G4double eScalingUnits = eScaling * CLHEP::volt / CLHEP::m;
973 G4double bScalingUnits = bScaling * CLHEP::tesla;
974 BDSArray1DCoords* eArray = LoadBDSIM1D(eFilePath);
975 BDSArray1DCoords* bArray = LoadBDSIM1D(bFilePath);
976 BDSArray1DCoords* eArrayR = CreateArrayReflected(eArray, eReflection);
977 BDSArray1DCoords* bArrayR = CreateArrayReflected(bArray, bReflection);
978 BDSInterpolator1D* eInt = CreateInterpolator1D(eArrayR, eInterpolatorType);
979 BDSInterpolator1D* bInt = CreateInterpolator1D(bArrayR, bInterpolatorType);
980 BDSFieldEMInterpolated* result = new BDSFieldEMInterpolated1D(eInt, bInt, transform,
981 eScalingUnits, bScalingUnits);
982 return result;
983}
984
986 const G4String& bFilePath,
987 BDSInterpolatorType eInterpolatorType,
988 BDSInterpolatorType bInterpolatorType,
989 const G4Transform3D& transform,
990 G4double eScaling,
991 G4double bScaling,
992 const BDSArrayReflectionTypeSet* eReflection,
993 const BDSArrayReflectionTypeSet* bReflection)
994{
995 G4double eScalingUnits = eScaling * CLHEP::volt / CLHEP::m;
996 G4double bScalingUnits = bScaling * CLHEP::tesla;
997 BDSArray2DCoords* eArray = LoadBDSIM2D(eFilePath);
998 BDSArray2DCoords* bArray = LoadBDSIM2D(bFilePath);
999 BDSArray2DCoords* eArrayR = CreateArrayReflected(eArray, eReflection);
1000 BDSArray2DCoords* bArrayR = CreateArrayReflected(bArray, bReflection);
1001 BDSInterpolator2D* eInt = CreateInterpolator2D(eArrayR, eInterpolatorType);
1002 BDSInterpolator2D* bInt = CreateInterpolator2D(bArrayR, bInterpolatorType);
1003 BDSFieldEMInterpolated* result = new BDSFieldEMInterpolated2D(eInt, bInt, transform,
1004 eScalingUnits, bScalingUnits);
1005 return result;
1006}
1007
1009 const G4String& bFilePath,
1010 BDSInterpolatorType eInterpolatorType,
1011 BDSInterpolatorType bInterpolatorType,
1012 const G4Transform3D& transform,
1013 G4double eScaling,
1014 G4double bScaling,
1015 const BDSArrayReflectionTypeSet* eReflection,
1016 const BDSArrayReflectionTypeSet* bReflection)
1017{
1018 G4double eScalingUnits = eScaling * CLHEP::volt / CLHEP::m;
1019 G4double bScalingUnits = bScaling * CLHEP::tesla;
1020 BDSArray3DCoords* eArray = LoadBDSIM3D(eFilePath);
1021 BDSArray3DCoords* bArray = LoadBDSIM3D(bFilePath);
1022 BDSArray3DCoords* eArrayR = CreateArrayReflected(eArray, eReflection);
1023 BDSArray3DCoords* bArrayR = CreateArrayReflected(bArray, bReflection);
1024 BDSInterpolator3D* eInt = CreateInterpolator3D(eArrayR, eInterpolatorType);
1025 BDSInterpolator3D* bInt = CreateInterpolator3D(bArrayR, bInterpolatorType);
1026 BDSFieldEMInterpolated* result = new BDSFieldEMInterpolated3D(eInt, bInt, transform,
1027 eScalingUnits, bScalingUnits);
1028 return result;
1029}
1030
1032 const G4String& bFilePath,
1033 BDSInterpolatorType eInterpolatorType,
1034 BDSInterpolatorType bInterpolatorType,
1035 const G4Transform3D& transform,
1036 G4double eScaling,
1037 G4double bScaling,
1038 const BDSArrayReflectionTypeSet* eReflection,
1039 const BDSArrayReflectionTypeSet* bReflection)
1040{
1041 G4double eScalingUnits = eScaling * CLHEP::volt / CLHEP::m;
1042 G4double bScalingUnits = bScaling * CLHEP::tesla;
1043 BDSArray4DCoords* eArray = LoadBDSIM4D(eFilePath);
1044 BDSArray4DCoords* bArray = LoadBDSIM4D(bFilePath);
1045 BDSArray4DCoords* eArrayR = CreateArrayReflected(eArray, eReflection);
1046 BDSArray4DCoords* bArrayR = CreateArrayReflected(bArray, bReflection);
1047 BDSInterpolator4D* eInt = CreateInterpolator4D(eArrayR, eInterpolatorType);
1048 BDSInterpolator4D* bInt = CreateInterpolator4D(bArrayR, bInterpolatorType);
1049 BDSFieldEMInterpolated* result = new BDSFieldEMInterpolated4D(eInt, bInt, transform,
1050 eScalingUnits, bScalingUnits);
1051 return result;
1052}
Wrapped BDSArray1DCoords with possible transformation to extend field.
1D array with spatial mapping derived from BDSArray4DCoords.
A wrapper to achieve 2D reflection of a minimal dipole field solve.
A wrapper to achieve 2D reflection of a minimal quadrupole field solve.
Wrapped BDSArray2DCoords with possible transformation to extend field.
2D array with spatial mapping derived from BDSArray4DCoords.
Wrapped BDSArray3DCoords with possible transformation to extend field.
3D array with spatial mapping derived from BDSArray4DCoords.
Wrapped BDSArray4DCoords with possible transformation to extend field.
Overlay of 4D array that provides uniform only spatial coordinate mapping.
G4double XStep() const
The distance in spatial coordinates between any two points in the array.
G4double YStep() const
The distance in spatial coordinates between any two points in the array.
G4int DimensionIndex(BDSDimensionType spatialDimension) const
Simple holder of information about an array.
1D array for completeness in array system.
1D array for completeness in array system.
Vectorised version of BDSArrayOperatorIndex.
Interface for modifying by reference array indices.
virtual G4String Name() const
Supply a name of this operator for feedback to the user in print out.
virtual std::array< G4bool, 4 > OperatesOnXYZT() const
Return which axes this object operates on overall.
Flip field component in individual dimensions if out of original array bounds.
Reflect field values for a dipolar field in the positive quadrant.
Reflect field values for a dipolar field about the x-z plane.
Reflect field values for a quadrupole field in the positive quadrant.
Reflect field values for a solenoid-like field in the z axis.
Reflect field component in individual dimensions.
A vectorised version of BDSArrayOperatorValueV.
Interface for modifying field values.
virtual G4String Name() const
Return a name of the operator for feedback to the user in print out.
General exception with possible name of object and message.
A 1D field from an interpolated array with any interpolation.
A 2D field from an interpolated array with any interpolation.
A 3D field from an interpolated array with any interpolation.
A 4D field from an interpolated array with any interpolation.
Class to provide scaling and a base class pointer for interpolator fields.
A 1D field from an interpolated array with any interpolation.
A 2D field from an interpolated array with any interpolation.
A 3D field from an interpolated array with any interpolation.
A 4D field from an interpolated array with any interpolation.
Class to provide scaling and a base class pointer for interpolator fields.
All info required to build complete field of any type.
G4double BScaling() const
Accessor.
const BDSArrayReflectionTypeSet & ElectricArrayReflectionType() const
Accessor.
BDSFieldFormat MagneticFormat() const
Accessor.
G4String NameOfParserDefinition() const
Accessor.
G4String ElectricFile() const
Accessor.
BDSInterpolatorType ElectricInterpolatorType() const
Accessor.
BDSInterpolatorType MagneticInterpolatorType() const
Accessor.
G4double EScaling() const
Accessor.
G4String MagneticFile() const
Accessor.
G4Transform3D Transform() const
Transform for the field definition only.
BDSFieldFormat ElectricFormat() const
Accessor.
const BDSArrayReflectionTypeSet & MagneticArrayReflectionType() const
Accessor.
G4double BRho() const
Accessor.
G4bool AutoScale() const
Accessor.
Loader for BDSIM format fields.
BDSArray3DCoords * Load3D(const G4String &fileName)
Load a 3D array.
BDSArray4DCoords * Load4D(const G4String &fileName)
Load a 4D array.
BDSArray1DCoords * Load1D(const G4String &fileName)
Load a 1D array.
BDSArray2DCoords * Load2D(const G4String &fileName)
Load a 2D array.
Loader for 2D Poisson SuperFish SF7 files.
BDSArray2DCoords * LoadMag2D(G4String fileName)
Load the 2D array of 3-Vector field values.
A loader for various field map formats.
BDSFieldEInterpolated * LoadBDSIM3DE(const G4String &filePath, BDSInterpolatorType interpolatorType, const G4Transform3D &transform, G4double eScaling, const BDSArrayReflectionTypeSet *reflection=nullptr)
Load a 3D BDSIM format electric field.
static void EFilePathOK(const BDSFieldInfo &info)
Check file path isn't empty and throw exception if it is.
BDSFieldEMInterpolated * LoadBDSIM3DEM(const G4String &eFilePath, const G4String &bFilePath, BDSInterpolatorType eInterpolatorType, BDSInterpolatorType bInterpolatorType, const G4Transform3D &transform, G4double eScaling, G4double bScaling, const BDSArrayReflectionTypeSet *eReflection=nullptr, const BDSArrayReflectionTypeSet *bReflection=nullptr)
Load a 3D BDSIM format electro-magnetic field.
BDSInterpolator3D * CreateInterpolator3D(BDSArray3DCoords *array, BDSInterpolatorType interpolatorType) const
Create the appropriate 3D interpolator for an array.
std::map< G4String, BDSArray1DCoords * > arrays1d
Map of cached field map array.
BDSFieldEMInterpolated * LoadBDSIM4DEM(const G4String &eFilePath, const G4String &bFilePath, BDSInterpolatorType eInterpolatorType, BDSInterpolatorType bInterpolatorType, const G4Transform3D &transform, G4double eScaling, G4double bScaling, const BDSArrayReflectionTypeSet *eReflection=nullptr, const BDSArrayReflectionTypeSet *bReflection=nullptr)
Load a 4D BDSIM format electro-magnetic field.
std::map< G4String, BDSArray2DCoords * > arrays2d
Map of cached field map array.
BDSArray2DCoords * LoadPoissonMag2D(const G4String &filePath)
Utility function to use the right templated loader class (gz or normal).
BDSArray3DCoords * Get3DCached(const G4String &filePath)
Return the cached array if there is one - may return nullptr.
BDSArray2DCoords * LoadBDSIM2D(const G4String &filePath)
Utility function to use the right templated loader class (gz or normal).
BDSFieldEMInterpolated * LoadEMField(const BDSFieldInfo &info)
Main interface to load an electro-magnetic field.
BDSInterpolator1D * CreateInterpolator1D(BDSArray1DCoords *array, BDSInterpolatorType interpolatorType) const
Create the appropriate 1D interpolator for an array.
BDSFieldEInterpolated * LoadBDSIM2DE(const G4String &filePath, BDSInterpolatorType interpolatorType, const G4Transform3D &transform, G4double eScaling, const BDSArrayReflectionTypeSet *reflection=nullptr)
Load a 2D BDSIM format electric field.
std::map< G4String, BDSArray3DCoords * > arrays3d
Map of cached field map array.
void ReportIfProblemWithReflection(const BDSArrayInfo &info, const std::array< G4bool, 4 > &operatesOnXYZT, G4double tolerance=0.05) const
BDSInterpolator2D * CreateInterpolator2D(BDSArray2DCoords *array, BDSInterpolatorType interpolatorType) const
Create the appropriate 2D interpolator for an array.
BDSFieldEInterpolated * LoadBDSIM4DE(const G4String &filePath, BDSInterpolatorType interpolatorType, const G4Transform3D &transform, G4double eScaling, const BDSArrayReflectionTypeSet *reflection=nullptr)
Load a 4D BDSIM format electric field.
BDSFieldMagInterpolated * LoadPoissonSuperFishB(const G4String &filePath, BDSInterpolatorType interpolatorType, const G4Transform3D &transform, G4double bScaling, const BDSArrayReflectionTypeSet *reflection=nullptr)
Load a 2D poisson superfish B field map.
BDSFieldLoader()
Private default constructor as singleton.
BDSFieldMagInterpolated * LoadPoissonSuperFishBQuad(const G4String &filePath, BDSInterpolatorType interpolatorType, const G4Transform3D &transform, G4double bScaling, const BDSArrayReflectionTypeSet *reflection=nullptr)
BDSArray1DCoords * Get1DCached(const G4String &filePath)
Return the cached array if there is one - may return nullptr.
BDSFieldMagInterpolated * LoadBDSIM1DB(const G4String &filePath, BDSInterpolatorType interpolatorType, const G4Transform3D &transform, G4double bScaling, const BDSArrayReflectionTypeSet *reflection=nullptr)
Load a 1D BDSIM format magnetic field.
BDSFieldEMInterpolated * LoadBDSIM1DEM(const G4String &eFilePath, const G4String &bFilePath, BDSInterpolatorType eInterpolatorType, BDSInterpolatorType bInterpolatorType, const G4Transform3D &transform, G4double eScaling, G4double bScaling, const BDSArrayReflectionTypeSet *eReflection=nullptr, const BDSArrayReflectionTypeSet *bReflection=nullptr)
Load a 1D BDSIM format electro-magnetic field.
BDSArray3DCoords * LoadBDSIM3D(const G4String &filePath)
Utility function to use the right templated loader class (gz or normal).
BDSFieldMagInterpolated * LoadBDSIM4DB(const G4String &filePath, BDSInterpolatorType interpolatorType, const G4Transform3D &transform, G4double bScaling, const BDSArrayReflectionTypeSet *reflection=nullptr)
Load a 4D BDSIM format magnetic field.
BDSFieldMagInterpolated * LoadBDSIM2DB(const G4String &filePath, BDSInterpolatorType interpolatorType, const G4Transform3D &transform, G4double bScaling, const BDSArrayReflectionTypeSet *reflection=nullptr)
Load a 2D BDSIM format magnetic field.
BDSFieldMagInterpolated * LoadMagField(const BDSFieldInfo &info, const BDSMagnetStrength *scalingStrength=nullptr, const G4String &scalingKey="none")
Main interface to load a magnetic field.
static BDSFieldLoader * instance
Singleton instance.
static BDSFieldLoader * Instance()
Singleton accessor.
BDSFieldEMInterpolated * LoadBDSIM2DEM(const G4String &eFilePath, const G4String &bFilePath, BDSInterpolatorType eInterpolatorType, BDSInterpolatorType bInterpolatorType, const G4Transform3D &transform, G4double eScaling, G4double bScaling, const BDSArrayReflectionTypeSet *eReflection=nullptr, const BDSArrayReflectionTypeSet *bReflection=nullptr)
Load a 2D BDSIM format electro-magnetic field.
BDSArray4DCoords * Get4DCached(const G4String &filePath)
Return the cached array if there is one - may return nullptr.
BDSFieldMagInterpolated * LoadPoissonSuperFishBDipole(const G4String &filePath, BDSInterpolatorType interpolatorType, const G4Transform3D &transform, G4double bScaling, const BDSArrayReflectionTypeSet *reflection=nullptr)
BDSInterpolator4D * CreateInterpolator4D(BDSArray4DCoords *array, BDSInterpolatorType interpolatorType) const
Create the appropriate 4D interpolator for an array.
BDSFieldMagInterpolated * LoadBDSIM3DB(const G4String &filePath, BDSInterpolatorType interpolatorType, const G4Transform3D &transform, G4double bScaling, const BDSArrayReflectionTypeSet *reflection=nullptr)
Load a 3D BDSIM format magnetic field.
BDSFieldEInterpolated * LoadEField(const BDSFieldInfo &info)
Main interface to load an electric field.
G4bool NeedToProvideTransform(const BDSArrayReflectionTypeSet *reflectionTypes) const
BDSFieldEInterpolated * LoadBDSIM1DE(const G4String &filePath, BDSInterpolatorType interpolatorType, const G4Transform3D &transform, G4double eScaling, const BDSArrayReflectionTypeSet *reflection=nullptr)
Load a 1D BDSIM format electric field.
void CreateOperators(const BDSArrayReflectionTypeSet *reflectionTypes, const BDSArray4DCoords *existingArray, BDSArrayOperatorIndex *&indexOperator, BDSArrayOperatorValue *&valueOperator) const
static void BFilePathOK(const BDSFieldInfo &info)
Check file path isn't empty and throw exception if it is.
BDSArray1DCoords * LoadBDSIM1D(const G4String &filePath)
Utility function to use the right templated loader class (gz or normal).
BDSArray4DCoords * LoadBDSIM4D(const G4String &filePath)
Utility function to use the right templated loader class (gz or normal).
std::map< G4String, BDSArray4DCoords * > arrays4d
Map of cached field map array.
BDSArray2DCoords * Get2DCached(const G4String &filePath)
Return the cached array if there is one - may return nullptr.
Find multipole components of fieldmaps by numerical differentiation.
BDSMagnetStrength * CalculateMultipoles(BDSFieldMag *BField, G4int order, G4double Brho=4)
Find the Magnet strengths of a multipole field to nth order.
A 1D field from an interpolated array with any interpolation.
A 2D field from an interpolated array with any interpolation.
A 3D field from an interpolated array with any interpolation.
A 4D field from an interpolated array with any interpolation.
Class to provide scaling and a base class pointer for interpolator fields.
Cubic interpolation over 1d array.
Linear interpolation over 1d array including magnitude interpolation.
Linear interpolation over 1d array.
Interpolated field array that gives the nearest neighbour value.
Interface for all 1D interpolators.
Cubic interpolation over 2d array.
Linear interpolation over 2d array including magnitude interpolation.
Linear interpolation over 2d array.
Interpolated field array that gives the nearest neighbour value.
Interface for all 2D interpolators.
Cubic interpolation over 3d array.
Linear interpolation over 3d array including magnitude interpolation.
Linear interpolation over 3d array.
Interpolated field array that gives the nearest neighbour value.
Interface for all 3D interpolators.
Cubic interpolation over 4d array.
Linear interpolation over 4d array including magnitude interpolation.
Linear interpolation over 4d array.
Interpolated field array that gives the nearest neighbour value.
Interface for all 4D interpolators.
Efficient storage of magnet strengths.
type underlying() const
return underlying value (can be used in switch statement)
BDSInterpolatorType InterpolatorTypeSpecificFromAuto(G4int nDimension, BDSInterpolatorType autoType)
G4bool ProblemWithArrayReflectionCombination(const BDSArrayReflectionTypeSet &setIn, G4String *details=nullptr)
Return true if there's a conceptual conflict with the set of field reflections requested.
G4int NDimensionsOfFieldFormat(const BDSFieldFormat &ff)
Report the number of dimensions for that format.