TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Ecrire_YAML.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 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.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* 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.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER 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;
12* 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.
13*
14*****************************************************************************/
15
16#include <Ecrire_YAML.h>
17#include <Equation_base.h>
18#include <Postraitement.h>
19#include <Probleme_base.h>
20
21/*! @brief Generate the YAML file that will be read for checkpoint
22 */
23void Ecrire_YAML::write_checkpoint_file(const std::string& yaml_fname)
24{
26 {
27 set_data();
28 write_checkpoint_restart_file(1 /*save*/, yaml_fname);
29 }
31}
32
33/*! @brief Generate the YAML file that will be read for restart
34 */
35void Ecrire_YAML::write_restart_file(const std::string& yaml_fname)
36{
38 {
39 set_data();
40 write_checkpoint_restart_file(0 /*restart*/, yaml_fname);
41 }
43}
44
45/*! @brief Generate the YAML file that will be read with champ_fonc_reprise
46 */
47void Ecrire_YAML::write_champ_fonc_restart_file(const std::string& yaml_fname)
48{
50 write_checkpoint_restart_file(0 /*restart*/, yaml_fname); // The data have been set in champ_fonc_reprise as we only need to restore some of them (not all unknowns)
52}
53
54/*! @brief Private method to generate the whole YAML file for checkpoint/restart
55 * Here is how the checkpoint file is organized:
56 * - every unknown is stored in its own dataset.
57 * - for all parallel datasets, the first dimension has to do with the rank of the processor,
58 * which means in parallel, for each unknown, every processor writes collectively in the same dataset into their dedicated portion.
59 * - for all datasets, the next dimension (either the first or the second if we have a parallel dataset) has to do with the number of backups performed.
60 * For simple_sauvegarde, this dimension has a size of 1 as we only keep the last backup.
61 * For classic sauvegarde, this dimension has a size of $nb_iter_max (can be managed in Schema_Temps_base). So the number of backups that we can store is limited !
62 * If we exceed this number, we will overwrite the first backups !
63 * - we track the timesteps that are being stored in the checkpoint file in a specific dataset (time/t)
64 * and we also provide the index of the latest backup in time/last_iteration (this is important for restart so we can find the right slot to recover the data).
65 *
66 */
67void Ecrire_YAML::write_checkpoint_restart_file(bool save, const std::string& yaml_fname)
68{
69 std::string text = "pdi:";
70
71 declare_metadata(save, text);
72 declare_data(save, text);
73
74 // declare plugins
75 begin_bloc("plugins:", text);
76#ifndef NDEBUG
77 add_line("trace:", text);
78#endif
80 add_line("mpi:", text);
81 add_line("decl_hdf5:", text);
82
83 for(unsigned i_pb=0; i_pb<pbs_.size(); i_pb++)
84 {
85 if(save)
86 {
87 // if the checkpoint file already exists, we erase it and create a brand new one
88 write_file_initialization(i_pb, text);
89 write_config_file_initialization(i_pb, text);
90 // block to write the data
91 write_data_for_checkpoint(i_pb, 1 /* writing all local data */, text);
92 write_data_for_checkpoint(i_pb, 0 /* writing all global data */, text);
93 // block to write the saved timesteps
94 write_time_scheme(1, pbs_[i_pb].filename, text);
95 // writing the types of the fields we want to save
96 write_fields_types_for_checkpoint(i_pb, text);
97 // writing format of the file
98 write_format_for_checkpoint(pbs_[i_pb].filename, text);
99 }
100 else
101 {
102 write_data_for_restart(i_pb, text);
103 }
104 write_config_file(save, i_pb, text);
105 }
106
107 SFichier fic(yaml_fname.c_str());
108 fic << text;
109}
110
111/*! \brief Writes the block in the YAML file that will trigger the creation of the configuration file
112 */
113void Ecrire_YAML::write_config_file_initialization(int pb_i, std::string& text)
114{
115 std::string para = "- file: " + pbs_[pb_i].configFilename_;
116 begin_bloc(para, text);
117 std::string event = "on_event: InitConfig";
118 add_line(event, text);
119 add_line("collision_policy: replace_and_warn # print a warning if file or any of dataset already exist", text);
121 add_line("communicator: $MPI_COMM_SELF", text);
122
123 // we need to dump a single variable with PDI for the collision policy to work
124 begin_bloc("write:", text);
125 declare_scalar("nb_proc", "int", text);
126 end_bloc();
127 end_bloc();
128}
129
130/*! \brief Writes the block in the YAML file that will trigger IO actions for the configuration file
131 */
132void Ecrire_YAML::write_config_file(bool save, int pb_i, std::string& text)
133{
134 // General information about the number of procs
135 std::string para = "- file: " + pbs_[pb_i].configFilename_;
136 begin_bloc(para, text);
137 std::string event = save ? "on_event: WriteConfig" : "on_event: ReadConfig";
138 add_line(event, text);
140 add_line("communicator: $MPI_COMM_SELF", text);
141 std::string ioAction = save ? "write:" : "read:";
142 begin_bloc(ioAction, text);
143 // nb_proc is written during the file initialization
144 if (!save)
145 declare_scalar("nb_proc", "int", text);
146 declare_scalar("nb_nodes", "int", text);
147 end_bloc();
148 end_bloc();
149
151 write_partition(save, pb_i, text);
152}
153
154/*! \brief Writes the block in the YAML file to manage the node ids for each processor
155 */
156void Ecrire_YAML::write_partition(bool save, int pb_i, std::string& text)
157{
158 if (save)
159 {
160 add_line("# For every processor in the world, save the rank of its group in a unique file", text);
161 add_line("# (useful if we later chose to resume the computation with a different number of nodes)", text);
162 }
163 else
164 {
165 add_line("# For every processor in the world, read the rank of the group it previously belonged to", text);
166 add_line("# (necessary if we are resuming the computation with a different number of nodes)", text);
167 }
168 std::string para = "- file: " + pbs_[pb_i].configFilename_;
169
170 begin_bloc(para, text);
171 std::string event = save ? "on_event: WriteNodeRanks" : "on_event: ReadNodeRanks";
172 add_line(event, text);
174 {
175 add_line("communicator: $MPI_COMM_SELF", text);
176 }
177 if (save)
178 {
179 begin_bloc("datasets:", text);
180 declare_array("nodeRanks", "int", "'$nb_proc'", text);
181 end_bloc();
182 }
183 std::string ioAction = save ? "write:" : "read:";
184 begin_bloc(ioAction, text);
185 write_impl_dataset("nodeRanks", "nodeRanks", text);
186 end_bloc();
187 end_bloc();
188}
189
190/*! @brief Writes the block in the YAML file that will specify the format of the checkpoint file named fname
191 */
192void Ecrire_YAML::write_format_for_checkpoint(const std::string& fname, std::string& text)
193{
194 std::string format_sauvegarde = "- file: " + fname;
195 begin_bloc(format_sauvegarde, text);
197 add_line("communicator: $master", text);
198 begin_bloc("write:", text);
199 write_impl_dataset("format_sauvegarde/version", "version", text);
200 end_bloc();
201 end_bloc();
202}
203
204/*! @brief Writes the block in the YAML file regarding the time scheme for the checkpoint file fname
205 */
206void Ecrire_YAML::write_time_scheme(bool save, const std::string& fname, std::string& text)
207{
208 std::string time_scheme = "- file: " + fname;
209 begin_bloc(time_scheme, text);
210 if(save)
211 add_line("on_event: time_scheme", text);
212
214 {
215 // during checkpoint, the master of the node knows all the information so no need for everyone to write
216 // during restart, every processor of the node will need to retrieve the time-scheme information
217 std::string communicator = save ? "$master" : "$node";
218 add_line("communicator: " + communicator, text);
219 }
220
221 // For checkpoint : declaring the dataset that will contain all the timesteps that will be saved
222 if(save)
223 {
224 begin_bloc("datasets:", text);
225 std::string size = "\'$nb_iter_max\'";
226 declare_array("time/t", "double", size, text);
227 end_bloc();
228 }
229
230 std::string IO = save ? "write:" : "read:";
231 begin_bloc(IO, text);
232 if(save) // For checkpoint : writing in the dedicated dataset the timestep that is being saved
233 write_TRUST_dataset("time/t", "temps", 0, "" /*no conditions*/, false, std::vector<std::string>() /*no attributes*/, text);
234 else // For restart : getting all the timesteps that have been saved
235 write_impl_dataset("time/t", "temps_sauvegardes", text);
236 // For checkpoint/restart : writing/getting the last iteration that has been saved
237 write_impl_dataset("time/last_iteration", "iter", text);
238 end_bloc();
239 end_bloc();
240}
241
242/*! @brief Writes the block in the YAML file that will trigger the creation of the checkpoint file for the problem pb_i
243 */
244void Ecrire_YAML::write_file_initialization(int pb_i, std::string& text)
245{
246 std::string para = "- file: " + pbs_[pb_i].filename;
247 begin_bloc(para, text);
248 std::string event = "on_event: init_" + pbs_[pb_i].pb->le_nom().getString();
249 add_line(event, text);
250 add_line("collision_policy: replace_and_warn # print a warning if file or any of dataset already exist", text);
252 add_line("communicator: $master", text);
253
254 // we need to dump a single variable with PDI for the collision policy to work
255 begin_bloc("write:", text);
256 write_impl_dataset("format_sauvegarde/simple_sauvegarde", "simple_sauvegarde", text);
257 end_bloc();
258 end_bloc();
259}
260
261/*! @brief Writes the block in the YAML file that describes how the parallel data of the problem pb_i to be saved will be dumped in a dataset
262 */
263void Ecrire_YAML::write_data_for_checkpoint(int pb_i, bool local_data, std::string& text)
264{
265 std::string checkpoint = "- file: " + pbs_[pb_i].filename;
266 begin_bloc(checkpoint, text);
267 std::string event_type = local_data ? "local_backup_" : "global_backup_";
268 std::string event = "on_event: " + event_type + pbs_[pb_i].pb->le_nom().getString();
269 add_line(event, text);
271 {
272 if(local_data)
273 add_line("communicator: $node", text);
274 else
275 add_line("communicator: $master", text);
276 }
277
278 auto add_dataset = [&](const YAML_data& d, bool declare)
279 {
280 if(!d.is_dataset())
281 return;
282 // if the nature of the data does not correspond to the type of data we want to deal with in this bloc, we pass
283 if( d.is_local() != local_data )
284 return;
285 const std::string& name = d.get_name();
286 const std::string& dname = d.get_hdf_name();
287 const std::string& type = d.get_type();
288 int nb_dim = d.get_dims();
289 bool is_parallel = Process::is_parallel() && d.is_local();
290 if(declare)
291 declare_TRUST_dataset(dname, name, type, nb_dim, is_parallel, text);
292 else
293 {
294 const std::string& cond = d.get_conditions();
295 const std::vector<std::string>& attr = d.get_attributes();
296 write_TRUST_dataset(dname, name, nb_dim, cond, is_parallel, attr, text);
297 }
298 };
299 // declaring datasets
300 begin_bloc("datasets:", text);
301 for(const auto& d: pbs_[pb_i].data)
302 add_dataset(d, true);
303 end_bloc();
304
305 // writing fields
306 begin_bloc("write:", text);
307 for(const auto& d: pbs_[pb_i].data)
308 add_dataset(d, false);
309 end_bloc();
310
311 end_bloc();
312}
313
314/*! @brief Writes the block in the YAML file that describes how to write the types of the fields of pb_i we want to save
315 */
316void Ecrire_YAML::write_fields_types_for_checkpoint(int pb_i, std::string& text)
317{
318 const std::string& fname = pbs_[pb_i].filename;
319 std::string checkpoint = "- file: " + fname;
320 begin_bloc(checkpoint, text);
321 const std::string& pb_name = pbs_[pb_i].pb->le_nom().getString();
322 std::string event = "on_event: " + pb_name + "_get_types";
323 add_line(event, text);
325 add_line("communicator: $master", text);
326
327 // parsing all data and see if if we have to save their types
328 std::vector<std::string> types;
329 for(const auto& d: pbs_[pb_i].data)
330 {
331 if(!d.save_field_type())
332 continue;
333
334 const std::string& name = d.get_name();
335 std::string type = "TYPE_" + name;
336 types.push_back(type);
337 // also saving the length of the string
338 std::string sz = "size_" + type;
339 types.push_back(sz);
340 }
341
342 begin_bloc("write:", text);
343 // writing all the found types as attributes
344 write_impl_dataset(pb_name + "_TYPES", "TYPES", types, text);
345 end_bloc();
346
347 end_bloc();
348}
349
350
351/*! @brief Writes the block in the YAML file that describes how to read the types of the fields of pb_i we want to save
352 */
353void Ecrire_YAML::write_fields_types_for_restart(int pb_i, std::string& text)
354{
355 const std::string& fname = pbs_[pb_i].filename;
356 const std::string& pb_name = pbs_[pb_i].pb->le_nom().getString();
357
358 auto add_block = [&](const std::string& name)
359 {
360 std::string restart = "- file: " + fname;
361 begin_bloc(restart, text);
362 std::string event = "on_event: get_" + name;
363 add_line(event, text);
365 add_line("communicator: $node", text);
366 begin_bloc("read:", text);
367 write_impl_dataset(pb_name + "_TYPES", "TYPES", std::vector<std::string> { name }, text);
368 end_bloc();
369 end_bloc();
370 };
371
372 for(const auto& d: pbs_[pb_i].data)
373 {
374 if(!d.save_field_type())
375 continue;
376
377 const std::string& name = d.get_name();
378 std::string type = "TYPE_" + name;
379 std::string sz = "size_" + type;
380 // adding 2 different blocks for the size of type and type as we first need to read the size of the string first to allocate
381 // the correct size for the string type
382 add_block(type);
383 add_block(sz);
384 }
385}
386
387
388/*! @brief Writes the block in the YAML file that describes how the data of the problem pb_i to be restored will be read from the checkpoint file
389 */
390void Ecrire_YAML::write_data_for_restart(int pb_i, std::string& text)
391{
392 const std::string& fname = pbs_[pb_i].filename;
393 // writing a single block for all data as they are read on the go (not at once after an event trigger, unlike checkpoint)
394 for(const auto& d: pbs_[pb_i].data)
395 {
396 if(!d.is_dataset())
397 continue;
398
399 const std::string& name = d.get_name();
400 std::string restart = "- file: " + fname;
401 begin_bloc(restart, text);
403 add_line("communicator: $node", text);
404
405 begin_bloc("read:", text);
406 int nb_dim = d.get_dims();
407 const std::string& cond = d.get_conditions();
408 bool is_parallel = Process::is_parallel() && d.is_local();
409 const std::vector<std::string>& attr = d.get_attributes();
410 const std::string& dname = d.get_hdf_name();
411 write_TRUST_dataset(dname, name, nb_dim, cond, is_parallel, attr, text);
412 end_bloc();
413 end_bloc();
414 }
415
416 // writing time
417 write_time_scheme(0, fname, text);
418
419 // writing the block for the types of the fields we want to restore
420 write_fields_types_for_restart(pb_i, text);
421}
422
423/*! @brief Declaring all metadata (ie data that will be kept in PDI memory) in the YAML file
424 */
425void Ecrire_YAML::declare_metadata(bool save, std::string& text)
426{
427 begin_bloc("metadata: # small values for which PDI keeps a copy", text);
428
429 add_line("# scheme information", text);
430 if(save)
431 {
432 add_line("iter: int # Number of checkpoints performed until now (WARNING: does not correspond to the current iteration in my time loop)", text);
433 add_line("nb_iter_max: int # Maximum number of checkpoints (WARNING: if this number is too small, we overwrite the first checkpoints)", text);
434 add_line("temps : double # current physical time", text);
435 }
436 else
437 {
438 add_line("iter : int # last saved iteration", text);
439 add_line("temps : double # physical time from which we want to restart computation", text);
440 }
441
442 add_line("# information on format", text);
443 add_line("version : int", text);
444 add_line("simple_sauvegarde: int", text);
445
446 // Declaring the dimensions of all the unknowns that will be saved/restored
447 for(unsigned i_pb=0; i_pb<pbs_.size(); i_pb++)
448 {
449 for(const auto& d: pbs_[i_pb].data)
450 {
451 const std::string& name = d.get_name();
452 // if we want to save the type of the data, which is a string, we need to declare its dimension
453 if(d.save_field_type())
454 {
455 std::string size = "size_TYPE_" + name;
456 declare_scalar(size, "int", text);
457 std::string tname = "TYPE_" + name;
458 std::string tsize = "$size_" + tname;
459 declare_array(tname, "char", tsize, text);
460 }
461
462 int nb_dim = d.get_dims();
463 // if the data is scalar, then no need to declare its dimension (only its type is necessary)
464 if(nb_dim == 0)
465 continue;
466 std::string asize = std::to_string(nb_dim);
467 std::string aname = "dim_" + name;
468 declare_array(aname, "int", asize, text);
469
470 // if the data is local to each proc (ie different on each processor), it might not have the same dimensions everywhere
471 // so we take the bigger dimension for the dataset
472 if(Process::is_parallel() && d.is_local())
473 {
474 std::string glob_dim = "glob_dim_" + name;
475 declare_scalar(glob_dim, "int", text);
476 }
477 }
478 }
479
480 add_line("# metadata regarding parallelism", text);
481 add_line("# total number of processors for this simulation", text);
482 add_line("nb_proc : int", text);
483 add_line("# total number of nodes for this simulation", text);
484 add_line("nb_nodes : int", text);
486 {
487 add_line("# MPI communicator for my group", text);
488 add_line("node : MPI_Comm", text);
489 add_line("# number of processors inside my group", text);
490 add_line("nodeSize : int", text);
491 add_line("# my rank inside my group", text);
492 add_line("nodeRk : int", text);
493 add_line("# rank of my group among all the other groups", text);
494 add_line("nodeId : int", text);
495 add_line("# MPI communicator for masters of each group", text);
496 add_line("master : MPI_Comm", text);
497 add_line("# List of the node ids of every processor in the world", text);
498 declare_array("nodeRanks", "int", "[ \'$nb_proc' ]",text);
499 }
500 end_bloc();
501}
502
503/*! @brief Declaring all data in the YAML file
504 */
505void Ecrire_YAML::declare_data(bool save, std::string& text)
506{
507 begin_bloc("data: # data we want to save/restore (essentially fields of unknown)", text);
508
509 for(unsigned i_pb=0; i_pb<pbs_.size(); i_pb++)
510 {
511 for(const auto& d: pbs_[i_pb].data)
512 {
513 const std::string& name = d.get_name();
514 const std::string& type = d.get_type();
515 int nb_dim = d.get_dims();
516 if(nb_dim == 0)
517 declare_scalar(name, type, text);
518 else
519 declare_dtab(name, name, type, nb_dim, text);
520 }
521 }
522 declare_scalar("TYPES", "int", text);
523 // For restart: declaring the array that will contain the timesteps that have been saved
524 if(!save)
525 declare_array("temps_sauvegardes", "double", "[ \'$iter + 1' ]",text);
526
527 end_bloc();
528}
529
530/*! @brief Parse every added problems to collect the data that we need to save/restore
531 */
532void Ecrire_YAML::set_data()
533{
534 assert(!pbs_.empty());
535
536 for(unsigned i_pb=0; i_pb<pbs_.size(); i_pb++)
537 {
538 const Probleme_base& pb = pbs_[i_pb].pb.valeur();
539 std::vector<YAML_data>& data = pbs_[i_pb].data;
540 // equations unknowns
541 for(int i_eq=0; i_eq<pb.nombre_d_equations(); i_eq++)
542 {
543 std::vector<YAML_data> eqs = pb.equation(i_eq).data_a_sauvegarder();
544 data.insert(data.end(), eqs.begin(), eqs.end());
545 }
546 // domain-related data that needs to be saved (e.g. mobile domain)
547 std::vector<YAML_data> dom = pb.domaine().data_a_sauvegarder(pb);
548 data.insert(data.end(), dom.begin(), dom.end());
549 // statistical post-processing fields
550 for (const auto& post_base : pb.postraitements())
551 {
552 std::vector<YAML_data> post = post_base->data_a_sauvegarder();
553 data.insert(data.end(), post.begin(), post.end());
554 }
555 }
556}
557
558/*! @brief Adds a field (name+dimension) to the block of the problem pb_name in the YAML file
559 */
560void Ecrire_YAML::add_field(Nom pb_name, Nom nom, int nb_dim)
561{
562 assert(!pbs_.empty());
563
564 for(unsigned i_pb=0; i_pb<pbs_.size(); i_pb++)
565 {
566 // this method is meant to be called at the beginning of the computation only + pbs_ is usually really small
567 // so the search shouldn't be costly
568 if(pbs_[i_pb].pb->le_nom() == pb_name)
569 {
570 const std::string& name = nom.getString();
571 YAML_data data(name, "double", nb_dim);
572 pbs_[i_pb].data.push_back(data);
573 return;
574 }
575 }
576 Cerr << "Ecrire_Yaml::add_field Trying to add field " << nom << " to non-existant problem " << pb_name << finl;
577 Cerr << "Add " << pb_name << " to the Yaml list of problems first " << finl;
579}
580
581/*! @brief Adds a scalar (name+type) to the block of the problem pb_name in the YAML file
582 */
583void Ecrire_YAML::add_scalar(Nom pb_name, Nom nom, Nom type, bool is_local)
584{
585 assert(!pbs_.empty());
586 for(unsigned i_pb=0; i_pb<pbs_.size(); i_pb++)
587 {
588 // this method is meant to be called at the beginning of the computation only + pbs_ is usually really small
589 // so the search shouldn't be costly
590 if(pbs_[i_pb].pb->le_nom() == pb_name)
591 {
592 const std::string& name = nom.getString();
593 YAML_data data(name, type.getString());
594 data.set_local(is_local);
595 pbs_[i_pb].data.push_back(data);
596 return;
597 }
598 }
599 Cerr << "Ecrire_Yaml::add_scalar Trying to add scalar " << nom << " to non-existant problem " << pb_name << finl;
600 Cerr << "Add " << pb_name << " to the Yaml list of problems first " << finl;
602}
603
604/*! @brief Declaring a scalar in the YAML file
605 * @param (std::string name) name of the scalar
606 * @param (std::string type) type of the array
607 * @param (std::string& text) the string that will be completed by the method
608 */
609void Ecrire_YAML::declare_scalar(const std::string& name, const std::string& type, std::string& text)
610{
611 std::string scal = name + " : " + type;
612 add_line(scal, text);
613}
614
615
616/*! @brief Declaring a one-dimensional array in the YAML file
617 * @param (std::string name) name of the array
618 * @param (std::string type) type of the array
619 * @param (std::string size) size of the array
620 * @param (std::string& text) the string that will be completed by the method
621 */
622void Ecrire_YAML::declare_array(const std::string& name, const std::string& type, const std::string& size, std::string& text)
623{
624 std::string decl = name + " : { type: array, subtype: " + type + ", size: " + size + " }";
625 add_line(decl, text);
626}
627
628/*! @brief Declaring a multi-dimensional array (ie TRUSTTab) in the YAML file
629 * @param (std::string dname) name of the dataset
630 * @param (std::string name) name of the array
631 * @param (std::string type) type of the array
632 * @param (int nb_dim) number of the dimensions of the array
633 * @param (std::string& text) the string that will be completed by the method
634 */
635void Ecrire_YAML::declare_dtab(const std::string& dname, const std::string& name, const std::string& type, int nb_dim, std::string& text)
636{
637 std::string data = dname + " : { type: array, subtype: " + type + ", size: [ \'$dim_" + name + "[0]\'";
638 for(int d=1; d<nb_dim; d++)
639 data = data + "," + "\'$dim_" + name + "[" + std::to_string(d) + "]\'";
640 data = data + " ] }";
641 add_line(data, text);
642}
643
644/*! @brief Declaring a dataset that will contain a data (unknown field or scalar) coming from TRUST in the YAML file:
645 * 1st dimension is that of the process rank in the node for parallel computation,
646 * 2nd dimension is that of the various iterations to be saved,
647 * 3rd dimension of the dataset actually corresponds to the first dimension of the field (we take the largest first dimension of the node so that it can fit the data of every process)
648 * remaining dimensions of the dataset are those of the field
649 * @param (std::string dname) name of the dataset
650 * @param (std::string name) name of the data
651 * @param (std::string type) type of the data
652 * @param (int nb_dim) number of the dimensions of the data
653 * @param (bool is_parallel) true if the dataset is parallel, false if not
654 * @param (std::string& text) the string that will be completed by the method
655 */
656void Ecrire_YAML::declare_TRUST_dataset(const std::string& dname, const std::string& name, const std::string& type, int nb_dim, bool is_parallel, std::string& text)
657{
658 std::string dataset_dim = dname + ": { type: array, subtype: " + type + ", size: [";
659 if(is_parallel)
660 dataset_dim = dataset_dim + "\'$nodeSize\', ";
661 dataset_dim = dataset_dim + "\'$nb_iter_max\'";
662 for(int d=0; d<nb_dim; d++)
663 {
664 if(d == 0 && is_parallel)
665 dataset_dim = dataset_dim + ", \'$glob_dim_" + name + "\'";
666 else
667 dataset_dim = dataset_dim + ", \'$dim_" + name + "[" + std::to_string(d) + "]\'";
668 }
669 dataset_dim = dataset_dim + " ] }";
670 add_line(dataset_dim, text);
671}
672
673/*! @brief Writes the block in the YAML file to dump a TRUST data in a dataset
674 * @param (std::string dname) name of the dataset
675 * @param (std::string name) name of the data
676 * @param (int nb_dim) number of the dimensions of the DoubleTab
677 * @param (std::string cond) conditions to respect in order to trigger the writing/reading of the DoubleTab
678 * @param (bool is_parallel) true if the dataset is parallel, false if not
679 * @param (std::string& text) the string that will be completed by the method
680 */
681void Ecrire_YAML::write_TRUST_dataset(const std::string& dname, const std::string& name, int nb_dim, const std::string& cond, bool is_parallel, const std::vector<std::string>& attributes, std::string& text)
682{
683 std::string header = name + ":";
684 begin_bloc(header, text);
685 if(!cond.empty())
686 {
687 std::string condition = "when: \'" + cond + "\'";
688 add_line(condition, text);
689 }
690 std::string dataset_name = "dataset: " + dname;
691 add_line(dataset_name, text);
692 write_TRUST_dataset_selection(name, nb_dim, is_parallel, text);
693 if(!attributes.empty())
694 write_attributes(attributes, text);
695 end_bloc();
696}
697
698/*! @brief Writes the block in the YAML file that contains all attributes to current dataset
699 * WARNING: with PDI, HDF5-attributes are necessarily attached to a dataset (for now)
700 * @param (const std::vector<std::string>& attributes) vector of the names of the attributes
701 * @param (std::string& text) the string that will be completed by the method
702 */
703void Ecrire_YAML::write_attributes(const std::vector<std::string>& attributes, std::string& text)
704{
705 begin_bloc("attributes:", text);
706 for(const auto& aname: attributes)
707 {
708 std::string attr = aname + ": $" + aname;
709 add_line(attr, text);
710 }
711 end_bloc();
712}
713
714
715/*! @brief Writes the block in the YAML file to select the section in the TRUST dataset where the data will be written
716 * @param (std::string name) name of the data
717 * @param (int nb_dim) number of the dimensions of the DoubleTab
718 * @param (bool is_parallel) true if the dataset is parallel, false if not
719 * @param (std::string& text) the string that will be completed by the method
720 */
721void Ecrire_YAML::write_TRUST_dataset_selection(const std::string& name, int nb_dim, bool is_parallel, std::string& text)
722{
723 std::vector<std::string> sizes;
724 if(is_parallel)
725 {
726 // one processor
727 sizes.push_back("1");
728 }
729 // one iteration
730 sizes.push_back("1");
731 for(int d=0; d<nb_dim; d++)
732 sizes.push_back("\'$dim_" + name + "[" + std::to_string(d) + "]\'");
733
734 std::vector<std::string> offsets;
735 if(is_parallel)
736 offsets.push_back("\'$nodeRk\'");
737 offsets.push_back("\'$iter\'");
738 for(int d=0; d<nb_dim; d++)
739 offsets.push_back("0");
740
741 write_dataset_selection(sizes, offsets, text);
742}
743
744/*! @brief Writes the block in the YAML file to select the section in any dataset where the data will be written
745 * @param const std::vector<std::string>& sizes array containing the size of the data for each dimension
746 * @param const std::vector<std::string>& offset array containing the offset from where the data will be written for each dimension
747 * @param (std::string& text) the string that will be completed by the method
748 */
749void Ecrire_YAML::write_dataset_selection(const std::vector<std::string>& sizes, const std::vector<std::string>& offsets, std::string& text)
750{
751 assert(!sizes.empty() && sizes.size() == offsets.size());
752 begin_bloc("dataset_selection:", text);
753 std::string size = "size: [";
754 size += sizes[0];
755 for (auto sz = std::next(sizes.begin()); sz != sizes.end(); ++sz)
756 size += "," + *sz;
757 size += "]";
758 add_line(size, text);
759 std::string start = "start: [";
760 start += offsets[0];
761 for (auto ofs = std::next(offsets.begin()); ofs != offsets.end(); ++ofs)
762 start += "," + *ofs;
763 start += "]";
764 add_line(start, text);
765 end_bloc();
766}
767
768/*! @brief Writes the block in the YAML file to dump the data in an implicit dataset
769 * ie a dataset that does not need to be declared as its dimension corresponds to those of the data
770 * @param (std::string dname) name of the dataset where the data is stored
771 * @param (std::string name) name of the data
772 * @param (std::string& text) the string that will be completed by the method
773 */
774void Ecrire_YAML::write_impl_dataset(const std::string& dname, const std::string& name, std::string& text)
775{
776 std::string header = name + ":";
777 begin_bloc(header, text);
778 std::string dataset_name = "dataset: " + dname;
779 add_line(dataset_name, text);
780 end_bloc();
781}
782
783
784/*! @brief Writes the block in the YAML file to dump the data in an implicit dataset
785 * ie a dataset that does not need to be declared as its dimension corresponds to those of the data
786 * @param (std::string dname) name of the dataset where the data is stored
787 * @param (std::string name) name of the data
788 * @param (const std::vector<std::string>& attributes) vector of the names of the attributes
789 * @param (std::string& text) the string that will be completed by the method
790 */
791void Ecrire_YAML::write_impl_dataset(const std::string& dname, const std::string& name, const std::vector<std::string>& attributes, std::string& text)
792{
793 std::string header = name + ":";
794 begin_bloc(header, text);
795 std::string dataset_name = "dataset: " + dname;
796 add_line(dataset_name, text);
797 if(!attributes.empty())
798 write_attributes(attributes, text);
799 end_bloc();
800}
virtual std::vector< YAML_data > data_a_sauvegarder(const Probleme_base &pb) const
void add_field(Nom pb, Nom nom, int nb_dim)
Adds a field (name+dimension) to the block of the problem pb_name in the YAML file.
void write_champ_fonc_restart_file(const std::string &filename)
Generate the YAML file that will be read with champ_fonc_reprise.
void write_checkpoint_file(const std::string &yaml_fname)
Generate the YAML file that will be read for checkpoint.
void add_scalar(Nom pb, Nom nom, Nom type, bool is_local)
Adds a scalar (name+type) to the block of the problem pb_name in the YAML file.
void write_restart_file(const std::string &yaml_fname)
Generate the YAML file that will be read for restart.
virtual std::vector< YAML_data > data_a_sauvegarder() const
for PDI IO: retrieve name, type and dimensions of the data to save/restore. This has to be overrode f...
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const std::string & getString() const
Definition Nom.h:92
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Probleme_U.h:109
const Domaine & domaine() const
Renvoie le domaine associe au probleme.
Postraitements & postraitements()
virtual int nombre_d_equations() const =0
virtual const Equation_base & equation(int) const =0
static bool is_parallel()
Definition Process.cpp:110
static void barrier()
Synchronise tous les processeurs du groupe courant (attend que tous les processeurs soient arrives a ...
Definition Process.cpp:136
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
classe YAML_data : collection of all needed information for data to save/restore in order to write th...
Definition YAML_data.h:26
const std::string & get_conditions() const
Definition YAML_data.h:47
const std::string & get_hdf_name() const
Definition YAML_data.h:50
bool save_field_type() const
Definition YAML_data.h:51
int get_dims() const
Definition YAML_data.h:45
bool is_local() const
Definition YAML_data.h:46
const std::string & get_name() const
Definition YAML_data.h:43
const std::vector< std::string > & get_attributes() const
Definition YAML_data.h:48
void set_local(bool l)
Definition YAML_data.h:35
bool is_dataset() const
Definition YAML_data.h:49
const std::string & get_type() const
Definition YAML_data.h:44