20#include "gtest/gtest.h"
32 char** argv =
nullptr;
33 ippl::initialize(argc, argv);
34 gmsg =
new Inform(
nullptr, -1);
36 std::filesystem::create_directories(
"data");
46 const auto* info = ::testing::UnitTest::GetInstance()->current_test_info();
47 testStem_ = std::string(
"solenoid_") + info->name();
77 std::shared_ptr<PartBunch_t>
makeBunch(
const size_t numParticles) {
79 const auto fsCmd = std::make_shared<TestableFieldSolverCmd>();
81 fsCmd->setType(
"NONE");
85 fsCmd->setBCX(
"PERIODIC");
86 fsCmd->setBCY(
"PERIODIC");
87 fsCmd->setBCZ(
"PERIODIC");
89 auto beam = std::make_shared<Beam>();
91 EXPECT_NE(opBeam,
nullptr);
93 auto bunch = std::make_shared<PartBunch_t>(
94 std::vector{1.0}, std::vector{1.0},
95 std::vector<Beam*>{opBeam},
96 std::vector<size_t>{numParticles},
98 bunch->getParticleContainer()->createParticles(numParticles);
103 const std::string& filename,
double zBeginCm,
double zEndCm,
int nz,
double rBeginCm,
104 double rEndCm,
int nr,
double bzValue = 1.0,
double brValue = 0.0) {
107 out <<
"2DMagnetoStatic XZ\n";
108 out << zBeginCm <<
" " << zEndCm <<
" " << nz - 1 <<
"\n";
109 out << rBeginCm <<
" " << rEndCm <<
" " <<
nr - 1 <<
"\n";
110 for (
int ir = 0; ir <
nr; ++ir) {
111 for (
int iz = 0; iz < nz; ++iz) {
112 out << bzValue <<
" " << brValue <<
"\n";
118 std::filesystem::path
outputPath(
const std::string& suffix)
const {
119 return std::filesystem::path(
"data") / (
testStem_ + suffix);
123 std::filesystem::remove(
outputPath(
"_ElementPositions.txt"));
124 std::filesystem::remove(
outputPath(
"_ElementPositions.py"));
125 std::filesystem::remove(
outputPath(
"_ElementPositions.sdds"));
126 std::filesystem::remove(
outputPath(
"_ElementPositions.vtk"));
127 std::filesystem::remove(
outputPath(
"_ElementPositions.html"));
128 std::filesystem::remove(
outputPath(
"_ElementPositions.gpl"));
135 const auto quote = line.rfind(
'"');
136 EXPECT_NE(quote, std::string::npos);
137 std::istringstream values(line.substr(quote + 1));
138 double z = 0.0, x = 0.0, y = 0.0;
139 values >> z >> x >> y;
144 std::vector<std::string> tokens;
145 std::istringstream in(line);
147 while (in >> token) {
148 tokens.push_back(token);
175 const auto mapFile = writeXZFieldmap(
"solenoid_edges.map", -5.0, 15.0, 4, 0.0, 3.0, 3);
182 double startField = 1.0;
183 double endField = 0.0;
185 solenoid.
initialise(
nullptr, startField, endField);
187 FAIL() << ex.
where() <<
": " << ex.
what();
189 FAIL() <<
"non-OPAL exception";
192 double fieldBegin = 0.0, fieldEnd = 0.0;
195 double bodyBegin = 0.0, bodyEnd = 0.0;
198 EXPECT_NEAR(startField, 0.95, 1e-12);
199 EXPECT_NEAR(endField, 1.15, 1e-12);
201 EXPECT_NEAR(fieldBegin, -0.05, 1e-12);
202 EXPECT_NEAR(fieldEnd, 0.15, 1e-12);
203 EXPECT_NEAR(bodyBegin, 0.0, 1e-12);
204 EXPECT_NEAR(bodyEnd, 1.0, 1e-12);
207 EXPECT_TRUE(solenoid.
isInside({0.0, 0.0, 0.00}));
208 EXPECT_TRUE(solenoid.
isInside({0.0, 0.0, 0.14}));
209 EXPECT_FALSE(solenoid.
isInside({0.0, 0.0, 0.20}));
211 double horizontalRadius = 0.0;
212 double verticalRadius = 0.0;
214 const bool hasSupport = solenoid.
getSupportEnvelope(horizontalRadius, verticalRadius);
215 ASSERT_TRUE(hasSupport);
217 EXPECT_NEAR(horizontalRadius, 0.03, 1e-12);
218 EXPECT_NEAR(verticalRadius, 0.03, 1e-12);
222 const auto mapFile = writeXZFieldmap(
"solenoid_lattice.map", -5.0, 15.0, 4, 0.0, 3.0, 3);
229 auto bunch = makeBunch(0);
234 beamline.
visit(solenoid, visitor, *bunch);
236 FAIL() << ex.
where() <<
": " << ex.
what();
238 FAIL() <<
"non-OPAL exception";
244 const auto& placedComponent = *
elements.begin();
253 std::ifstream txt(outputPath(
"_ElementPositions.txt"));
254 ASSERT_TRUE(txt.is_open());
256 std::string textLine;
257 bool foundBegin =
false;
258 bool foundEnd =
false;
259 while (std::getline(txt, textLine)) {
260 if (textLine.find(
"\"BEGIN: SOL1\"") != std::string::npos) {
261 const auto [z, x, y] = parsePositionLine(textLine);
263 EXPECT_NEAR(z, entry(2), 1e-12);
264 EXPECT_NEAR(x, entry(0), 1e-12);
265 EXPECT_NEAR(y, entry(1), 1e-12);
267 }
else if (textLine.find(
"\"END: SOL1\"") != std::string::npos) {
268 const auto [z, x, y] = parsePositionLine(textLine);
270 EXPECT_NEAR(z, exit(2), 1e-12);
271 EXPECT_NEAR(x, exit(0), 1e-12);
272 EXPECT_NEAR(y, exit(1), 1e-12);
276 EXPECT_TRUE(foundBegin);
277 EXPECT_TRUE(foundEnd);
279 std::ifstream py(outputPath(
"_ElementPositions.py"));
280 ASSERT_TRUE(py.is_open());
281 const std::string script(
282 (std::istreambuf_iterator<char>(py)), std::istreambuf_iterator<char>());
283 EXPECT_NE(script.find(
"color = [5]"), std::string::npos);
284 EXPECT_NE(script.find(
"numVertices = [432]"), std::string::npos);
286 script.find(
"os.path.getmtime(script_file) > os.path.getmtime(vtk_file)"),
291 auto solenoid = std::make_shared<SolenoidRep>(
"SOL1");
299 std::ifstream sdds(outputPath(
"_ElementPositions.sdds"));
300 ASSERT_TRUE(sdds.is_open());
303 bool foundSolenoidRow =
false;
304 while (std::getline(sdds, line)) {
305 if (line.find(
"\"SOL1\"") == std::string::npos) {
309 const auto tokens = splitWhitespace(line);
310 ASSERT_GE(tokens.size(), 12u);
311 EXPECT_EQ(tokens[7],
"1");
312 EXPECT_EQ(tokens[10],
"0");
313 foundSolenoidRow =
true;
315 EXPECT_TRUE(foundSolenoidRow);
319 const auto mapFile = writeXZFieldmap(
"solenoid_drift_mesh.map", -5.0, 15.0, 4, 0.0, 3.0, 3);
330 auto bunch = makeBunch(0);
334 beamline.
visit(drift, visitor, *bunch);
335 beamline.
visit(solenoid, visitor, *bunch);
339 std::ifstream py(outputPath(
"_ElementPositions.py"));
340 ASSERT_TRUE(py.is_open());
341 const std::string script(
342 (std::istreambuf_iterator<char>(py)), std::istreambuf_iterator<char>());
343 EXPECT_NE(script.find(
"color = [8, 5]"), std::string::npos);
344 EXPECT_NE(script.find(
"numVertices = [144, 432]"), std::string::npos);
354 auto bunch = makeBunch(0);
358 beamline.
visit(quadrupole, visitor, *bunch);
362 std::ifstream py(outputPath(
"_ElementPositions.py"));
363 ASSERT_TRUE(py.is_open());
364 const std::string script(
365 (std::istreambuf_iterator<char>(py)), std::istreambuf_iterator<char>());
366 EXPECT_NE(script.find(
"color = [2]"), std::string::npos);
367 EXPECT_NE(script.find(
"numVertices = [32]"), std::string::npos);
378 mesh.
write(testStem_);
380 std::ifstream py(outputPath(
"_ElementPositions.py"));
381 ASSERT_TRUE(py.is_open());
382 const std::string script(
383 (std::istreambuf_iterator<char>(py)), std::istreambuf_iterator<char>());
384 EXPECT_NE(script.find(
"color = [6]"), std::string::npos);
385 EXPECT_NE(script.find(
"numVertices = [1008]"), std::string::npos);
395 mesh.
add(travelingWave);
396 mesh.
write(testStem_);
398 std::ifstream py(outputPath(
"_ElementPositions.py"));
399 ASSERT_TRUE(py.is_open());
400 const std::string script(
401 (std::istreambuf_iterator<char>(py)), std::istreambuf_iterator<char>());
402 EXPECT_NE(script.find(
"color = [7]"), std::string::npos);
403 EXPECT_NE(script.find(
"numVertices = [1152]"), std::string::npos);
ippl::Vector< T, Dim > Vector_t
TEST_F(SolenoidPlacementTest, FieldMapEdgesAndSupportEnvelopeFollowFieldMap)
Abstract base class for accelerator geometry classes.
static Beam * find(const std::string &name)
Find named BEAM.
virtual void visitBeamline(const Beamline &)=0
Apply the algorithm to a beam line.
An abstract sequence of beam line components.
ippl::Vector< double, 3 > getOrigin() const
ElementType getType() const override
Get element type std::string.
ElementBase * clone() const override
Return clone.
const BGeometryBase & getGeometry() const override
Get geometry.
BGeometryBase & getGeometry() override
Get geometry.
void accept(BeamlineVisitor &visitor) const override
Apply visitor.
void iterate(BeamlineVisitor &, bool) const override
Apply visitor to all elements of the line.
void setElementPosition(double elemedge)
Access to ELEMEDGE attribute.
void setAperture(const ApertureType &type, const std::vector< double > &args)
virtual double getElementLength() const
Get design length.
virtual void setElementLength(double length)
Set design length.
void add(key_t::first_type initialStep, key_t::second_type finalStep, const value_t &val)
std::set< std::shared_ptr< Component > > value_t
void saveSDDS(double startS) const
void add(const ElementBase &element)
void write(const std::string &fname)
void setNormalComponent(int n, double)
Geometry representing an identity transform.
std::vector< Attribute > itsAttr
The object attributes.
PlacedElement getPlacedElement(const std::shared_ptr< Component > &comp) const
Return the placed-element view used by the bridge stage.
std::set< std::shared_ptr< Component > > getElements(const Vector_t< double, 3 > &x)
void visit(const T &, BeamlineVisitor &, PartBunch_t &)
void storeInputFn(const std::string &fn)
store opals input filename
static OpalData * getInstance()
void setOpenMode(OpenMode openMode)
virtual const std::string & what() const
Return the message string for the exception.
virtual const std::string & where() const
Return the name of the method or function which detected the exception.
Geometric placement record for an element instance.
CoordinateSystemTrafo getNominalEntryTransform() const
CoordinateSystemTrafo getNominalExitTransform() const
void setBCY(const std::string &bc)
void setType(const std::string &t)
void setBCZ(const std::string &bc)
void setBCX(const std::string &bc)
void cleanupOutputs() const
static void TearDownTestSuite()
std::shared_ptr< DataSink > dataSink_m
static void SetUpTestSuite()
static std::tuple< double, double, double > parsePositionLine(const std::string &line)
std::shared_ptr< PartBunch_t > makeBunch(const size_t numParticles)
static std::vector< std::string > splitWhitespace(const std::string &line)
std::filesystem::path writeXZFieldmap(const std::string &filename, double zBeginCm, double zEndCm, int nz, double rBeginCm, double rEndCm, int nr, double bzValue=1.0, double brValue=0.0)
std::filesystem::path outputPath(const std::string &suffix) const
std::filesystem::path fieldmapFile_
std::shared_ptr< FieldSolverCmd > fsCmdBase_m
virtual CoordinateSystemTrafo getEdgeToBegin() const override
Get the coordinate transformation to the begin of the element.
virtual void initialise(PartBunch_t *bunch, double &startField, double &endField) override
initialise the solenoid element
virtual void getElementDimensions(double &zBegin, double &zEnd) const override
Return the nominal body extent of the solenoid.
virtual void getFieldExtend(double &zBegin, double &zEnd) const override
Return the local field-support interval of the solenoid.
virtual CoordinateSystemTrafo getEdgeToEnd() const override
Get the coordinate transformation to the end of the element.
virtual bool isInside(const Vector_t< double, 3 > &r) const override
Check if position r is inside the field map.
bool getSupportEnvelope(double &horizontalRadius, double &verticalRadius) const
Get a finite transverse support envelope for placement/export.
void setFieldMapFN(std::string fn)
Assign the field filename.
void setPredefinedString(Attribute &attr, const std::string &val)
Set predefined string value.
bool enableHDF5
If true HDF5 files are written.