28#include <gtest/gtest.h>
44#include "Utility/Inform.h"
50 void setType(
const std::string& t) {
54 void setBCX(
const std::string& bc) {
57 void setBCY(
const std::string& bc) {
60 void setBCZ(
const std::string& bc) {
64 void setBinsName(
const std::string& binsName) {
93 constexpr size_t kDefaultNParticles = 64;
95 class BinnedFieldSolverSmokeTest :
public ::testing::Test {
97 static void SetUpTestSuite() {
99 char** argv =
nullptr;
100 ippl::initialize(argc, argv);
107 gmsg =
new Inform(
nullptr, -1);
114 static void TearDownTestSuite() {
120 void SetUp()
override {
122 constexpr double nx = 8;
123 constexpr double ny = 8;
124 constexpr double nz = 8;
126 fsCmd = std::make_shared<TestableFieldSolverCmd>();
127 fsCmd->setType(
"NONE");
131 fsCmd->setBCX(
"PERIODIC");
132 fsCmd->setBCY(
"PERIODIC");
133 fsCmd->setBCZ(
"PERIODIC");
138 dataSink = std::make_shared<DataSink>();
139 beam = std::make_shared<Beam>();
144 bunch = std::make_shared<PartBunch_t>(
145 std::vector<double>{1.0},
146 std::vector<double>{1.0},
147 std::vector<Beam*>{testBeam},
148 std::vector<size_t>{kDefaultNParticles},
150 "LF2", fsCmdBase.get(), dataSink.get());
151 pc = bunch->getParticleContainer();
154 void TearDown()
override {
163 void createParticles(
size_t nPart,
double pzMin,
double pzMax) {
164 pc->createParticles(nPart);
166 std::mt19937_64 eng(42 + ippl::Comm->rank());
168 auto R_host = pc->R.getHostMirror();
169 auto P_host = pc->P.getHostMirror();
170 auto dt_host = pc->dt.getHostMirror();
171 auto E_host = pc->E.getHostMirror();
174 const auto rmin = bunch->rmin_m;
175 const auto rmax = bunch->rmax_m;
177 std::uniform_real_distribution<double> unifR_x(rmin[0] + 0.1, rmax[0] - 0.1);
178 std::uniform_real_distribution<double> unifR_y(rmin[1] + 0.1, rmax[1] - 0.1);
179 std::uniform_real_distribution<double> unifR_z(rmin[2] + 0.1, rmax[2] - 0.1);
180 std::uniform_real_distribution<double> unifP_z(pzMin, pzMax);
182 const double dt = bunch->getdT();
183 const double qi = pc->getChargePerParticle();
185 for (
size_t i = 0; i < nPart; ++i) {
186 R_host(i)[0] = unifR_x(eng);
187 R_host(i)[1] = unifR_y(eng);
188 R_host(i)[2] = unifR_z(eng);
192 P_host(i)[2] = unifP_z(eng);
202 Kokkos::deep_copy(pc->R.getView(), R_host);
203 Kokkos::deep_copy(pc->P.getView(), P_host);
204 Kokkos::deep_copy(pc->dt.getView(), dt_host);
205 Kokkos::deep_copy(pc->E.getView(), E_host);
208 ippl::Comm->barrier();
213 void rebuildBunch() {
216 bunch = std::make_shared<PartBunch_t>(
217 std::vector<double>{1.0},
218 std::vector<double>{1.0},
219 std::vector<Beam*>{testBeam},
220 std::vector<size_t>{kDefaultNParticles},
222 "LF2", fsCmdBase.get(), dataSink.get());
223 pc = bunch->getParticleContainer();
226 std::shared_ptr<AdaptBins_t> attachBins(
228 double desiredWidth) {
229 using ConcreteBins_t =
232 CoordinateSelector_t selector(2);
233 auto bins = std::make_shared<ConcreteBins_t>(
234 *pc, selector, maxBins, alpha, beta, desiredWidth,
236 bunch->setBins(bins);
240 void defineBinningCommand(
242 bool adaptiveBinning) {
243 auto* binsCmd =
new TestableBinningCmd();
244 binsCmd->setOpalName(name);
245 binsCmd->setMaxBins(maxBins);
246 binsCmd->setAdaptiveBinning(adaptiveBinning);
247 binsCmd->setTablePrintFrequency(0.0);
248 binsCmd->setParameterString(
"VELOCITYZ");
253 void expectAllParticleEZeroAndFinite(
double tol) {
254 auto E_host = pc->E.getHostMirror();
255 Kokkos::deep_copy(E_host, pc->E.getView());
257 const size_t localN = pc->getLocalNum();
258 for (
size_t i = 0; i < localN; ++i) {
259 for (
unsigned d = 0; d < 3; ++d) {
260 const double val = E_host(i)[d];
261 EXPECT_TRUE(std::isfinite(val)) <<
"E[" << i <<
"][" << d <<
"]=" << val;
262 EXPECT_NEAR(val, 0.0, tol) <<
"E[" << i <<
"][" << d <<
"]";
267 std::shared_ptr<TestableFieldSolverCmd> fsCmd;
268 std::shared_ptr<FieldSolverCmd> fsCmdBase;
269 std::shared_ptr<DataSink> dataSink;
270 std::shared_ptr<Beam> beam;
271 std::shared_ptr<PartBunch_t> bunch;
272 std::shared_ptr<ParticleContainer_t> pc;
275 TEST_F(BinnedFieldSolverSmokeTest, LegacyPath_NoBins_NoThrowAndEZero) {
276 ASSERT_FALSE(bunch->hasBinning());
277 createParticles(kDefaultNParticles, 0.1, 0.9);
279 EXPECT_NO_THROW(bunch->computeSelfFields());
280 expectAllParticleEZeroAndFinite(1e-8);
283 TEST_F(BinnedFieldSolverSmokeTest, BinnedPath_WithBins_NoThrowAndEZero) {
284 createParticles(kDefaultNParticles, 0.1, 2.0);
287 auto bins = attachBins(maxBins, 1.0, 1.0, 0.3);
288 ASSERT_TRUE(bunch->hasBinning());
290 EXPECT_NO_THROW(bunch->computeSelfFields());
292 const auto currentBins = bins->getCurrentBinCount();
293 EXPECT_GE(currentBins, 1);
294 EXPECT_LE(currentBins, maxBins);
296 expectAllParticleEZeroAndFinite(1e-8);
299 TEST_F(BinnedFieldSolverSmokeTest, BinnedPath_AdaptiveBinningFalseKeepsUniformMaxBins) {
301 const std::string binsName =
"UNIT_TEST_UNIFORM_BINNING";
302 defineBinningCommand(binsName, maxBins,
false);
304 fsCmd->setType(
"OPEN");
305 fsCmd->setBinsName(binsName);
306 fsCmd->setBCX(
"OPEN");
307 fsCmd->setBCY(
"OPEN");
308 fsCmd->setBCZ(
"OPEN");
311 createParticles(kDefaultNParticles, 0.1, 2.0);
312 ASSERT_TRUE(bunch->hasBinning());
314 EXPECT_NO_THROW(bunch->computeSelfFields());
316 auto bins = bunch->getBins();
317 ASSERT_NE(bins,
nullptr);
318 EXPECT_EQ(bins->getCurrentBinCount(), maxBins);
321 TEST_F(BinnedFieldSolverSmokeTest, BunchUpdate_ImageChargeBoundsIncludeMirroredZ) {
322 constexpr double zPlane = 0.0;
323 bunch->setImageChargeConfiguration(
true, zPlane);
325 createParticles(kDefaultNParticles, 0.1, 0.9);
326 bunch->bunchUpdate();
328 pc->computeMinMaxR();
329 const auto minR = pc->getMinR();
330 const auto maxR = pc->getMaxR();
331 const auto gridMin = bunch->rmin_m;
332 const auto gridMax = bunch->rmax_m;
334 const double mirroredMinZ = 2.0 * zPlane - maxR[2];
335 const double mirroredMaxZ = 2.0 * zPlane - minR[2];
337 EXPECT_LE(gridMin[2], std::min(minR[2], mirroredMinZ));
338 EXPECT_GE(gridMax[2], std::max(maxR[2], mirroredMaxZ));
Template PIC bunch: IPPL PicManager, shared field mesh/solver, and multiple particle containers.
TEST_F(MonitorTest, GetType)
static Beam * find(const std::string &name)
Find named BEAM.
void storeInputFn(const std::string &fn)
store opals input filename
static OpalData * getInstance()
void define(Object *newObject)
Define a new object.
typename ParticleBinning::CoordinateSelector< ParticleContainer_t > CoordinateSelector_t
ParticleContainer< T, Dim > ParticleContainer_t
typename ParticleBinning::AdaptBinsBase< ParticleContainer_t > AdaptBins_t
A class that bins particles in energy bins and allows for adaptive runtime rebinning.
typename BunchType::bin_index_type bin_index_type
Container for all per-particle (and per-simulation) fields tracked during OPALX tracking.
void setMaxBins(int value)
void setTablePrintFrequency(double value)
void setParameterString(const std::string &value)
void setAdaptiveBinning(bool value)
void setBool(Attribute &attr, bool val)
Set logical value.
void setString(Attribute &attr, const std::string &val)
Set string value.
void setReal(Attribute &attr, double val)
Set real value.
void setPredefinedString(Attribute &attr, const std::string &val)
Set predefined string value.
bool enableHDF5
If true HDF5 files are written.