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 "9"
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 << "[OutputCsvTool]: " << e.what() << '\n';
121 throw BadInput(static_cast<std::string>("[OutputCsvTool]: ")
122 + static_cast<std::string>(e.what()));
123 }
124}
125
126template <typename T>
128{
129#ifdef MPI_PRESENT
130 // Get information necessary to calculate byte sizes of output
131 numerical_layers = this->sim->m_simulation_config.getIntParameters("numerical_layers");
132 local_number_of_facets = this->sim->m_simulation_config.getIntParameters("number_of_facets");
134 this->sim->m_simulation_config.getIntParameters("global_number_of_facets");
135 // Set datatype of field to the one used across this simulation
139 if (this->sim->my_rank == 0)
140 {
141 // Flush the file
142 std::ofstream file(m_output_filepath);
143 }
144#else
145 // Flush the file
146 std::ofstream file(m_output_filepath);
147#endif
148 if (m_save_mode == "specific_time_steps")
149 {
150 try
151 {
152 std::vector<double> save_steps{
153 this->ini_file_data.getDoubleVectorParameters("save_time_steps")};
154 for (int i{0}; i < save_steps.size(); i++)
155 {
156 m_save_steps.push_back(static_cast<int>(save_steps[i]));
157 }
158 }
159 catch (const BadInput& e)
160 {
161 std::cerr << "[OutputCsvTool]: " << e.what() << '\n';
162 throw BadInput(static_cast<std::string>("[OutputCsvTool]: ")
163 + static_cast<std::string>(e.what()));
164 }
165 }
166 return true;
167}
168
169template <typename T>
170bool OutputCsvTool<T>::exec(std::string_view param)
171{
172 if (param == "InitChain")
173 {
174 return init();
175 }
176 if (param == "PreTimeStepChain")
177 {
178 return preTimeStep();
179 }
180 if (param == "PostNonLinIterChain")
181 {
182 return postNonLinIter();
183 }
184 if (param == "PostTimeStepChain")
185 {
186 return postTimeStep();
187 }
188 if (param == "OutputChain")
189 {
190 return output();
191 }
192 return false;
193}
194
195template <typename T>
197{
198#ifdef MPI_PRESENT
199 MPI_File_open(MPI_COMM_WORLD, m_output_filepath.c_str(), MPI_MODE_WRONLY | MPI_MODE_CREATE,
201#endif
202 return true;
203}
204
205template <typename T>
207{
208 try
209 {
210 if ((m_save_mode == "specific_time_steps") && (m_currentIndex < m_save_steps.size())
211 && (m_save_steps[m_currentIndex] == this->sim->time_step))
212 {
213#ifdef MPI_PRESENT
215#else
216 _writeData();
217#endif
218 m_currentIndex++;
219 }
220 else if ((m_save_mode == "specific_time_steps_surface")
221 && (m_currentIndex < m_save_steps.size())
222 && (m_save_steps[m_currentIndex] == this->sim->time_step))
223 {
224#ifdef MPI_PRESENT
226 this->sim->m_simulation_config.getIntParameters("numerical_layers"));
227#else
228 _writeDataSurface(this->sim->m_simulation_config.getIntParameters("numerical_layers"));
229#endif
230 m_currentIndex++;
231 }
232 else if ((m_save_mode == "interval")
233 && (this->sim->time_step % this->ini_file_data.getIntParameters("interval") == 0))
234 {
235#ifdef MPI_PRESENT
237#else
238 _writeData();
239#endif
240 }
241 else if ((m_save_mode == "interval_surface")
242 && (this->sim->time_step % this->ini_file_data.getIntParameters("interval") == 0))
243 {
244#ifdef MPI_PRESENT
246 this->sim->m_simulation_config.getIntParameters("numerical_layers"));
247#else
248 _writeDataSurface(this->sim->m_simulation_config.getIntParameters("numerical_layers"));
249#endif
250 }
251#ifdef MPI_PRESENT
252 if (this->sim->elapsed_time + this->sim->m_simulation_config.getIntParameters("time_delta")
253 > this->sim->m_simulation_config.getIntParameters("time_max")
254 && !(footer.empty()))
255 {
256 // If this is the last time step, you can write the footer already.
257 _writeFooter();
258 }
259#endif
260 }
261 catch (const BadInput& e)
262 {
263 std::cerr << "[OutputCsvTool]: " << e.what() << '\n';
264 throw BadInput(static_cast<std::string>("[OutputCsvTool]: ")
265 + static_cast<std::string>(e.what()));
266 }
267 return true;
268}
269
270template <typename T>
272{
273#ifdef MPI_PRESENT
274 // Check to only write footer, if it hasn't already been written (in preTimeStep)
275 if (!(footer.empty()))
276 {
277 _writeFooter();
278 }
280#else
281 if (m_save_mode == "surface")
282 {
283 try
284 {
285 _writeDataSurface(this->sim->m_simulation_config.getIntParameters("numerical_layers"));
286 }
287 catch (const BadInput& e)
288 {
289 std::cerr << "[OutputCsvTool]: " << e.what() << '\n';
290 throw BadInput(static_cast<std::string>("[OutputCsvTool]: ")
291 + static_cast<std::string>(e.what()));
292 }
293 }
294 else
295 {
296 _writeData();
297 }
298#endif
299 return true;
300}
301
308template <typename T>
310{
311 output_file.open(m_output_filepath, std::ios::app);
312
313 for (const auto& field_name : m_save_fields)
314 {
315 output_file << field_name << "," << this->sim->elapsed_time << ",";
316 try
317 {
318 const std::valarray<T>& field{this->sim->getField(field_name)};
319 for (int i{0}; i < field.size() - 1; i++)
320 {
321 output_file << field[i] << std::setprecision(15) << ",";
322 }
323 output_file << field[field.size() - 1] << std::setprecision(15) << "\n";
324 }
325 catch (const BadInput& e)
326 {
327 std::cerr << "[OutputCsvTool]: " << field_name
328 << " module not "
329 "loaded or accessable!\n "
330 "[OutputCsvTool]:"
331 << e.what() << '\n';
332 throw BadInput(static_cast<std::string>("[OutputCsvTool]: ") + field_name
333 + static_cast<std::string>(" module "
334 "not loaded or "
335 "accessable!\n [OutputCsvTool]: ")
336 + static_cast<std::string>(e.what()));
337 }
338 }
339
340 output_file.close();
341}
342
343#ifdef MPI_PRESENT
351template <typename T>
353{
355 {
356 std::cerr << "[OutputCsvTool]: Trying to access an unopened file. Please also use init and "
357 "output chains "
358 "when using MPI I/O.\n";
359 throw std::runtime_error(
360 "[OutputCsvTool]: Trying to access an unopened file. Please also use init and output "
361 "chains when using "
362 "MPI I/O.");
363 }
364 for (const auto& field_name : m_save_fields)
365 {
366 try
367 {
368 const std::valarray<T>& field{this->sim->getField(field_name)};
372 // Update the starting position (in bytes) for the next write
373 // Each process from the first k can write at position rank * size of its array.
374 // Each process > k needs to account for the larger k processes to determine its pointer
375 // start.
377 {
379 footer += field_name + "," + std::to_string(this->sim->elapsed_time) + ","
380 + std::to_string(numerical_layers * global_number_of_facets) + ",";
381 }
382 else if (field.size() == local_number_of_facets)
383 {
385 footer += field_name + "," + std::to_string(this->sim->elapsed_time) + ","
386 + std::to_string(global_number_of_facets) + ",";
387 }
388 else
389 {
390 start += type_size * field.size() * this->sim->world_size;
391 footer += field_name + "," + std::to_string(this->sim->elapsed_time) + ","
392 + std::to_string(field.size() * this->sim->world_size) + ",";
393 }
394 }
395 catch (const BadInput& e)
396 {
397 std::cerr << "[OutputCsvTool]: " << field_name
398 << " module not "
399 "loaded or accessable!\n "
400 "[OutputCsvTool]:"
401 << e.what() << '\n';
402 throw BadInput(static_cast<std::string>("[OutputCsvTool]: ") + field_name
403 + static_cast<std::string>(" module "
404 "not loaded or "
405 "accessable!\n [OutputCsvTool]: ")
406 + static_cast<std::string>(e.what()));
407 }
408 }
409}
410#endif
411
420template <typename T>
422{
423 output_file.open(m_output_filepath, std::ios::app);
424
425 for (const auto& field_name : m_save_fields)
426 {
427 output_file << field_name << "," << this->sim->elapsed_time << ",";
428 try
429 {
430 const std::valarray<T>& field{this->sim->getField(field_name)};
431 for (int i{0}; i < static_cast<int>(field.size() / period) - 1; i++)
432 {
433 output_file << field[i * period] << std::setprecision(15) << ",";
434 }
435 output_file << field[field.size() - period] << std::setprecision(15) << "\n";
436 }
437 catch (const BadInput& e)
438 {
439 std::cerr << "[OutputCsvTool]: " << field_name
440 << " module not "
441 "loaded or accessable!\n "
442 "[OutputCsvTool]:"
443 << e.what() << '\n';
444 throw BadInput(static_cast<std::string>("[OutputCsvTool]: ") + field_name
445 + static_cast<std::string>(" module "
446 "not loaded or "
447 "accessable!\n [OutputCsvTool]:")
448 + static_cast<std::string>(e.what()));
449 }
450 }
451
452 output_file.close();
453}
454
455#ifdef MPI_PRESENT
465template <typename T>
467{
469 {
470 std::cerr << "[OutputCsvTool]: Trying to access an unopened file. Please also use init and "
471 "output chains "
472 "when using MPI I/O.\n";
473 throw std::runtime_error(
474 "[OutputCsvTool]: Trying to access an unopened file. Please also use init and output "
475 "chains when using "
476 "MPI I/O.");
477 }
478 for (const auto& field_name : m_save_fields)
479 {
480 // Get only the surface values of the field variable.
481 try
482 {
483 const std::valarray<T>& field{this->sim->getField(field_name)};
484 std::valarray<T> field_surface(field.size() / period);
485 for (int i{0}; i < field_surface.size(); i++)
486 {
488 }
489 // Update the starting position (in bytes) for the next write
490 // Each process from the first k can write at position rank * size of its array.
491 // Each process > k needs to account for the larger k processes to determine its pointer
492 // start.
496 // Update the starting position (in bytes) for the next write
498 {
500 footer += field_name + "," + std::to_string(this->sim->elapsed_time) + ","
502 + ",";
503 }
504 }
505 catch (const BadInput& e)
506 {
507 std::cerr << "[OutputCsvTool]: " << field_name
508 << " module not "
509 "loaded or accessable!\n "
510 "[OutputCsvTool]:"
511 << e.what() << '\n';
512 throw BadInput(static_cast<std::string>("[OutputCsvTool]: ") + field_name
513 + static_cast<std::string>(" module "
514 "not loaded or "
515 "accessable!\n [OutputCsvTool]: ")
516 + static_cast<std::string>(e.what()));
517 }
518 }
519}
520
530template <typename T>
531int OutputCsvTool<T>::_calcDisplacement(const std::valarray<T>& field)
532{
535 {
536 // For the block of same size processes, displacement is rank * local_field_size *
537 // data_type_byte_size.
538 if (this->sim->my_rank < this->sim->number_of_larger_procs)
539 {
540 proc_displacement = this->sim->my_rank * field.size() * type_size;
541 }
542 // For the second block, add the first block displacement and count how many second block
543 // processes are between the targeted position and the first block.
544 // local_field_size_large_proc = local_field_size_small_proc + numerical_layers.
545 else
546 {
548 (this->sim->number_of_larger_procs * (field.size() + numerical_layers)
549 + (this->sim->my_rank - this->sim->number_of_larger_procs) * field.size())
550 * type_size;
551 }
552 }
553 else if (field.size() == local_number_of_facets)
554 {
555 // For the block of same size processes, displacement is rank * local_field_size *
556 // data_type_byte_size.
557 if (this->sim->my_rank < this->sim->number_of_larger_procs)
558 {
559 proc_displacement = this->sim->my_rank * field.size() * type_size;
560 }
561 // For the second block, add the first block displacement and count how many second block
562 // processes are between the targeted position and the first block.
563 // local_field_size_large_proc = local_field_size_small_proc + 1.
564 else
565 {
567 (this->sim->number_of_larger_procs * (field.size() + 1)
568 + (this->sim->my_rank - this->sim->number_of_larger_procs) * field.size())
569 * type_size;
570 }
571 }
572 else
573 {
575 }
576 return proc_displacement;
577}
578
586template <typename T>
588{
590 int data_size_displacement{static_cast<int>(start + footer_type_size * footer.size())};
591 if (this->sim->my_rank == 0)
592 {
596 data_sizes[1] = footer.size();
599 }
600}
601#endif
602
603template <typename T>
605
606#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:37
CsrSparseMatrix()
Constructor for an empty CsrSparseMatrix object. Leaves all storage arrays empty but sets the flag to...
Definition CsrMatrix.h:94
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:120
std::vector< std::string > getStringVectorParameters(const std::string &key) const
Definition InputManager.cpp:508
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:45
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:498
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:271
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:196
static std::string getName()
Definition OutputCsvTool.h:99
bool exec(std::string_view param) override
Definition OutputCsvTool.h:170
bool setup(std::vector< std::shared_ptr< GenericSubmodule< T > > > all_submodules) override
Definition OutputCsvTool.h:127
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:206