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