OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
TestOpalMultipoleT.cpp
Go to the documentation of this file.
1//
2// Copyright (c) 2026, Paul Scherrer Institute, Villigen PSI, Switzerland
3// All rights reserved
4//
5// This file is part of OPAL.
6//
7// OPAL is free software: you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation, either version 3 of the License, or
10// (at your option) any later version.
11//
12// You should have received a copy of the GNU General License
13// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
14//
18#include "gtest/gtest.h"
19
20class TestOpalMultipoleT : public testing::Test {
21public:
22 TestOpalMultipoleT() = default;
23
24 static void SetUpTestSuite() {
25 int argc = 0;
26 char** argv = nullptr;
27 ippl::initialize(argc, argv);
28 // Many OPAL writers assume `gmsg` is initialized (see SDDSWriter/StatWriter).
29 // Unit tests normally don't set this up via Main().
30 gmsg = new Inform(nullptr, -1);
31 }
32 static void TearDownTestSuite() {
33 delete gmsg;
34 gmsg = nullptr;
35 ippl::finalize();
36 }
37};
38
39// Does the user interface affect the correct magnet configuration
40TEST_F(TestOpalMultipoleT, UserInterface) {
41 // Make the UI
43 // Set the attributes
64 // Update the magnet
65 EXPECT_NO_THROW(ui.update());
66 // Check the values
67 auto* myMagnet = dynamic_cast<MultipoleT*>(ui.getElement());
68 EXPECT_TRUE(myMagnet);
69 EXPECT_NEAR(myMagnet->getElementLength(), 4.1, 1e-6);
70 auto tp = myMagnet->getTransProfile();
71 EXPECT_EQ(tp.size(), MultipoleTConfig::NumPoles);
72 EXPECT_NEAR(tp[0], 0.2, 1e-6);
73 EXPECT_NEAR(tp[1], 0.3, 1e-6);
74 auto [s0, left, right] = myMagnet->getFringeField();
75 EXPECT_NEAR(s0, 4.1 / 2.0, 1e-6);
76 EXPECT_NEAR(left, 0.5, 1e-6);
77 EXPECT_NEAR(right, 0.6, 1e-6);
78 auto [vertical, horizontal] = myMagnet->getAperture();
79 EXPECT_NEAR(vertical, 1.1, 1e-6);
80 EXPECT_NEAR(horizontal, 1.0, 1e-6);
81 EXPECT_NEAR(myMagnet->getMaxFOrder(), 4.0, 1e-6);
82 EXPECT_NEAR(myMagnet->getRotation(), 0.0, 1e-6);
83 EXPECT_NEAR(myMagnet->getEntranceAngle(), 0.01, 1e-6);
84 EXPECT_NEAR(myMagnet->getBoundingBoxLength(), 6.0, 1e-6);
85 EXPECT_NEAR(myMagnet->getBendAngle(), 0.628, 1e-6);
86 EXPECT_NEAR(myMagnet->getMaxXOrder(), 7.0, 1e-6);
87 EXPECT_FALSE(myMagnet->getVariableRadius());
88 EXPECT_NEAR(myMagnet->getEntryOffset(), 0.0, 1e-6);
89 // Check rotation (only works for straight magnets)
92 EXPECT_NO_THROW(ui.update());
93 EXPECT_NEAR(myMagnet->getRotation(), 0.1, 1e-6);
94 // Check entry offset (only works for var radius magnets)
99 EXPECT_ANY_THROW(ui.update()); // Currently throws 'cos var radius not yet supported
100 // Check time dependency
104 EXPECT_NO_THROW(ui.update());
105 EXPECT_EQ(myMagnet->getScalingName(), "SCALING");
106}
107
108// Does the user interface clone have the correct magnet configuration
109TEST_F(TestOpalMultipoleT, UserInterfaceClone) {
110 // Make the UI
112 // Set the attributes
128 // Make the clone
129 std::unique_ptr<OpalMultipoleT> uiClone{ui.clone("Clone")};
130 // Update the magnet
131 EXPECT_NO_THROW(uiClone->update());
132 // Check the values
133 auto* myMagnet = dynamic_cast<MultipoleT*>(uiClone->getElement());
134 EXPECT_TRUE(myMagnet);
135 EXPECT_NEAR(myMagnet->getElementLength(), 4.1, 1e-6);
136 auto tp = myMagnet->getTransProfile();
137 EXPECT_EQ(tp.size(), 6);
138 EXPECT_NEAR(tp[0], 0.2, 1e-6);
139 EXPECT_NEAR(tp[1], 0.3, 1e-6);
140 EXPECT_NEAR(tp[2], 0.0, 1e-6);
141 EXPECT_NEAR(tp[3], 0.0, 1e-6);
142 EXPECT_NEAR(tp[4], 0.0, 1e-6);
143 EXPECT_NEAR(tp[5], 0.0, 1e-6);
144 auto [s0, left, right] = myMagnet->getFringeField();
145 EXPECT_NEAR(s0, 4.1 / 2.0, 1e-6);
146 EXPECT_NEAR(left, 0.5, 1e-6);
147 EXPECT_NEAR(right, 0.6, 1e-6);
148 auto [vertical, horizontal] = myMagnet->getAperture();
149 EXPECT_NEAR(vertical, 1.1, 1e-6);
150 EXPECT_NEAR(horizontal, 1.0, 1e-6);
151 EXPECT_NEAR(myMagnet->getMaxFOrder(), 4.0, 1e-6);
152 EXPECT_NEAR(myMagnet->getRotation(), 0.0, 1e-6);
153 EXPECT_NEAR(myMagnet->getEntranceAngle(), 0.01, 1e-6);
154 EXPECT_NEAR(myMagnet->getBoundingBoxLength(), 6.0, 1e-6);
155 EXPECT_NEAR(myMagnet->getBendAngle(), 0.628, 1e-6);
156 EXPECT_NEAR(myMagnet->getMaxXOrder(), 7.0, 1e-6);
157 EXPECT_FALSE(myMagnet->getVariableRadius());
158 EXPECT_NEAR(myMagnet->getEntryOffset(), 0.0, 1e-6);
159 EXPECT_EQ(myMagnet->getScalingName(), "SCALING");
160}
161
162// Check the various configuration validation tests
163TEST_F(TestOpalMultipoleT, UserInterfaceSanityCheck) {
164 // Make the UI
166 // Set the attributes
180 // Try F order of zero
182 EXPECT_ANY_THROW(ui.update());
183 // Try F order of 21
185 EXPECT_ANY_THROW(ui.update());
186 // Try skew straight magnet
190 EXPECT_NO_THROW(ui.update());
191 // Try skew bent magnet
194 EXPECT_ANY_THROW(ui.update());
195 // Try the variable radius magnet
199 EXPECT_ANY_THROW(ui.update());
200 // Try the entry offset with a straight magnet
204 EXPECT_ANY_THROW(ui.update());
205 // Try the entry offset with a bent magnet
209 EXPECT_ANY_THROW(ui.update());
210 // Try the entry offset with a variable radius bent magnet
214 EXPECT_ANY_THROW(ui.update());
215}
216
217// Does the print API work
219 // Make the UI
220 const OpalMultipoleT ui;
221 // And print it
222 std::stringstream ss;
223 ui.print(ss);
224 EXPECT_EQ(ss.str(), "MULTIPOLET;\n");
225}
Inform * gmsg
Definition changes.cpp:7
TEST_F(TestOpalMultipoleT, UserInterface)
ElementBase * getElement() const
Return the embedded OPALX element.
Definition Element.h:119
std::vector< Attribute > itsAttr
The object attributes.
Definition Object.h:210
OpalMultipoleT * clone(const std::string &name) override
void update() override
void print(std::ostream &os) const override
Print the object.
static void TearDownTestSuite()
TestOpalMultipoleT()=default
void setRealArray(Attribute &attr, const std::vector< double > &value)
Set array value.
void setBool(Attribute &attr, bool val)
Set logical value.
void setUpperCaseString(Attribute &attr, const std::string &val)
Set uppercase string value.
void setReal(Attribute &attr, double val)
Set real value.
static constexpr unsigned int NumPoles