BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSFieldLoaderPoisson.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 "BDSArray2DCoords.hh"
19#include "BDSDebug.hh"
20#include "BDSException.hh"
21#include "BDSFieldLoaderPoisson.hh"
22#include "BDSFieldValue.hh"
23
24#include "globals.hh" // geant4 types / globals
25
26#include "CLHEP/Units/SystemOfUnits.h"
27
28#include <algorithm>
29#include <fstream>
30#include <iostream>
31#include <regex>
32#include <sstream>
33#include <string>
34#include <vector>
35
36#ifdef USE_GZSTREAM
37#include "src-external/gzstream/gzstream.h"
38#endif
39
40template <class T>
42{;}
43
44template <class T>
46{;}
47
48template <class T>
50{
51 file.open(fileName);
52
53 // test if file is valid
54#ifdef USE_GZSTREAM
55 bool validFile = file.rdbuf()->is_open();
56#else
57 bool validFile = file.is_open();
58#endif
59 if (!validFile)
60 {throw BDSException(__METHOD_NAME__, "Invalid file name or no such file named \"" + fileName + "\"");}
61 else
62 {G4cout << "Loading \"" << fileName << "\"" << G4endl;}
63
64 // Pointer to where result will be stored. Can't be constructed until we know
65 // the dimensions.
66 BDSArray2DCoords* result = nullptr;
67 G4int nX = 1;
68 G4int nY = 1;
69 G4double xMin = 0;
70 G4double yMin = 0;
71 G4double xMax = 0;
72 G4double yMax = 0;
73 G4int nColumns = 0;
74 std::vector<G4String> keys;
75 std::vector<G4String> units;
76
77 // temporary variables
78 G4bool intoData = false;
79 G4bool pastNStep = false;
80 G4bool dataFinished = false;
81 std::string line;
82 G4int indX = 0;
83 G4int indY = 0;
84
85 while (std::getline(file, line))
86 {// read a line only if it's not a blank one
87
88 // Skip a line if it's only whitespace
89 if (std::all_of(line.begin(), line.end(), isspace))
90 {continue;}
91
92 if (intoData)
93 {
94 if (dataFinished)
95 {continue;} // just keep skipping lines after the appropriate amount of data is loaded
96
97 // General data entry
98 std::istringstream liness(line);
99 G4double value = 0;
100 std::vector<G4float> lineData(nColumns); // reserve to avoid copying as it expands
101 for (G4int i = 0; i < nColumns; ++i)
102 {
103 liness >> value;
104 lineData[i] = value;
105 }
106 // Construct field value
107 BDSFieldValue fv = BDSFieldValue(lineData[2], lineData[3], 0);
108 // we could use the gradients here, but we don't
109
110 // Copy into array.
111 (*result)(indX,indY) = fv;
112
113 indX++;
114 if (indX == nX)
115 {// we've completed one set of x
116 indX = 0;
117 indY++;
118 }
119 if (indY == nY)
120 {// we've completed one set of y
121 indY = 0;
122 dataFinished = true;
123 }
124
125 continue;
126 }
127
128 // else try and parser what must be header bits.
129
130 // Min
131 std::regex min("^.*?\\(Xmin,Ymin\\)\\s*=\\s*", std::regex_constants::icase);
132 if (std::regex_search(line, min))
133 {// found line beginning with '(Xmin,YMin)'
134 std::regex minValues("\\(([0-9eE.+-]+),([0-9eE.+-]+)\\)");
135 std::smatch match;
136 std::regex_search(line, match, minValues);
137 xMin = std::stod(match[1])*CLHEP::cm;
138 yMin = std::stod(match[2])*CLHEP::cm;
139 continue;
140 }
141
142 // Max
143 std::regex max("^.*?\\(Xmax,Ymax\\)\\s*=\\s*", std::regex_constants::icase);
144 if (std::regex_search(line, max))
145 {// found line beginning with '(Xmax,YMax)'
146 std::regex maxValues("\\(([0-9eE.+-]+),([0-9eE.+-]+)\\)");
147 std::smatch match;
148 std::regex_search(line, match, maxValues);
149 xMax = std::stod(match[1])*CLHEP::cm;
150 yMax = std::stod(match[2])*CLHEP::cm;
151 continue;
152 }
153
154 // Steps
155 std::regex incr("\\s*X\\s*and\\s*Y", std::regex_constants::icase);
156 if (std::regex_search(line, incr))
157 {//found line for number of increments
158 std::regex nStepValues(":\\s*([0-9eE.+-]+)\\s*([0-9eE.+-]+)");
159 std::smatch match;
160 std::regex_search(line, match, nStepValues);
161 nX = std::stoi(match[1]) + 1;
162 nY = std::stoi(match[2]) + 1; // number of increments, so number of points is +1
163 pastNStep = true;
164 continue;
165 }
166
167 // Columns
168 std::regex noNumbers("^(\\D)*$");
169 G4bool noNumbersR = std::regex_search(line, noNumbers);
170 G4bool hasParenthesis = (line.find("(") != std::string::npos) || (line.find(")") != std::string::npos);
171 G4bool hasNoParenthesis = !hasParenthesis;
172 if (pastNStep && noNumbersR && hasNoParenthesis)
173 {
174 std::istringstream liness(line);
175 for (G4String key; liness >> key;)
176 {keys.push_back(key);}
177 nColumns = G4int(std::distance(keys.begin(), keys.end()));
178 continue;
179 }
180
181 // Units
182 if (pastNStep && noNumbersR && hasParenthesis)
183 {
184 // match text inside (XXX) parenthesis, ie strip them off
185 std::regex unitsRE("[\\(](\\w+\\-*\\/*\\w*)[\\)]");
186 std::smatch match;
187 std::regex_search(line, match, unitsRE);
188 for (const auto& u : match)
189 {units.push_back(G4String(u));}
190 result = new BDSArray2DCoords(nX, nY, xMin, xMax, yMin, yMax);
191 intoData = true;
192 }
193 //nothing heap allocated so safe to let all go out of scope
194 }
195
196 file.close();
197
198 if (!result)
199 {throw BDSException(__METHOD_NAME__, "Invalid file contents - no column header found");}
200
201 return result;
202}
203
204
206
207#ifdef USE_GZSTREAM
209#endif
2D array with spatial mapping derived from BDSArray4DCoords.
General exception with possible name of object and message.
Loader for 2D Poisson SuperFish SF7 files.
BDSArray2DCoords * LoadMag2D(G4String fileName)
Load the 2D array of 3-Vector field values.