TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Save_Restart.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 <EcritureLectureSpecial.h>
17#include <Entree_Fichier_base.h>
18#include <Entree_Fichier_base.h>
19#include <Discretisation_base.h>
20#include <EcrFicCollecteBin.h>
21#include <LecFicDiffuseBin.h>
22#include <communications.h>
23#include <FichierHDFPar.h>
24#include <Probleme_base.h>
25#include <Sortie_Nulle.h>
26#include <Save_Restart.h>
27#include <TRUST_2_PDI.h>
28#include <Ecrire_YAML.h>
29#include <sys/stat.h>
30#include <Avanc.h>
31#include <Perf_counters.h>
32#define CHECK_ALLOCATE 0
33#ifdef CHECK_ALLOCATE
34#include <unistd.h> // For access to int close(int fd); with PGI
35#include <fcntl.h>
36#include <errno.h>
37#endif
38
39// Returns the version of the save format
40// 151 to say that it is the version initiated at version 1.5.1 of TRUST
41inline int version_format_sauvegarde() { return 184; }
42
43// Version using PDI library
44inline int version_format_PDI() { return 196; }
45
46/*! @brief Initialization of file_size, bad_allocate, nb_pb_total, num_pb
47 *
48 */
49long int Save_Restart::File_size_=0; // file_size is the disk space in bytes necessary to write the XYZ files
50int Save_Restart::Bad_allocate_=1; // bad_allocate is an int that tells us if the allocation has already taken place
51int Save_Restart::Nb_pb_total_=0; // nb_pb_total is the total number of problems
52int Save_Restart::Num_pb_=1; // num_pb is the number of the current problem
53
55{
56 pb_base_ = pb;
57}
58
60{
61 if(pb_base_->schema_temps().file_allocation() && EcritureLectureSpecial::Active) // Allows testing disk space allocation
62 {
63 if (Bad_allocate_==1) // If allocation did not take place
64 if (Process::je_suis_maitre()) // Only with the master process
65 {
66 if (Num_pb_==1) // If the problem is the first
67 if (!allocate_file_size(File_size_)) // I attempt a disk space allocation of size 2*file_size
68 Bad_allocate_=0; // If this fails, I indicate to the code that the allocation already took place and did not work
69 else
70 Num_pb_=Nb_pb_total_; // If OK, I modify num_pb so that other problems do not attempt allocation
71 else
72 Num_pb_-=1; // If the problem is not the first, I decrement the problem number
73 }
74 const int canal = 2007;
75 if (Process::je_suis_maitre()) // the master processor sends bad_allocate to everyone
76 for (int p=1; p<Process::nproc(); p++)
77 envoyer(Bad_allocate_,p,canal);
78 else
79 recevoir(Bad_allocate_,0,canal);
80
81 if (Bad_allocate_==0) // If allocation failed
82 {
83 sauver_xyz(1);
84 if (Num_pb_==Nb_pb_total_) // If the problem number corresponds to the total number of problems
85 {
87 {
88 Cerr << finl; // I stop the code clearly
89 Cerr << "***Error*** " << error_ << finl; // and I output the error from the code
90 Cerr << "A xyz backup was made because you do not have enough disk space" << finl;
91 Cerr << "to continue the current calculation. Free up disk space and" << finl;
92 Cerr << "restart the calculation thanks to the backup just made." << finl;
93 Cerr << finl;
94 }
97 }
98 Num_pb_+=1; // I increment the problem number
99 }
100 }
101}
102
103/*! @brief Verifies that the necessary space exists on the hard disk.
104 *
105 * @param the required disk space
106 * @return (int) returns 1 if disk space is sufficient, 0 otherwise
107 */
108int Save_Restart::allocate_file_size(long int& size) const
109{
110#ifndef MICROSOFT
111#ifndef __APPLE__
112#ifndef RS6000
113#ifdef CHECK_ALLOCATE
114 Nom Fichier_File_size(Objet_U::nom_du_cas());
115 Fichier_File_size+="_File_size";
116 const char *file = Fichier_File_size; // Allocation file
117 // if (size<1048576) // If size is too small we set it to 1 MB
118 // size=1048576;
119 off_t taille = off_t(size+size); // Conversion of file size 2*size
120
121 int fichier = open(file, O_WRONLY | O_CREAT, 0666); // Opening of File_size file
122 if (fichier == -1) // Opening error
123 {
124 error_="Open of ";
125 error_+=file;
126 error_+=" : ";
127 error_+=strerror(errno); // Error on opening
128 close(fichier); // file closing
129 remove(file); // Destruction of File_size file
130 return 0; // Allocation failure because file not opened
131 }
132
133 if (posix_fallocate(fichier, 0, taille) != 0) // Disk space allocation error
134 {
135 error_="Allocation of ";
136 error_+=file;
137 error_+=" : ";
138 error_+=strerror(errno); // Error on allocation
139 close(fichier); // file closing
140 remove(file); // Destruction of File_size file
141 return 0; // Allocation failure because not enough space
142 }
143 close(fichier); // file closing
144 remove(file); // Destruction of File_size file
145#endif
146#endif
147#endif
148#endif
149 return 1;
150}
151
153{
154#ifndef RS6000
155 if (pb_base_->schema_temps().file_allocation() && EcritureLectureSpecial::Active)
156 {
157 Nom nom_fich_xyz(".xyz");
158 sauver_xyz(0);
160 {
161 ifstream fichier(nom_fich_xyz); // Calculation of disk space taken by XYZ file of current problem
162 fichier.seekg(0, std::ios_base::end);
163 File_size_ += fichier.tellg(); // Increments the disk space already necessary
164 fichier.close();
165 remove(nom_fich_xyz);
166 }
167 Nb_pb_total_ += 1; // Allows knowing the total number of problems at the end of preparer_calcul
168 }
169#endif
170
171 for(int i=0; i<pb_base_->nombre_d_equations(); i++)
172 pb_base_->equation(i).init_save_file();
173}
174
175void Save_Restart::setTinitFromLastTime(double last_time)
176{
177 // Set the time to restart the calculation
178 pb_base_->schema_temps().set_temps_courant() = last_time;
179 // Initialize tinit and current time according last_time
180 if (pb_base_->schema_temps().temps_init() > -DMAXFLOAT)
181 {
182 Cerr << "tinit was defined in .data file to " << pb_base_->schema_temps().temps_init() << ". The value is fixed to " << last_time << " accroding to resume_last_time_option" << finl;
183 }
184 pb_base_->schema_temps().set_temps_init() = last_time;
185 pb_base_->schema_temps().set_temps_precedent() = last_time;
186 Cerr << "==================================================================================================" << finl;
187 Cerr << "In the backup file, we find the last time: " << last_time << " and read the fields." << finl;
188}
189
190void Save_Restart::checkVersion(const Nom& nomfic)
191{
192 if (Process::mp_min(restart_version_) != Process::mp_max(restart_version_))
193 {
194 Cerr << "The version of the format backup/resumption is not the same in the resumption files " << nomfic << finl;
196 }
197 if (restart_version_ > version_format_sauvegarde())
198 {
199 Cerr << "The format " << restart_version_ << " of the resumption file " << nomfic << " is posterior" << finl;
200 Cerr << "to the format " << version_format_sauvegarde() << " recognized by this version of TRUST." << finl;
201 Cerr << "Please use a more recent version." << finl;
203 }
204
205 // Writing of restart format
206 Cerr << "The version of the resumption format of file " << nomfic << " is " << restart_version_ << finl;
207}
208
209void Save_Restart::prepare_PDI_restart(int resume_last_time)
210{
212 TRUST_2_PDI pdi_interface;
213
214 int last_iteration = -1;
215 double tinit = -1.;
216
217 // Restart from the last time
218 if (resume_last_time)
219 {
220 // Look for the last time saved in checkpoint file to init current computation
221 pdi_interface.prepareRestart(restartComm_, last_iteration, tinit, 1 /*resume_last_time */);
222
223 // set last time found in checkpoint file to tinit if tinit not set
224 setTinitFromLastTime(tinit);
225 }
226 else // resume from the requested time
227 {
228 // looking for tinit in backup file
229 tinit = pb_base_->schema_temps().temps_init();
230 pdi_interface.prepareRestart(restartComm_, last_iteration, tinit, 0 /* reprise */);
231 }
232}
233
234void Save_Restart::sauver_xyz(int verbose) const
235{
236 statistics().begin_count(STD_COUNTERS::backup_file,statistics().get_last_opened_counter_level()+1);
237 Nom nom_fich_xyz("");
238 if (verbose)
239 {
240 nom_fich_xyz += Objet_U::nom_du_cas();
241 nom_fich_xyz += "_";
242 nom_fich_xyz += pb_base_->le_nom();
243 nom_fich_xyz += ".xyz";
244 Cerr << "Creation of " << nom_fich_xyz << " (" << EcritureLectureSpecial::get_Output() << ") for resumption of a calculation with a different number of processors." << finl;
245 }
246 else
247 {
248 nom_fich_xyz = ".xyz";
249 }
250 // Create the XYZ file for the current problem
251 ficsauv_.typer(EcritureLectureSpecial::get_Output());
252 ficsauv_->ouvrir(nom_fich_xyz);
253 // New for xyz since version 155: the backup format is written in the header
255 ficsauv_.valeur() << "format_sauvegarde:" << finl << version_format_sauvegarde() << finl;
256
258 int bytes = pb_base_->sauvegarder(ficsauv_.valeur());
260
262 ficsauv_.valeur() << Nom("fin");
263 (ficsauv_.valeur()).flush();
264 (ficsauv_.valeur()).syncfile();
265 ficsauv_.detach();
266 Cout << "[IO] " << statistics().get_time_since_last_open(STD_COUNTERS::backup_file) << " s to write xyz file." << finl;
267 statistics().end_count(STD_COUNTERS::backup_file,1,bytes);
268}
269
270
271void Save_Restart::lire_pdi_sauvegarde_reprise(Entree& is, Motcle& motlu, Nom& restart_file_name, Nom& yaml_fname)
272{
273 Nom nom;
274 is >> nom;
275 motlu = nom;
276 if(motlu==Motcle("{"))
277 {
278 Motcles compris(3);
279 compris[0]="}";
280 compris[1]="checkpoint_fname";
281 compris[2]="yaml_fname";
282 int ind = -1;
283 while (ind!=0)
284 {
285 is >> motlu;
286 ind = compris.rang(motlu);
287 if (ind==1)
288 is >> restart_file_name;
289 else if (ind==2)
290 {
291 Cerr << "[Save_Restart] lire_pdi_sauvegarde_reprise :: You have provided your own yaml file to initialize PDI ! " << finl;
292 is >> yaml_fname;
293
294 // Check to see if the file exists
295 LecFicDiffuse test;
296 if (!test.ouvrir(yaml_fname))
297 {
298 Cerr << "[Save_Restart] lire_pdi_sauvegarde_reprise :: Error! The provided file " << yaml_fname << " does not exist " << finl;
300 }
301 }
302 else if (ind==-1)
303 {
304 Cerr << "[Save_Restart] lire_pdi_sauvegarde_reprise :: " << motlu << " is not understood. Keywords are:" << finl;
305 Cerr << compris << finl;
307 }
308 }
309 }
310 else
311 {
312 Cerr << "[Save_Restart] lire_pdi_sauvegarde_reprise :: " << motlu << " is not understood. Expected { :" << finl;
314 }
315}
316
317
318/////////////////////////////////////////////
319// Reading restart options for a computation
320/////////////////////////////////////////////
321void Save_Restart::lire_reprise(Entree& is, Motcle& motlu)
322{
323 int resume_last_time = (motlu == "resume_last_time" ? 1 : 0);
324 // reset to zero to allow a standard restart after an xyz restart
326 Motcle format_rep;
327 is >> format_rep;
328 if ((format_rep != "formatte") && (format_rep != "binaire") && (format_rep != "xyz") && (format_rep != "single_hdf") && (format_rep != "pdi") && (format_rep != "pdi_expert"))
329 {
330 Cerr << "Restarting calculation... : keyword " << format_rep << " not understood. Waiting for:" << finl << motlu << " formatte|binaire|xyz|single_hdf|pdi|pdi_expert Filename" << finl;
332 }
333
334 // XXX Elie Saikali : for PolyMAC_CDO => only .sauv files are possible
335 if (pb_base_->discretisation().is_PolyMAC_MPFA() && format_rep != "binaire")
336 {
337 Cerr << "Error in Save_Restart::" << __func__ << " !! " << finl;
338 Cerr << "Only the binary format is currently supported to resume a simulation with the discretization " << pb_base_->discretisation().que_suis_je() << " ! " << finl;
339 Cerr << "Please update your data file and use a .sauv file !" << finl;
341 }
342
343 // Read the filename:
344 Nom nom_yaml;
345 if( format_rep == "pdi_expert" )
346 {
347 lire_pdi_sauvegarde_reprise(is, motlu, restart_filename_, nom_yaml);
348 format_rep = "pdi";
349 }
350 else
351 is >> restart_filename_;
352 // Force hdf restart beyond a certain number of MPI ranks:
353 if (format_rep != "xyz" && Process::force_single_file(Process::nproc(), restart_filename_))
354 format_rep = "pdi";
355
356 if(format_rep == "pdi")
357 {
358 std::string yaml_fname = nom_yaml.getString();
359 if(yaml_fname == "??")
360 {
361 Ecrire_YAML yaml_file;
362 yaml_file.add_pb_base(pb_base_, restart_filename_);
363 yaml_fname = "restart_" + pb_base_->le_nom().getString() + ".yml";
364 yaml_file.write_restart_file(yaml_fname);
365 }
366 TRUST_2_PDI::init(yaml_fname);
367
368 // Prepare restart
369 prepare_PDI_restart(resume_last_time);
370
371 Entree useless;
372 pb_base_->reprendre(useless);
373
375 }
376 else if(format_rep == "single_hdf")
377 {
378 // !! DEPRECATED HDF5 FILE !!
379 Cerr << "==============================================================================" << finl;
380 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
381 Cerr << "WARNING::you are using a deprecated backup file format. Please switch to PDI." << finl;
382 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
383 Cerr << "==============================================================================" << finl;
384 LecFicDiffuse test;
385 if (!test.ouvrir(restart_filename_))
386 {
387 Cerr << "Error! " << restart_filename_ << " file not found ! " << finl;
389 }
390 FichierHDFPar fic_hdf;
391 Entree_Brute input_data;
392 fic_hdf.open(restart_filename_, true);
393 fic_hdf.read_dataset("/sauv", Process::me(),input_data);
394
395 if(resume_last_time)
396 {
397 double last_time = -1;
398 last_time = get_last_time(input_data);
399 setTinitFromLastTime(last_time);
400 fic_hdf.read_dataset("/sauv", Process::me(), input_data);
401 }
402
403 input_data >> motlu;
404 if (motlu=="format_sauvegarde:")
405 {
406 input_data >> restart_version_;
407 checkVersion(restart_filename_);
408 }
409 else
410 {
411 Cerr<<"This .sauv file is too old and the format is not supported anymore."<<finl;
413 }
414 fic_hdf.close();
415
416 // Restart computation from checkpoint file
417 pb_base_->reprendre(input_data);
418 }
419 else
420 {
421 OWN_PTR(Entree_Fichier_base) fic;
422 if (format_rep == "formatte")
423 fic.typer("LecFicDistribue");
424 else if (format_rep == "binaire")
425 fic.typer("LecFicDistribueBin");
426 else if (format_rep == "xyz")
427 {
430 }
431 fic->ouvrir(restart_filename_);
432 if (fic->fail())
433 {
434 Cerr << "Error during the opening of the restart file : " << restart_filename_ << finl;
436 }
437
438 // Restart from the last time
439 if (resume_last_time)
440 {
441 // Look for the last time and set it to tinit if tinit not set
442 double last_time = -1.;
443 last_time = get_last_time(fic);
444 setTinitFromLastTime(last_time);
445
446 fic->close();
447 fic->ouvrir(restart_filename_);
448 }
449
450 // Read the backup format version if this is a standard restart
451 // Since 1.5.1, the backup format is marked at the header of backup files
452 // to allow easier evolution of the format in the future.
453 // Moreover with 1.5.1, faces are numbered differently, so restarting
454 // from an older backup file is incorrect; this is a way to warn users:
455 // they must perform an xyz restart to continue a computation started with an older version.
456 // Since 1.5.5, there is no format version for xyz
457 fic.valeur() >> motlu;
458 if (motlu != "FORMAT_SAUVEGARDE:")
459 {
460 if (format_rep == "xyz")
461 {
462 // We close and re-open the file:
463 fic->close();
464 fic->ouvrir(restart_filename_);
465 restart_version_ = 151;
466 }
467 else
468 {
469 Cerr << "-------------------------------------------------------------------------------------" << finl;
470 Cerr << "The resumption file " << restart_filename_ << " can not be read by this version of TRUST" << finl;
471 Cerr << "which is a later version than 1.5. Indeed, the numbering of the faces have changed" << finl;
472 Cerr << "and it would produce an erroneous resumption. If you want to use this version," << finl;
473 Cerr << "you must do a resumption of the file .xyz saved during the previous calculation" << finl;
474 Cerr << "because this file is independent of the numbering of the faces." << finl;
475 Cerr << "The next backup will be made in a format compatible with the new" << finl;
476 Cerr << "numbering of the faces and you can then redo classical resumptions." << finl;
477 Cerr << "-------------------------------------------------------------------------------------" << finl;
479 }
480 }
481 else
482 {
483 fic.valeur() >> restart_version_;
484 checkVersion(restart_filename_);
485 }
486
487 // Restart computation from checkpoint file
488 pb_base_->reprendre(fic.valeur());
489 }
490
491 restart_done_ = true;
492 restart_in_progress_ = true;
493}
494
495////////////////////////////////////////////////
496// Reading save options for a computation
497////////////////////////////////////////////////
498void Save_Restart::lire_sauvegarde(Entree& is, Motcle& motlu)
499{
500 // restart_file=1: the file is overwritten at each backup (and thus contains only one instant)
501 if (motlu == "sauvegarde_simple")
502 simple_restart_ = true;
503 is >> checkpoint_format_;
504 if ((Motcle(checkpoint_format_) != "binaire") && (Motcle(checkpoint_format_) != "formatte") &&
505 (Motcle(checkpoint_format_) != "xyz") && (Motcle(checkpoint_format_) != "single_hdf") &&
506 (Motcle(checkpoint_format_) != "pdi") && (Motcle(checkpoint_format_) != "pdi_expert") )
507 {
508 checkpoint_filename_ = checkpoint_format_;
509 checkpoint_format_ = "binaire";
510 }
511 else
512 {
513 if( Motcle(checkpoint_format_) == "pdi_expert" )
514 {
515 lire_pdi_sauvegarde_reprise(is, motlu, checkpoint_filename_, yaml_fname_);
516 checkpoint_format_ = "pdi";
517 }
518 else
519 {
520 if( Motcle(checkpoint_format_) == "single_hdf" )
521 {
522 Cerr << "==============================================================================" << finl;
523 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
524 Cerr << "WARNING::you are using a deprecated backup file format. Please switch to PDI." << finl;
525 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
526 Cerr << "==============================================================================" << finl;
527 }
528 is >> checkpoint_filename_;
529 }
530 }
531}
532
534{
535 // XXX Elie Saikali : for PolyMAC_MPFA => No xyz for the moment
536 if (pb_base_->discretisation().is_PolyMAC_MPFA())
537 {
538 Cerr << "Problem " << pb_base_->le_nom() << " with the discretization "
539 << pb_base_->discretisation().que_suis_je() << " => EcritureLectureSpecial = 0 !" << finl;
541 }
542 checkpoint_format_ = "binaire";
543 checkpoint_filename_ = Objet_U::nom_du_cas();
544 checkpoint_filename_ += "_";
545 checkpoint_filename_ += pb_base_->le_nom();
546 checkpoint_filename_ += ".sauv";
547
548 while (1)
549 {
550 if ((motlu == "reprise") || (motlu == "resume_last_time"))
551 lire_reprise(is, motlu);
552 else if (motlu == "sauvegarde" || motlu == "sauvegarde_simple")
553 lire_sauvegarde(is, motlu);
554 else if (motlu == "}")
555 break;
556 else
557 {
558 Cerr << "Error in Save_Restart::lire_sauvegarde_reprise" << finl;
559 Cerr << "We expected } instead of " << motlu << " to mark the end of the data set" << finl;
561 }
562 is >> motlu;
563 }
564
565 ficsauv_.detach();
566 // Force hdf backup beyond a certain number of MPI ranks:
567 if (checkpoint_format_ != "xyz" && Process::force_single_file(Process::nproc(), checkpoint_filename_))
568 checkpoint_format_ = "pdi";
569
570 if ((Motcle(checkpoint_format_) != "binaire") && (Motcle(checkpoint_format_) != "formatte") &&
571 (Motcle(checkpoint_format_) != "xyz") && (Motcle(checkpoint_format_) != "pdi") &&
572 (Motcle(checkpoint_format_) != "single_hdf"))
573 {
574 Cerr << "Error of backup format ! We expected formatte, binaire, xyz, or pdi/pdi_expert (which replace single_hdf). single_hdf format is still available but is deprecated, please use pdi instead." << finl;
576 }
577
578 if (pb_base_->schema_temps().temps_init() <= -DMAXFLOAT)
579 {
580 pb_base_->schema_temps().set_temps_init() = 0;
581 pb_base_->schema_temps().set_temps_courant() = 0;
582 }
583
584 if (reprise_effectuee())
585 {
586 // check if dt_ev exists, otherwise set reprise to 2
587 // we will recreate the header in dt_ev otherwise the header is wrong on pb_couple restart
588 Nom fichier(Objet_U::nom_du_cas());
589 fichier += ".dt_ev";
590 struct stat f;
591 if (stat(fichier, &f))
592 reprise_effectuee() = 2;
593 }
594}
595
596/*! @brief Writes to file for restart (backup).
597 *
598 */
600{
601 int pdi_format = Motcle(checkpoint_format_) == "pdi";
602 if(pdi_format)
603 {
605 {
606 std::string yaml_fname = yaml_fname_.getString();
607 if(yaml_fname == "??")
608 {
609 Ecrire_YAML yaml_file;
610 yaml_fname = "save_" + pb_base_->le_nom().getString() + ".yml";
611 yaml_file.add_pb_base(pb_base_, checkpoint_filename_);
612 yaml_file.write_checkpoint_file(yaml_fname);
613 }
614 TRUST_2_PDI::init(yaml_fname);
615 }
616
617 if(!config_file_created_)
618 {
619 int nb_proc = Process::nproc();
620 IntTab nodeRanks(nb_proc);
622 envoyer_gather(nodeRanks, nodeRanks, 0);
623 // Creating and filling the configuration checkpoint file
624 // which contains all the information about the nodes partition used for checkpoint
626 {
627 TRUST_2_PDI pdi_interface;
628 pdi_interface.write("nb_proc", &nb_proc);
629 pdi_interface.trigger("InitConfig");
630
632 pdi_interface.write("nb_nodes", &nb_nodes);
633 pdi_interface.trigger("WriteConfig");
634 pdi_interface.TRUST_start_sharing("nodeRanks", nodeRanks.data());
635 pdi_interface.trigger("WriteNodeRanks");
636 pdi_interface.stop_sharing_last_variable();
637 }
638 config_file_created_ = true;
639 }
640
641 // if we are dealing with a coupled problem, the initialization might have been done twice
642 // in which case we don't want to overwrite the file
643 if(Process::node_master() && !ficsauv_created_)
644 {
645 TRUST_2_PDI pdi_interface;
646 // if a file with the same name already exists, delete it and create a new one
647 int non_const_sr = simple_restart_;
648 pdi_interface.TRUST_start_sharing("simple_sauvegarde", &non_const_sr);
649 std::string event = "init_" + pb_base_->le_nom().getString();
650 pdi_interface.trigger(event);
651 pdi_interface.stop_sharing_last_variable();
652
653 // format information
654 int version = version_format_PDI();
655 pdi_interface.write("version", &version);
656 ficsauv_created_ = true;
657 }
658 }
659 else if (!ficsauv_ && !osauv_hdf_)
660 {
661 // If the backup file has not been opened yet, create the backup file:
662 if (Motcle(checkpoint_format_) == "formatte")
663 {
664 ficsauv_.typer("EcrFicCollecte");
665 //
666 // Even in 64b, a save/restart SAUV file never actually requires 64b indices since all the information
667 // saved is per proc. So we might as well save some space (not so much actually, since most of the data
668 // saved are double values).
669 //
670 ficsauv_->set_64b(false);
671 ficsauv_->ouvrir(checkpoint_filename_);
672 ficsauv_->setf(ios::scientific);
673 }
674 else if (Motcle(checkpoint_format_) == "binaire")
675 {
676 ficsauv_.typer("EcrFicCollecteBin");
677 ficsauv_->set_64b(false); // see comment above!
678 ficsauv_->ouvrir(checkpoint_filename_);
679 }
680 else if (Motcle(checkpoint_format_) == "xyz")
681 {
682 ficsauv_.typer(EcritureLectureSpecial::get_Output());
683 ficsauv_->ouvrir(checkpoint_filename_);
684 }
685 else if (Motcle(checkpoint_format_) == "single_hdf")
686 osauv_hdf_ = new Sortie_Brute;
687 else
688 {
689 Cerr << "Error in Save_Restart::sauver() " << finl;
690 Cerr << "The format for the backup file must be either binary or formatted or pdi/pdi_expert (which replace single_hdf). single_hdf is still available but is deprecated, please use pdi instead." << finl;
691 Cerr << "But it is :" << checkpoint_format_ << finl;
693 }
694 // If this is the first backup, write the backup format in the header
695 if (Motcle(checkpoint_format_) == "xyz")
696 {
698 ficsauv_.valeur() << "format_sauvegarde:" << finl << version_format_sauvegarde() << finl;
699 }
700 else if ((Motcle(checkpoint_format_) == "single_hdf"))
701 *osauv_hdf_ << "format_sauvegarde:" << finl << version_format_sauvegarde() << finl;
702 else
703 ficsauv_.valeur() << "format_sauvegarde:" << finl << version_format_sauvegarde() << finl;
704 }
705
706 // Perform the backup writing
707 int bytes;
708 EcritureLectureSpecial::mode_ecr = (Motcle(checkpoint_format_) == "xyz");
710 if(pdi_format)
711 {
712 TRUST_2_PDI pdi_interface;
713 int tmp = 1;
714 pdi_interface.TRUST_start_sharing("TYPES", &tmp);
715
716 Sortie_Nulle useless;
717 bytes = pb_base_->sauvegarder(useless);
718
719 // backup of the unknown fields (which are local to each processor so it will involve a parallel writing)
720 std::string f_event = "local_backup_" + pb_base_->le_nom().getString();
721 pdi_interface.trigger(f_event);
723 {
724 // backup of the data that are global to everyone so we just need one proc (the master of the node) to write it
725 std::string s_event = "global_backup_" + pb_base_->le_nom().getString();
726 pdi_interface.trigger(s_event);
727
728 // we save the types of fields we want to save (not all of them actually, only the ones that are necessary for restart)
729 std::string t_event = pb_base_->le_nom().getString() + "_get_types";
730 pdi_interface.trigger(t_event);
731 }
732 pdi_interface.stop_sharing();
733 }
734 else if (Motcle(checkpoint_format_) == "single_hdf")
735 bytes = pb_base_->sauvegarder(*osauv_hdf_);
736 else
737 bytes = pb_base_->sauvegarder(ficsauv_.valeur());
740
741 // If this is a simple backup, close the file immediately and properly
742 if (simple_restart_ && !pdi_format)
743 {
744 if (Motcle(checkpoint_format_) == "xyz")
745 {
747 ficsauv_.valeur() << Nom("fin");
748 (ficsauv_.valeur()).flush();
749 (ficsauv_.valeur()).syncfile();
750 }
751 else if (Motcle(checkpoint_format_) == "single_hdf")
752 {
753 *osauv_hdf_ << Nom("fin");
754 FichierHDFPar fic_hdf;
755 fic_hdf.create(checkpoint_filename_);
756 fic_hdf.create_and_fill_dataset_MW("/sauv", *osauv_hdf_);
757 fic_hdf.close();
758 delete osauv_hdf_;
759 osauv_hdf_ = 0;
760 }
761 else
762 {
763 ficsauv_.valeur() << Nom("fin");
764 (ficsauv_.valeur()).flush();
765 }
766 ficsauv_.detach();
767 }
768 return bytes;
769}
770
772{
773 // Close the backup file properly
774 // If it is a simple backup, fin was written at each call to ::sauver()
775 if(Motcle(checkpoint_format_) == "pdi" && TRUST_2_PDI::is_PDI_initialized())
777 else if (!simple_restart_ && (ficsauv_ || osauv_hdf_) )
778 {
779 if (Motcle(checkpoint_format_) == "xyz")
780 {
782 ficsauv_.valeur() << Nom("fin");
783 (ficsauv_.valeur()).flush();
784 (ficsauv_.valeur()).syncfile();
785 }
786 else if (Motcle(checkpoint_format_) == "single_hdf")
787 {
788 *osauv_hdf_ << Nom("fin");
789 FichierHDFPar fic_hdf;
790 fic_hdf.create(checkpoint_filename_);
791 fic_hdf.create_and_fill_dataset_MW("/sauv", *osauv_hdf_);
792 fic_hdf.close();
793 delete osauv_hdf_;
794 osauv_hdf_ = 0;
795 }
796 else
797 {
798 ficsauv_.valeur() << Nom("fin");
799 (ficsauv_.valeur()).flush();
800 }
801
802 ficsauv_.detach();
803 }
804 // If the backup is a standard one and the user has not disabled the final xyz backup,
805 // then perform the final xyz backup
806 if (Motcle(checkpoint_format_) != "xyz")
807 {
809 sauver_xyz(1);
810 else
811 Cerr << "As saving .xyz file disabled since 1.9.7, add into your datafile \"EcritureLectureSpecial 1\" to enable it again if wanted." << finl;
812 }
813
814 for(int i=0; i<pb_base_->nombre_d_equations(); i++)
815 pb_base_->equation(i).close_save_file();
816}
int get_node_id() const
Retrieve ID of my numa node.
Definition Comm_Group.h:194
int get_number_of_nodes() const
Definition Comm_Group.h:199
class Ecrire_YAML Use this to generate a yaml file that will then be read by the PDI library (for che...
Definition Ecrire_YAML.h:64
void write_checkpoint_file(const std::string &yaml_fname)
Generate the YAML file that will be read for checkpoint.
void add_pb_base(const Probleme_base &pb_base, const Nom &full_file_name)
Definition Ecrire_YAML.h:76
void write_restart_file(const std::string &yaml_fname)
Generate the YAML file that will be read for restart.
static Nom & get_Output()
Returns the write mode in use (so it can be modified).
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
Parallel collective version of FichierHDF, to be used for all concurrent reading/writing on HDF files...
virtual void create_and_fill_dataset_MW(Nom dataset_basename, Sortie_Brute &sortie)
virtual void read_dataset(Nom dataset_basename, int proc_rank, Entree_Brute &entree)
virtual void open(Nom filename, bool readOnly)
virtual void close()
virtual void create(Nom filename)
This class implements the operators and virtual methods of the EFichier class as follows: The file to...
A character string (Nom) in uppercase.
Definition Motcle.h:26
An array of Motcle objects.
Definition Motcle.h:63
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
const std::string & getString() const
Definition Nom.h:92
const Nom & le_nom() const override
Returns *this.
Definition Nom.cpp:555
static const Nom & nom_du_cas()
Returns a constant reference to the case name. This method is static.
Definition Objet_U.cpp:145
virtual int reprendre(Entree &)
Restores an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:336
static const Comm_Group & get_node_group()
Returns a reference to the node-level communicator group.
class Probleme_base It is a Probleme_U that is not a coupling.
static double mp_min(double)
Definition Process.cpp:391
static double mp_max(double)
Definition Process.cpp:379
static int node_master()
Returns 1 if on the NUMA node master processor, 0 otherwise.
Definition Process.cpp:92
static int nproc()
Returns the number of processors in the current group. See Comm_Group::nproc() and PE_Groups::current...
Definition Process.cpp:102
static void barrier()
Synchronizes all processors in the current group (waits until all processors have reached the barrier...
Definition Process.cpp:133
static bool force_single_file(const int ranks, const Nom &filename)
Definition Process.cpp:57
static int me()
Returns the rank of the local processor in the current communication group. See Comm_Group::rank() an...
Definition Process.cpp:122
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
static int je_suis_maitre()
Returns 1 if on the master processor of the current group (i.e. me() == 0), 0 otherwise.
Definition Process.cpp:82
bool & reprise_effectuee()
void preparer_calcul()
int sauver() const
Writes to file for restart (backup).
void sauver_xyz(int) const
void allocation() const
void assoscier_pb_base(const Probleme_base &)
void lire_sauvegarde_reprise(Entree &is, Motcle &motlu)
int allocate_file_size(long int &size) const
Verifies that the necessary space exists on the hard disk.
This derived class of Sortie stacks whatever it receives in an internal binary buffer.
Derived class of Sortie that sends data nowhere (it is a sink). Used in Journal() when logging is dis...
_TYPE_ * data()
TRUST_2_PDI Encapsulation of PDI methods (library used for IO operations). See the website pdi....
Definition TRUST_2_PDI.h:59
static void set_PDI_restart(int r)
void stop_sharing_last_variable()
void write(const std::string &name, const void *data)
void prepareRestart(OWN_PTR(Comm_Group)&nodeGroup, int &last_iteration, double &tinit, int resume_last_time)
Generic method to prepare the restart of a computation.
static void init(std::string IO_config)
Definition TRUST_2_PDI.h:63
static void set_PDI_checkpoint(int c)
void stop_sharing()
static void finalize()
Definition TRUST_2_PDI.h:83
static int is_PDI_initialized()
void TRUST_start_sharing(const std::string &name, const void *data)
void trigger(const std::string &event)