Commit 29482453 authored by chrisrogers1234's avatar chrisrogers1234
Browse files

DumpFields and fix bug introduced in Ring tracker

parent 761c932c
......@@ -10,3 +10,4 @@ Makefile
revision.h
src/opal
tests/tools/gtest
tests/opal_unit_test
......@@ -123,7 +123,7 @@ ENDIF (USE_MIC)
# Handle options
OPTION (ENABLE_AMR_SOLVER "Enable BoxLib based AMR solver" OFF)
OPTION (ENABLE_SAAMG_SOLVER "Enable iteartive SA-AMG-PCG self field solver" ON)
OPTION (ENABLE_SAAMG_SOLVER "Enable iteartive SA-AMG-PCG self field solver" OFF)
OPTION (DBG_SCALARFIELD "Enable dump of scalar field rho_m" OFF)
OPTION (DBG_STENCIL "Dump stencil of iterative solver in matlab format" OFF)
......@@ -183,6 +183,8 @@ IF (ENABLE_AMR_SOLVER)
ENDIF (ENABLE_AMR_SOLVER)
if (ENABLE_SAAMG_SOLVER OR ENABLE_AMR_SOLVER)
MESSAGE ("Enable SAAMG_SOLVER " ${ENABLE_SAAMG_SOLVER})
MESSAGE ("Enable AMR_SOLVER " ${ENABLE_AMR_SOLVER})
find_package (Trilinos REQUIRED HINTS $ENV{TRILINOS_PREFIX} $ENV{TRILINOS_DIR} $ENV{TRILINOS})
message (STATUS "Found Trilinos: ${Trilinos_DIR}")
......
......@@ -390,7 +390,7 @@ class Ring : public Component {
// number of cells/rotational symmetry of the ring
int symmetry_m;
double scale_m;
double scale_m = 1.;
// rf harmonic number
double cyclHarm_m;
......
......@@ -87,6 +87,7 @@ bool SBend3D::apply(const size_t &i, const double &t,
bool SBend3D::apply(const Vector_t &R, const Vector_t &centroid,
const double &t, Vector_t &E, Vector_t &B) {
//std::cerr << "ROGERS SBend3D::apply " << R << " " << B << std::endl;
return map_m->getFieldstrength(R, E, B);
}
......
......@@ -60,7 +60,7 @@ class ThreeDGrid : public Mesh {
class Iterator;
/** Deep copy the grid */
Mesh * clone() {return new ThreeDGrid(*this);}
ThreeDGrid * clone() {return new ThreeDGrid(*this);}
/** Not implemented (returns NULL) */
Mesh * dual () const;
......
......@@ -71,6 +71,8 @@
#include "Utilities/NumToStr.h"
#include "Utilities/OpalException.h"
#include "BasicActions/DumpFields.h"
#include "Structure/H5PartWrapperForPC.h"
#include "Structure/BoundaryGeometry.h"
#include "Utilities/Options.h"
......@@ -1143,6 +1145,7 @@ void ParallelCyclotronTracker::execute() {
extE_m = Vector_t(0.0, 0.0, 0.0);
extB_m = Vector_t(0.0, 0.0, 0.0);
DumpFields::writeFields((((*FieldDimensions.begin())->second).second));
if(timeIntegrator_m == 0) {
*gmsg << "* 4th order Runge-Kutta integrator" << endl;
......@@ -2405,7 +2408,6 @@ void ParallelCyclotronTracker::Tracker_RK4() {
// change phase space parameters from local frame of bunch (dr,dtheta,dz) to global Cartesian frame (X,Y,Z)
for(int j = 0; j < 3; j++)variable_m[j] = itsBunch->R[i](j); //[x,y,z] units: [mm]
for(int j = 0; j < 3; j++)variable_m[j+3] = itsBunch->P[i](j); //[px,py,pz] units: []
if((step_m % SinglePartDumpFreq == 0)) {
outfTrackOrbit_m << "ID" << (itsBunch->ID[i]);
outfTrackOrbit_m << " " << variable_m[0] << " " << variable_m[3] << " " << variable_m[1] << " "
......@@ -2457,7 +2459,7 @@ void ParallelCyclotronTracker::Tracker_RK4() {
if((step_m % SinglePartDumpFreq == 0)) {
outfTrackOrbit_m << "ID" <<itsBunch->ID[i];
outfTrackOrbit_m << " " << itsBunch->R[i](0) << " " <<itsBunch->P[i](0) << " " <<itsBunch->R[i](1)
<< " " << itsBunch->P[i](1) << " " <<itsBunch->R[i](2) << " " <<itsBunch->P[i](2)<< std::endl;
<< " " << itsBunch->P[i](1) << " " <<itsBunch->R[i](2) << " " <<itsBunch->P[i](2) << std::endl;
}
// change phase space parameters from local frame of bunch (dr,dtheta,dz) to global Cartesian frame (X,Y,Z)
......
set (_SRCS
Call.cpp
Dump.cpp
DumpFields.cpp
Echo.cpp
Help.cpp
Option.cpp
......
/*
* Copyright (c) 2016, Chris Rogers
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STFC nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <fstream>
#include "Fields/Interpolation/ThreeDGrid.h" // classic
#include "AbsBeamline/Component.h" // classic
#include "Utilities/OpalException.h"
#include "Attributes/Attributes.h"
#include "BasicActions/DumpFields.h"
// extern Inform *gmsg;
std::unordered_set<DumpFields*> DumpFields::dumpsSet_m;
std::string DumpFields::dumpfields_docstring =
std::string("The \"DUMPFIELDS\" statement dumps a field map to a user-defined")+
std::string(" field file, for checking that fields are read in correctly")+
std::string(" from disk. The fields are written out on a Cartesian grid.");
DumpFields::DumpFields() :
Action(10, "DUMPFIELDS", dumpfields_docstring.c_str()),
grid_m(NULL), filename_m("") {
// would be nice if "steps" could be integer
itsAttr[0] = Attributes::makeReal
("X_START", "Start point in the grid in x [mm]");
itsAttr[1] = Attributes::makeReal
("DX", "Grid step size in x [mm]");
itsAttr[2] = Attributes::makeReal
("X_STEPS", "Number of steps in x");
itsAttr[3] = Attributes::makeReal
("Y_START", "Start point in the grid in y [mm]");
itsAttr[4] = Attributes::makeReal
("DY", "Grid step size in y [mm]");
itsAttr[5] = Attributes::makeReal
("Y_STEPS", "Number of steps in y");
itsAttr[6] = Attributes::makeReal
("Z_START", "Start point in the grid in z [mm]");
itsAttr[7] = Attributes::makeReal
("DZ", "Grid step size in z [mm]");
itsAttr[8] = Attributes::makeReal
("Z_STEPS", "Number of steps in z");
itsAttr[9] = Attributes::makeString
("FILE_NAME", "Name of the file to which field data is dumped");
}
DumpFields::~DumpFields() {
if (grid_m != NULL) {
delete grid_m;
}
if (dumpsSet_m.find(this) != dumpsSet_m.end()) {
dumpsSet_m.erase(this);
}
}
DumpFields* DumpFields::clone(const std::string &name) {
DumpFields* dumper = new DumpFields();
if (grid_m != NULL) {
dumper->grid_m = grid_m->clone();
}
dumper->filename_m = filename_m;
if (dumpsSet_m.find(this) != dumpsSet_m.end()) {
dumpsSet_m.insert(dumper);
}
return dumper;
}
void DumpFields::execute() {
buildGrid();
// the routine for action (OpalParser/OpalParser) calls execute and then
// deletes 'this'; so we must build a copy that lasts until the field maps
// are constructed and we are ready for tracking (which is when the field
// maps are written). Hence the clone call below.
dumpsSet_m.insert(this->clone(""));
}
void DumpFields::buildGrid() {
double x0 = Attributes::getReal(itsAttr[0]);
double dx = Attributes::getReal(itsAttr[1]);
double nx = Attributes::getReal(itsAttr[2]);
double y0 = Attributes::getReal(itsAttr[3]);
double dy = Attributes::getReal(itsAttr[4]);
double ny = Attributes::getReal(itsAttr[5]);
double z0 = Attributes::getReal(itsAttr[6]);
double dz = Attributes::getReal(itsAttr[7]);
double nz = Attributes::getReal(itsAttr[8]);
checkInt(nx, "X_STEPS");
checkInt(ny, "Y_STEPS");
checkInt(nz, "Z_STEPS");
if (grid_m != NULL) {
delete grid_m;
}
grid_m = new interpolation::ThreeDGrid(dx, dy, dz,
x0, y0, z0,
nx, ny, nz);
filename_m = Attributes::getString(itsAttr[9]);
}
void DumpFields::writeFields(Component* field) {
typedef std::unordered_set<DumpFields*>::iterator dump_iter;
for (dump_iter it = dumpsSet_m.begin(); it != dumpsSet_m.end(); ++it) {
(*it)->writeFieldThis(field);
}
}
void DumpFields::checkInt(double real, std::string name, double tolerance) {
if (fabs(floor(real) - real) > tolerance) {
throw OpalException("DumpFields::checkInt",
"Value for "+name+
" should be an integer but a real value was found");
}
if (floor(real) < 0.5) {
throw OpalException("DumpFields::checkInt",
"Value for "+name+" should be 1 or more");
}
}
void DumpFields::writeFieldThis(Component* field) {
if (grid_m == NULL) {
throw OpalException("DumpFields::writeField",
"The grid was NULL; there was a problem with the DumpFields initialisation.");
}
if (field == NULL) {
throw OpalException("DumpFields::writeField",
"The field to be written was NULL.");
}
double time = 0.;
Vector_t point(0., 0., 0.);
Vector_t centroid(0., 0., 0.);
std::ofstream fout(filename_m.c_str(), std::ofstream::out);
if (!fout.good()) {
throw OpalException("DumpFields::writeField",
"Failed to open DumpFields file "+filename_m);
}
// set precision
fout << grid_m->end().toInteger() << "\n";
fout << 1 << " x [mm]\n";
fout << 2 << " y [mm]\n";
fout << 3 << " z [mm]\n";
fout << 4 << " Bx [T]\n";
fout << 5 << " By [T]\n";
fout << 6 << " Bz [T]\n";
fout << 0 << std::endl;
for (interpolation::Mesh::Iterator it = grid_m->begin();
it < grid_m->end();
++it) {
Vector_t E(0., 0., 0.);
Vector_t B(0., 0., 0.);
it.getPosition(&point[0]);
field->apply(point, centroid, time, E, B);
fout << point[0] << " " << point[1] << " " << point[2] << " ";
fout << B[0] << " " << B[1] << " " << B[2] << "\n";
}
if (!fout.good()) {
throw OpalException("DumpFields::writeField",
"Something went wrong during writing "+filename_m);
}
fout.close();
}
/*
* Copyright (c) 2016, Chris Rogers
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STFC nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OPAL_DUMPFIELDS_HH
#define OPAL_DUMPFIELDS_HH
#include <unordered_set>
#include <string>
#include "AbstractObjects/Action.h"
namespace interpolation {
class ThreeDGrid;
}
class Component;
/** DumpFields dumps the fields of a Ring in a user-defined grid
*
* The idea is to print out the field map across a grid in space-time for
* debugging purposes. The problem is to manage the DumpFields object through
* three phases of program execution; initial construction, parsing and then
* actual field map writing (where we need to somehow let DumpFields know what
* the field maps are). So for each DumpFields object created, we store in a
* set. When the execute() method is called, DumpFields builds a grid using
* the parsed information.
*
* When the ParallelCyclotronTracker is about to start tracking, it calls
* writeFields method which loops over the static set of DumpFields and writes
* each one. It is not the cleanest implementation, but I can't see a better
* way.
*
* The DumpFields themselves operate by iterating over a ThreeDGrid object
* and looking up the field/writing it out on each grid point.
*
*/
class DumpFields : public Action {
public:
/** Constructor */
DumpFields();
/** Destructor deletes grid_m and if in the dumps set, take it out */
virtual ~DumpFields();
/** Make a clone (overloadable copy-constructor).
* @param name not used
* If this is in the dumpsSet_m, so will the clone. Not sure how the
* itsAttr stuff works, so this may not get properly copied?
*/
virtual DumpFields *clone(const std::string &name);
/** Builds the grid but does not write the field map
*
* Builds a grid of points in x-y-z space using the ThreeDGrid algorithm.
* Checks that X_STEPS, Y_STEPS, Z_STEPS are integers or throws
* OpalException.
*/
virtual void execute();
/** Write the fields for all defined DumpFields objects
* @param field borrowed reference to the Component object that holds the
* field map; caller owns the memory.
* Iterates over the DumpFields in the dumpsSet_m and calls writeFieldThis
* on each DumpFields. This writes each field map in turn. Format is:
* <number of rows>
* <column 1> <units>
* <column 2> <units>
* <column 3> <units>
* <column 4> <units>
* <column 5> <units>
* <column 6> <units>
* 0
* <field map data>
*/
static void writeFields(Component* field);
private:
virtual void writeFieldThis(Component* field);
virtual void buildGrid();
static void checkInt(double value, std::string name, double tolerance = 1e-9);
interpolation::ThreeDGrid* grid_m;
std::string filename_m;
static std::unordered_set<DumpFields*> dumpsSet_m;
static std::string dumpfields_docstring;
DumpFields(const DumpFields& dump); // disabled
DumpFields& operator=(const DumpFields& dump); // disabled
};
#endif // ifdef OPAL_DUMPFIELDS_HH
......@@ -25,6 +25,7 @@
// Basic action commands.
#include "BasicActions/Call.h"
#include "BasicActions/Dump.h"
#include "BasicActions/DumpFields.h"
#include "BasicActions/Echo.h"
#include "BasicActions/Help.h"
#include "BasicActions/Option.h"
......@@ -145,6 +146,7 @@ namespace Configure {
OpalData *opal = OpalData::getInstance();
opal->create(new Call());
opal->create(new Dump());
opal->create(new DumpFields());
opal->create(new Echo());
opal->create(new Dynamic());
opal->create(new Eigen());
......
......@@ -305,14 +305,14 @@ TEST(RingTest, TestApply) {
Vector_t pos(x, y, -0.5);
Vector_t centroid, B, E;
// std::cout << pos << " ** " << std::flush;
EXPECT_FALSE(ring.apply(pos, centroid, 0., E, B)) << ::burnAfterReading(debugOutput);
EXPECT_FALSE(ring.apply(pos, centroid, 0., E, B)) << " for pos " << pos << ::burnAfterReading(debugOutput);
// std::cout << B << " " << E << std::endl;
Vector_t BRef(0.0, 0.0, 0.0);
if (x > 0. and x < 1.)
BRef = Vector_t(x-1., y+2., -0.5);
for (int i = 0; i < 3; ++i) {
EXPECT_NEAR(B(i), BRef(i), 1e-6) << ::burnAfterReading(debugOutput);
EXPECT_NEAR(E(i), -BRef(i), 1e-6) << ::burnAfterReading(debugOutput);
EXPECT_NEAR(B(i), BRef(i), 1e-6) << " for pos " << pos << ::burnAfterReading(debugOutput);
EXPECT_NEAR(E(i), -BRef(i), 1e-6) << " for pos " << pos << ::burnAfterReading(debugOutput);
}
}
// check that we get something reasonable for all phi
......@@ -478,4 +478,4 @@ TEST(RingTest, TestApply3) {
testField(0.1, 0.15, 0.2, Physics::pi/6.,
3.*cos(Physics::pi/6)+1.*sin(Physics::pi/6),
-3.*sin(Physics::pi/6)+1.*cos(Physics::pi/6), 2., 1e-6);
}
\ No newline at end of file
}
set (_SRCS
DumpFieldsTest.cpp
)
include_directories (
${CMAKE_CURRENT_SOURCE_DIR}
)
add_sources(${_SRCS})
/*
* Copyright (c) 2014, Chris Rogers
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STFC nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <fstream>
#include "gtest/gtest.h"
#include "opal_src/Utilities/MockComponent.h"
#include "Attributes/Attributes.h"
#include "Utilities/OpalException.h"
#include "BasicActions/DumpFields.h"
namespace test {
void test() {}
void setOneAttribute(DumpFields* dump, std::string name, double value) {
Attributes::setReal(*dump->findAttribute(name), value);
}
void setAttributes(DumpFields* dump,
double x0, double dx, double nx,
double y0, double dy, double ny,
double z0, double dz, double nz,
std::string filename) {
setOneAttribute(dump, "X_START", x0);
setOneAttribute(dump, "DX", dx);
setOneAttribute(dump, "X_STEPS", nx);
setOneAttribute(dump, "Y_START", y0);
setOneAttribute(dump, "DY", dy);
setOneAttribute(dump, "Y_STEPS", ny);
setOneAttribute(dump, "Z_START", z0);
setOneAttribute(dump, "DZ", dz);
setOneAttribute(dump, "Z_STEPS", nz);
Attributes::setString(*dump->findAttribute("FILE_NAME"), filename);
}
TEST(DumpFieldsTest, ConstructorDestructor) {
// neither in the set and grid is null
DumpFields* dump1 = new DumpFields();
delete dump1;
// grid is not null and it is in the set
DumpFields* dump2 = new DumpFields();
setAttributes(dump2, 1., 1., 1., 1., 1., 1., 1., 1., 1., "/dev/null");
dump2->execute();
delete dump2;
}
void execute_throws(DumpFields* dump, std::string reason) {
try {
dump->execute();
EXPECT_TRUE(false) << reason;
} catch (OpalException& exc) {
// pass;
}
}
TEST(DumpFieldsTest, executeTest) {
// dump the fields
DumpFields dump1;
execute_throws(&dump1, "should throw due to nsteps < 1");
setAttributes(&dump1, 1., 1., 1., 1., 1., 1., 1., 1., 1., "/dev/null");
dump1.execute(); // should be okay (normal)
setAttributes(&dump1, -1., -1., 1., -1., -1., 1., -1., -1., 1., "/dev/null");
dump1.execute(); // should be okay (-ve step is okay)
setAttributes(&dump1, -1., -1., 0., -1., -1., 1., -1., -1., 1., "/dev/null");
execute_throws(&dump1, "should throw due to nsteps x < 1");
setAttributes(&dump1, -1., -1., 1., -1., -1., 0., -1., -1., 1., "/dev/null");
execute_throws(&dump1, "should throw due to nsteps y < 1");
setAttributes(&dump1, -1., -1., 1., -1., -1., 1., -1., -1., 0., "/dev/null");
execute_throws(&dump1, "should throw due to nsteps z < 1");
setAttributes(&dump1, -1., -1., 1., -1., -1., 1., -1., -1., 1.5, "/dev/null");
execute_throws(&dump1, "should throw due to nsteps not integer");
}
void clear_files() {
size_t n_str_array = 4;
std::string str_array[4] = {"test1", "test2", "test3", "test4"};
for (size_t i = 0; i < n_str_array; ++i) {
if (fopen(str_array[i].c_str(), "r") != NULL) {
remove(str_array[i].c_str());
}
}
}
TEST(DumpFieldsTest, writeFieldsTest) {
clear_files();
DumpFields dump1;
setAttributes(&dump1, 1., 1., 1., 1., 1., 1., 1., 1., 1., "test1");
dump1.execute();
DumpFields dump2;
setAttributes(&dump2, 1., 1., 1., 1., 1., 1., 1., 1., 1., "test2");
dump2.execute();
DumpFields dump3;
setAttributes(&dump3, 1., 1., 1., 1., 1., 1., 1., 1., 1., "test3");
// note we don't execute dump3; so it should not be written
DumpFields dump4;
setAttributes(&dump4, 0.1, 0.1, 3., -0.1, 0.2, 2., 0.2, 0.3, 2., "test4");
dump4.execute();
MockComponent comp;
try {
DumpFields::writeFields(&comp);
} catch (OpalException& exc) {
EXPECT_TRUE(false) << "Threw OpalException on writefields: " << exc.what() << std::endl;;
}
std::ifstream fin1("test1");
EXPECT_TRUE(fin1.good());
std::ifstream fin2("test2");
EXPECT_TRUE(fin2.good());
std::ifstream fin3("test3");
EXPECT_FALSE(fin3.good()); // does not exist
std::ifstream fin4("test4");
EXPECT_TRUE(fin4.good());
int n_lines;
fin4 >> n_lines;
EXPECT_EQ(n_lines, 12);
std::string test_line;
for (size_t i = 0; i < 8; ++i) {
std::getline(fin4, test_line);