MoCSI API Reference
Loading...
Searching...
No Matches
OutputCsvTool.h
Go to the documentation of this file.
1#ifndef OUTPUT_CSV_TOOL_H
2#define OUTPUT_CSV_TOOL_H
3
4#define OUTPUT_CSV_TOOL_VERSION "8"
5
6#include <fstream>
7#include <iomanip>
8#include <iostream>
9#include <memory>
10#include <ostream>
11#include <string>
12#include <valarray>
13#include <vector>
14
15#include "../../src/GenericManagingModule.h"
16#include "../../src/ModuleFactory.h"
17
18#ifdef MPI_PRESENT
19#include <mpi.h>
20
21#endif
22
45template <typename T>
47{
48 private:
49 static bool m_registered;
50 std::string m_ini_filepath{"tools/OutputCsvTool.ini"};
51 std::string m_output_filepath{};
52 std::string m_save_mode{};
53 std::vector<std::string>
54 m_save_fields; // Right now this lives only in the local ini, but we make it live in
55 // the sim class, so that the other modules can write their save request
56 // to it.
57 std::vector<int> m_save_steps{};
58 int m_currentIndex{0};
59 std::ofstream output_file;
60
61 void _writeData();
62 void _writeDataSurface(int period);
63
64#ifdef MPI_PRESENT
67 int displacement{0};
68 int start{0};
69 int count{0};
72 long data_sizes[2];
73 std::string footer{};
74 void _writeDataMpi();
76 int _calcDisplacement(const std::valarray<T>& field);
77 void _writeFooter();
78#endif
79
80 public:
82 bool setup(std::vector<std::shared_ptr<GenericSubmodule<T>>> all_submodules) override;
83 bool exec(std::string_view param) override; // main functionality of the module
84
85 bool init() override;
86 bool preTimeStep() override { return true; };
87 bool postNonLinIter() override { return true; };
88 bool postTimeStep() override;
89 bool output() override;
90 std::vector<std::string> getChainInsertion() const override
91 {
92 return this->ini_file_data.getStringVectorParameters("chain_insertion");
93 };
94
95 static std::shared_ptr<GenericManagingModule<T>> createMethode(SimulationClassBase<T>* sim)
96 {
97 return std::make_shared<OutputCsvTool<T>>(sim);
98 };
99 static std::string getName() { return "OutputCsvTool"; };
100 std::string_view getNameLocal() const override { return "OutputCsvTool"; };
101};
102
103// ================= Implementation =================
104
105template <typename T>
107{
108 try
109 {
110 std::string ini_folder_path{
111 this->sim->m_simulation_config.getStringParameters("ini_folder_path")};
112 this->ini_file_data.loadUserInput(ini_folder_path + m_ini_filepath);
113 m_output_filepath = this->ini_file_data.getStringParameters("file_path");
114 m_save_mode = this->ini_file_data.getStringParameters("save_mode");
115 m_save_fields = this->ini_file_data.getStringVectorParameters("save_fields");
117 }
118 catch (const BadInput& e)
119 {
120 std::cerr << e.what() << '\n';
121 }
122}
123
124template <typename T>
126{
127#ifdef MPI_PRESENT
128 // Get information necessary to calculate byte sizes of output
129 numerical_layers = this->sim->m_simulation_config.getIntParameters("numerical_layers");
130 local_number_of_facets = this->sim->m_simulation_config.getIntParameters("number_of_facets");
132 this->sim->m_simulation_config.getIntParameters("global_number_of_facets");
133 // Set datatype of field to the one used across this simulation
137 if (this->sim->my_rank == 0)
138 {
139 // Flush the file
140 std::ofstream file(m_output_filepath);
141 }
142#else
143 // Flush the file
144 std::ofstream file(m_output_filepath);
145#endif
146 if (m_save_mode == "specific_time_steps")
147 {
148 try
149 {
150 std::vector<double> save_steps{
151 this->ini_file_data.getDoubleVectorParameters("save_time_steps")};
152 for (int i{0}; i < save_steps.size(); i++)
153 {
154 m_save_steps.push_back(static_cast<int>(save_steps[i]));
155 }
156 }
157 catch (const BadInput& e)
158 {
159 std::cerr << e.what() << '\n';
160 }
161 }
162 return true;
163}
164
165template <typename T>
166bool OutputCsvTool<T>::exec(std::string_view param)
167{
168 if (param == "InitChain")
169 {
170 return init();
171 }
172 if (param == "PreTimeStepChain")
173 {
174 return preTimeStep();
175 }
176 if (param == "PostNonLinIterChain")
177 {
178 return postNonLinIter();
179 }
180 if (param == "PostTimeStepChain")
181 {
182 return postTimeStep();
183 }
184 if (param == "OutputChain")
185 {
186 return output();
187 }
188 return false;
189}
190
191template <typename T>
193{
194#ifdef MPI_PRESENT
195 MPI_File_open(MPI_COMM_WORLD, m_output_filepath.c_str(), MPI_MODE_WRONLY | MPI_MODE_CREATE,
197#endif
198 return true;
199}
200
201template <typename T>
203{
204 if ((m_save_mode == "specific_time_steps") && (m_currentIndex < m_save_steps.size())
205 && (m_save_steps[m_currentIndex] == this->sim->time_step))
206 {
207#ifdef MPI_PRESENT
209#else
210 _writeData();
211#endif
212 m_currentIndex++;
213 }
214 else if ((m_save_mode == "specific_time_steps_surface")
215 && (m_currentIndex < m_save_steps.size())
216 && (m_save_steps[m_currentIndex] == this->sim->time_step))
217 {
218#ifdef MPI_PRESENT
219 _writeDataSurfaceMpi(this->sim->m_simulation_config.getIntParameters("numerical_layers"));
220#else
221 _writeDataSurface(this->sim->m_simulation_config.getIntParameters("numerical_layers"));
222#endif
223 m_currentIndex++;
224 }
225 else if ((m_save_mode == "interval")
226 && (this->sim->time_step % this->ini_file_data.getIntParameters("interval") == 0))
227 {
228#ifdef MPI_PRESENT
230#else
231 _writeData();
232#endif
233 }
234 else if ((m_save_mode == "interval_surface")
235 && (this->sim->time_step % this->ini_file_data.getIntParameters("interval") == 0))
236 {
237#ifdef MPI_PRESENT
238 _writeDataSurfaceMpi(this->sim->m_simulation_config.getIntParameters("numerical_layers"));
239#else
240 _writeDataSurface(this->sim->m_simulation_config.getIntParameters("numerical_layers"));
241#endif
242 }
243#ifdef MPI_PRESENT
244 if (this->sim->elapsed_time + this->sim->m_simulation_config.getIntParameters("time_delta")
245 > this->sim->m_simulation_config.getIntParameters("time_max")
246 && !(footer.empty()))
247 {
248 // If this is the last time step, you can write the footer already.
249 _writeFooter();
250 }
251#endif
252 return true;
253}
254
255template <typename T>
257{
258#ifdef MPI_PRESENT
259 // Check to only write footer, if it hasn't already been written (in preTimeStep)
260 if (!(footer.empty()))
261 {
262 _writeFooter();
263 }
265#else
266 if (m_save_mode == "surface")
267 {
268 _writeDataSurface(this->sim->m_simulation_config.getIntParameters("numerical_layers"));
269 }
270 else
271 {
272 _writeData();
273 }
274#endif
275 return true;
276}
277
284template <typename T>
286{
287 output_file.open(m_output_filepath, std::ios::app);
288
289 for (const auto& field_name : m_save_fields)
290 {
291 output_file << field_name << "," << this->sim->elapsed_time << ",";
292 const std::valarray<T>& field{this->sim->getField(field_name)};
293 for (int i{0}; i < field.size() - 1; i++)
294 {
295 output_file << field[i] << std::setprecision(15) << ",";
296 }
297 output_file << field[field.size() - 1] << std::setprecision(15) << "\n";
298 }
299
300 output_file.close();
301}
302
303#ifdef MPI_PRESENT
311template <typename T>
313{
315 {
316 std::cerr << "Trying to access an unopened file. Please also use init and output chains "
317 "when using MPI I/O.\n";
318 throw std::runtime_error(
319 "Trying to access an unopened file. Please also use init and output chains when using "
320 "MPI I/O.\n");
321 }
322 for (const auto& field_name : m_save_fields)
323 {
324 const std::valarray<T>& field{this->sim->getField(field_name)};
328 // Update the starting position (in bytes) for the next write
329 // Each process from the first k can write at position rank * size of its array.
330 // Each process > k needs to account for the larger k processes to determine its pointer
331 // start.
333 {
335 footer += field_name + "," + std::to_string(this->sim->elapsed_time) + ","
336 + std::to_string(numerical_layers * global_number_of_facets) + ",";
337 }
338 else if (field.size() == local_number_of_facets)
339 {
341 footer += field_name + "," + std::to_string(this->sim->elapsed_time) + ","
342 + std::to_string(global_number_of_facets) + ",";
343 }
344 else
345 {
346 start += type_size * field.size() * this->sim->world_size;
347 footer += field_name + "," + std::to_string(this->sim->elapsed_time) + ","
348 + std::to_string(field.size() * this->sim->world_size) + ",";
349 }
350 }
351}
352#endif
353
362template <typename T>
364{
365 output_file.open(m_output_filepath, std::ios::app);
366
367 for (const auto& field_name : m_save_fields)
368 {
369 output_file << field_name << "," << this->sim->elapsed_time << ",";
370 const std::valarray<T>& field{this->sim->getField(field_name)};
371 for (int i{0}; i < static_cast<int>(field.size() / period) - 1; i++)
372 {
373 output_file << field[i * period] << std::setprecision(15) << ",";
374 }
375 output_file << field[field.size() - period] << std::setprecision(15) << "\n";
376 }
377
378 output_file.close();
379}
380
381#ifdef MPI_PRESENT
391template <typename T>
393{
395 {
396 std::cerr << "Trying to access an unopened file. Please also use init and output chains "
397 "when using MPI I/O.\n";
398 throw std::runtime_error(
399 "Trying to access an unopened file. Please also use init and output chains when using "
400 "MPI I/O.\n");
401 }
402 for (const auto& field_name : m_save_fields)
403 {
404 // Get only the surface values of the field variable.
405 const std::valarray<T>& field{this->sim->getField(field_name)};
406 std::valarray<T> field_surface(field.size() / period);
407 for (int i{0}; i < field_surface.size(); i++)
408 {
410 }
411 // Update the starting position (in bytes) for the next write
412 // Each process from the first k can write at position rank * size of its array.
413 // Each process > k needs to account for the larger k processes to determine its pointer
414 // start.
418 // Update the starting position (in bytes) for the next write
420 {
422 footer += field_name + "," + std::to_string(this->sim->elapsed_time) + ","
423 + std::to_string(numerical_layers * global_number_of_facets / period) + ",";
424 }
425 }
426}
427
437template <typename T>
438int OutputCsvTool<T>::_calcDisplacement(const std::valarray<T>& field)
439{
442 {
443 // For the block of same size processes, displacement is rank * local_field_size *
444 // data_type_byte_size.
445 if (this->sim->my_rank < this->sim->number_of_larger_procs)
446 {
447 proc_displacement = this->sim->my_rank * field.size() * type_size;
448 }
449 // For the second block, add the first block displacement and count how many second block
450 // processes are between the targeted position and the first block.
451 // local_field_size_large_proc = local_field_size_small_proc + numerical_layers.
452 else
453 {
455 (this->sim->number_of_larger_procs * (field.size() + numerical_layers)
456 + (this->sim->my_rank - this->sim->number_of_larger_procs) * field.size())
457 * type_size;
458 }
459 }
460 else if (field.size() == local_number_of_facets)
461 {
462 // For the block of same size processes, displacement is rank * local_field_size *
463 // data_type_byte_size.
464 if (this->sim->my_rank < this->sim->number_of_larger_procs)
465 {
466 proc_displacement = this->sim->my_rank * field.size() * type_size;
467 }
468 // For the second block, add the first block displacement and count how many second block
469 // processes are between the targeted position and the first block.
470 // local_field_size_large_proc = local_field_size_small_proc + 1.
471 else
472 {
474 (this->sim->number_of_larger_procs * (field.size() + 1)
475 + (this->sim->my_rank - this->sim->number_of_larger_procs) * field.size())
476 * type_size;
477 }
478 }
479 else
480 {
482 }
483 return proc_displacement;
484}
485
493template <typename T>
495{
497 int data_size_displacement{static_cast<int>(start + footer_type_size * footer.size())};
498 if (this->sim->my_rank == 0)
499 {
503 data_sizes[1] = footer.size();
506 }
507}
508#endif
509
510template <typename T>
512
513#endif // OUTPUT_CSV_TOOL_H
This error class inherits from std::exception and marks faulty parameter or CL inputs....
Definition IniParser.h:71
Concrete implementation of a matrix class representing a Compressed Sparse Rows (CSR) matrix....
Definition CsrMatrix.h:35
CsrSparseMatrix()
Constructor for an empty CsrSparseMatrix object. Leaves all storage arrays empty but sets the flag to...
Definition CsrMatrix.h:92
Abstract base class for the managing modules. Managing modules are the highest tier of modules and ar...
Definition GenericManagingModule.h:29
InputManager ini_file_data
Definition GenericManagingModule.h:38
SimulationClassBase< T > * sim
Definition GenericManagingModule.h:31
std::vector< std::string > m_generic_submodules
Definition GenericManagingModule.h:36
std::pair< int, int > size() const
Function that returns the size of the matrix as a pair in (rows, columns) format.
Definition GenericMatrix.h:118
std::vector< std::string > getStringVectorParameters(const std::string &key) const
Definition InputManager.cpp:503
void loadUserInput(const std::string &user_ini_file_path)
Public function to load and merge user supplied ini files with the already stored data.
Definition InputManager.cpp:42
std::string getStringParameters(const std::string &key) const
Getter function to access the m_parameters map and returns a string. Throws a BadInput error,...
Definition InputManager.cpp:493
static constexpr bool registerModule(std::string name, creation_method module) noexcept
Function that adds a module to the module registry map.
Definition ModuleFactory.h:75
Saves specified simulation field data into CSV files.
Definition OutputCsvTool.h:47
bool output() override
Definition OutputCsvTool.h:256
bool preTimeStep() override
Definition OutputCsvTool.h:86
std::string_view getNameLocal() const override
Definition OutputCsvTool.h:100
bool postNonLinIter() override
Definition OutputCsvTool.h:87
bool init() override
Definition OutputCsvTool.h:192
static std::string getName()
Definition OutputCsvTool.h:99
bool exec(std::string_view param) override
Definition OutputCsvTool.h:166
bool setup(std::vector< std::shared_ptr< GenericSubmodule< T > > > all_submodules) override
Definition OutputCsvTool.h:125
OutputCsvTool(SimulationClassBase< T > *sim)
Definition OutputCsvTool.h:106
static std::shared_ptr< GenericManagingModule< T > > createMethode(SimulationClassBase< T > *sim)
Definition OutputCsvTool.h:95
std::vector< std::string > getChainInsertion() const override
Definition OutputCsvTool.h:90
bool postTimeStep() override
Definition OutputCsvTool.h:202