-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathsystem_tester.h
375 lines (336 loc) · 14.1 KB
/
system_tester.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/*!
* \file systemTest.h
* \author Robert 'Bob' Caddy ([email protected])
* \brief Header file for the tools to run a system test
* \date 2021-08-30
*
*/
#pragma once
// STL includes
#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
// External Libraries and Headers
#include <H5Cpp.h>
/*!
* \brief This namespace contains one class, SystemTestRunner, whose
* purpose is to (as you might expect) run system tests.
*/
namespace systemTest
{
/*!
* \brief Runs a system test using the full test name to determine all
* paths.
*
* \details By default this class uses the full name of your test, i.e. the test
* suite name plus the test name, along with some global variables to
* determine the paths to all the input files. The global variables are all
* set in main_tests.cpp and are the path to the Cholla directory, the make
* type being used, and the machine being run on. If the main function does
* get those it will throw an error so that error checking is not done here.
*
* To run a system test simply name the test according to convetion and put
* the input file in the `cholla/src/system_tests/input_files` directory and
* the data file in the `cholla/src/system_tests/fiducial_data` directory.
* Then name the files `testSuiteName_testCaseName` with the `.txt` or `.h5`
* extension respectively. If this class can't find the files it will
* throw an error with the path it searched. All the output files from the
* test are deposited in `cholla/bin/testSuiteName_testCaseName`
*
* More advanced functionality is provided with a series of member functions
* that allow you to programmatically generate the fiducial HDF5 file,
* choose which datasets to compare, whether or not to compare the number of
* time steps, etc.
*
*/
class SystemTestRunner;
} // namespace systemTest
class systemTest::SystemTestRunner
{
public:
/// The number of MPI ranks, defaults to 1
size_t numMpiRanks = 1;
/*!
* \brief Set the parameters that Cholla launches with, potentially entirely
* replacing the need for a settings file. A string of the launch parameters
* that will override the values in the settings file (if given). Any of
* Cholla's standard launch paramters work except `outdir` as that is
* reserved for usage in the systemTest::SystemTestRunner.runTest() method
*/
std::string chollaLaunchParams;
/*!
* \brief Run the system test that has been set up
*
*/
void runTest();
void launchCholla();
void openHydroTestData();
/*!
* \brief Get the Cholla Path object
*
* \return std::string The path to the Cholla executable
*/
std::string getChollaPath(){return _chollaPath;};
/*!
* \brief Get the Cholla Settings File Path object
*
* \return std::string The full filename/path to the settings file used to
* initialize Cholla
*/
std::string getChollaSettingsFilePath(){return _chollaSettingsPath;};
/*!
* \brief Get the Output Directory object
*
* \return std::string The path to the directory where all the output is
* stored
*/
std::string getOutputDirectory(){return _outputDirectory;};
/*!
* \brief Get the Console Output Path object
*
* \return std::string The full filename/path to the file where all the
* console output is stored
*/
std::string getConsoleOutputPath(){return _consoleOutputPath;};
/*!
* \brief Get the Fiducial File object
*
* \return H5::H5File
*/
H5::H5File getFiducialFile(){return _fiducialFile;};
/*!
* \brief Get the Test File object
*
* \param index The MPI rank of the file you want to return. Defaults to 0
* \return H5::H5File
*/
H5::H5File getTestFile(size_t const &i = 0){return _testHydroFieldsFileVec[i];};
/*!
* \brief Get the vector of datasets that will be tested
*
* \return std::vector<std::string>
*/
std::vector<std::string> getDataSetsToTest(){return _fiducialDataSetNames;};
/*!
* \brief Choose which datasets to test. By default it tests all the
* datasets in the fiducial data. A warning will be thrown if not all the
* datasets are being tested. Note that any call to this function will
* overwrite the default values
*
* \param[in] dataSetNames A std::vector of std::strings where each entry is
* a dataset name. Note that it is case sensitive
*/
void setDataSetsToTest(std::vector<std::string> const &dataSetNames)
{_fiducialDataSetNames = dataSetNames;};
/*!
* \brief Set the Compare Num Time Steps object
*
* \param[in] compare Defaults to `true`. If false then the number of timesteps
* is not compared.
*/
void setCompareNumTimeSteps(bool const &compare)
{_compareNumTimeSteps = compare;};
/*!
* \brief Set or add a fiducial dataset
*
* \param[in] fieldName The name of the field to be added
* \param[in] dataArr The std::vector for the data vector to be added as
* a data set
*/
void setFiducialData(std::string const &fieldName,
std::vector<double> const &dataVec);
/*!
* \brief Set the Fiducial Num Time Steps object
*
* \param numTimeSteps The number of time steps in the fiducial data
*/
void setFiducialNumTimeSteps(int const &numTimeSteps)
{_numFiducialTimeSteps = numTimeSteps;};
/*!
* \brief Generate an vector of the specified size populated by the specified
* value.
*
* \param[in] value The value to populate the vector with
* \param[in] nx (optional) The size of the field in the x-direction.
* Defaults to 1
* \param[in] ny (optional) The size of the field in the y-direction.
* Defaults to 1
* \param[in] nz (optional) The size of the field in the z-direction.
* Defaults to 1
* \return std::vector<double> A 1-dimensional std::vector of the required
* size containing the data.
*/
std::vector<double> generateConstantData(double const &value,
size_t const &nx=1,
size_t const &ny=1,
size_t const &nz=1);
/*!
* \brief Load the test data for physical fields from the HDF5 file(s). If
* there is more than one HDF5 file then it concatenates the contents into a
* single vector. Particle data is handeled with _loadTestParticleData
*
* \param[in] dataSetName The name of the dataset to get
* \param[out] testDims An vector with the length of each dimension in it
* \return std::vector<double> A vector containing the data
*/
std::vector<double> loadTestFieldData(std::string dataSetName,
std::vector<size_t> &testDims);
/*!
* \brief Generate a std::vector of the specified size populated by a sine
* wave. The equation used to generate the wave is:
*
* wave = offset + amplitude * sin(kx*xIndex + ky*yIndex + kz*zIndex + phase)
*
* \param[in] offset Flat offset from zero
* \param[in] amplitude Amplitude of the wave
* \param[in] kx The x component of the wave vector in pixel units
* \param[in] ky The y component of the wave vector in pixel units
* \param[in] kz The z component of the wave vector in pixel units
* \param[in] phase Phase of the sine wave
* \param[in] nx (optional) The size of the field in the x-direction.
* Defaults to 1
* \param[in] ny (optional) The size of the field in the y-direction.
* Defaults to 1
* \param[in] nz (optional) The size of the field in the z-direction.
* Defaults to 1
* \return std::vector<double> A 1-dimensional std::vector of the required
* size containing the data.
*/
std::vector<double> generateSineData(double const &offset,
double const &litude,
double const &kx,
double const &ky,
double const &kz,
double const &phase,
size_t const &nx=1,
size_t const &ny=1,
size_t const &nz=1);
// Constructor and Destructor
/*!
* \brief Construct a new System Test Runner object
*
* \param[in] particleData Is there particle data?
* \param[in] hydroData Is there hydro data?
* \param[in] useFiducialFile Indicate if you're using a HDF5 file or will
* generate your own. Defaults to `true`, i.e. using an HDF5 file. Set to
* `false` to generate your own
* \param[in] useSettingsFile Indicate if you're using a settings file. If
* `true` then the settings file is automatically found based on the naming
* convention. If false then the user MUST provide all the required settings
* with the SystemTestRunner::setChollaLaunchParams method
*/
SystemTestRunner(bool const &particleData=false,
bool const &hydroData=true,
bool const &useFiducialFile=true,
bool const &useSettingsFile=true);
~SystemTestRunner();
private:
/// The fiducial dat file
H5::H5File _fiducialFile;
/// The test hydro field data files
std::vector<H5::H5File> _testHydroFieldsFileVec;
/// The test particle data files
std::vector<H5::H5File> _testParticlesFileVec;
/// The path to the Cholla executable
std::string _chollaPath;
/// The full name of the test with an underscore instead of a period. This
/// is the name of many of the input files, the output directory, etc
std::string _fullTestFileName;
/// The path to the Cholla settings file
std::string _chollaSettingsPath;
/// The path to the fiducial data file
std::string _fiducialFilePath;
/// The path to the output directory
std::string _outputDirectory;
/// The path and name of the console output file
std::string _consoleOutputPath;
/// A list of all the data set names in the fiducial data file
std::vector<std::string> _fiducialDataSetNames;
/// A list of all the data set names in the test data file
std::vector<std::string> _testDataSetNames;
/// The number of fiducial time steps
int _numFiducialTimeSteps;
/// Map of fiducial data sets if we're not using a fiducial file
std::unordered_map<std::string, std::vector<double>> _fiducialDataSets;
/// The test particle IDs
std::vector<double> _testParticleIDs;
/// The total number of particles in the test dataset
size_t _testTotalNumParticles=0;
/// The fiducial particle IDs
std::vector<double> _fiducialParticleIDs;
/// The total number of particles in the fiducial dataset
size_t _fiducialTotalNumParticles=0;
/// Flag to indicate if a fiducial HDF5 data file is being used or a
/// programmatically generated H5File object. `true` = use a file, `false` =
/// use generated H5File object
bool _fiducialFileExists = false;
/// Flag to choose whether or not to compare the number of time steps
bool _compareNumTimeSteps = true;
/// Flag to indicate whether or not there is hydro field data
/// If true then hydro data files are searched for and will be compared to
/// fiducial values. If false then it is assumed that the test produces no
/// hydro field data
bool _hydroDataExists = true;
/// Flag to indicate whether or not there is particle data
/// If true then particle data files are searched for and will be compared
/// to fiducial values. If false then it is assumed that the test produces
/// no particle data
bool _particleDataExists = false;
/*!
* \brief Move a file. Throws an exception if the file does not exist.
* or if the move was unsuccessful
*
* \param[in] sourcePath The path the the file to be moved
* \param[in] destinationDirectory The path to the director the file should
* be moved to
*/
void _safeMove(std::string const &sourcePath,
std::string const &destinationDirectory);
/*!
* \brief Checks if the given file exists. Throws an exception if the
* file does not exist.
*
* \param[in] filePath The path to the file to check for
*/
void _checkFileExists(std::string const &filePath);
/*!
* \brief Using GTest assertions to check if the fiducial and test data have
* the same number of time steps
*
*/
void _checkNumTimeSteps();
/*!
* \brief Load the test data for particles from the HDF5 file(s). If
* there is more than one HDF5 file then it concatenates the contents into a
* single vector. Field data is handeled with _loadTestFieldData
*
* \param[in] dataSetName The name of the dataset to get
* \return std::vector<double> A vector containing the data
*/
std::vector<double> _loadTestParticleData(std::string const &dataSetName);
/*!
* \brief Load the test data for physical fields from the HDF5 file or
* returns the user set vector.
* Particle data is handeled with _loadFiducialParticleData.
*
* \param[in] dataSetName The name of the dataset to get
* \return std::vector<double> A vector with the contents of the data set
*/
std::vector<double> _loadFiducialFieldData(std::string const &dataSetName);
/*!
* \brief Load the fiducial data for particles from the HDF5 file or return
* the user set vector. Field data is handeled with _loadFiducialFieldData
*
* \param[in] dataSetName The name of the dataset to get
* \return std::vector<double> A vector containing the data
*/
std::vector<double> _loadFiducialParticleData(std::string const &dataSetName);
/*!
* \brief Return a vector of all the dataset names in the given HDF5 file
*
* \param[in] inputFile The HDF5 file to find names in
* \return std::vector<std::string>
*/
std::vector<std::string> _findDataSetNames(H5::H5File const &inputFile);
}; // End of class systemTest::SystemTestRunner