TRUST 1.9.8
HPC thermohydraulic platform
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> // Pour acces a int close(int fd); avec PGI
35#include <fcntl.h>
36#include <errno.h>
37#endif
38
39// Retourne la version du format de sauvegarde
40// 151 pour dire que c'est la version initiee a la version 1.5.1 de TRUST
41inline int version_format_sauvegarde() { return 184; }
42
43// Version using PDI library
44inline int version_format_PDI() { return 196; }
45
46/*! @brief Initialisation de file_size, bad_allocate, nb_pb_total, num_pb
47 *
48 */
49long int Save_Restart::File_size_=0; // file_size est l'espace disque en octet necessaire pour ecrire les fichiers XYZ
50int Save_Restart::Bad_allocate_=1; // bad_allocate est un int qui permet de savoir si l'allocation a deja eut lieu
51int Save_Restart::Nb_pb_total_=0; // nb_pb_total est le nombre total de probleme
52int Save_Restart::Num_pb_=1; // num_pb est le numero du probleme courant
53
55{
56 pb_base_ = pb;
57}
58
60{
61 if(pb_base_->schema_temps().file_allocation() && EcritureLectureSpecial::Active) // Permet de tester l'allocation d'espace disque
62 {
63 if (Bad_allocate_==1) // Si l'allocation n'a pas eut lieu
64 if (Process::je_suis_maitre()) // Qu'avec le proc maitre
65 {
66 if (Num_pb_==1) // Si le probleme est le premier
67 if (!allocate_file_size(File_size_)) // je tente une allocation d'espace disque de taille 2*file_size
68 Bad_allocate_=0; // Si cela echoue, j'indique au code que l'allocation a deja eut lieu et n'a pas fonctionner
69 else
70 Num_pb_=Nb_pb_total_; // Si OK, je modifie num_pb pour que les autres pb ne tentent pas d'allocation
71 else
72 Num_pb_-=1; // Si le probleme n'est pas le premier, je decremente le numero de probleme
73 }
74 const int canal = 2007;
75 if (Process::je_suis_maitre()) // le processeur maitre envoi bad_allocate a tout le monde
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) // Si l'allocation a echoue
82 {
83 sauver_xyz(1);
84 if (Num_pb_==Nb_pb_total_) // Si le numero de probleme correspond au nombre total de probleme
85 {
87 {
88 Cerr << finl; // j'arrete le code de facon claire
89 Cerr << "***Error*** " << error_ << finl; // et je sort l'erreur du 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; // j'incremente le numero de probleme
99 }
100 }
101}
102
103/*! @brief Verifie que la place necessaire existe sur le disque dur.
104 *
105 * @param l'espace disque requis
106 * @return (int) retourne 1 si l'espace disque est suffisant, 0 sinon
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; // Fichier d'allocation
117 // if (size<1048576) // Si size est trop petit on le fixe a 1 Mo
118 // size=1048576;
119 off_t taille = off_t(size+size); // Convertion de la taille du fichier 2*size
120
121 int fichier = open(file, O_WRONLY | O_CREAT, 0666); // Ouverture du fichier File_size
122 if (fichier == -1) // Erreur d'ouverture
123 {
124 error_="Open of ";
125 error_+=file;
126 error_+=" : ";
127 error_+=strerror(errno); // Erreur sur l'ouverture
128 close(fichier); // fermeture du fichier
129 remove(file); // Destruction du fichier File_size
130 return 0; // Echec d'allocation car fichier pas ouvert
131 }
132
133 if (posix_fallocate(fichier, 0, taille) != 0) // Erreur d'allocation de l'espace disque
134 {
135 error_="Allocation of ";
136 error_+=file;
137 error_+=" : ";
138 error_+=strerror(errno); // Erreur sur l'allocation
139 close(fichier); // fermeture du fichier
140 remove(file); // Destruction du fichier File_size
141 return 0; // Echec d'allocation car pas assez de place
142 }
143 close(fichier); // fermeture du fichier
144 remove(file); // Destruction du fichier File_size
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); // Calcul de l'espace disque pris par le fichier XYZ du probleme courant
162 fichier.seekg(0, std::ios_base::end);
163 File_size_ += fichier.tellg(); // Incremente l'espace disque deja necessaire
164 fichier.close();
165 remove(nom_fich_xyz);
166 }
167 Nb_pb_total_ += 1; // Permet de connaitre le nombre de probleme total a la fin du 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 // Ecriture du format de reprise
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 // Creation du fichier XYZ du probleme courant
251 ficsauv_.typer(EcritureLectureSpecial::get_Output());
252 ficsauv_->ouvrir(nom_fich_xyz);
253 // Nouveau pour le xyz depuis la 155: on note en en-tete le format de sauvegarde
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// Lecture des options de reprise d'un calcul
320/////////////////////////////////////////////
321void Save_Restart::lire_reprise(Entree& is, Motcle& motlu)
322{
323 int resume_last_time = (motlu == "resume_last_time" ? 1 : 0);
324 // remise a defaut a zero pour pouvoir faire une reprise std apres une reprise xyz
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 reprise hdf au dela d'un certain nombre de rangs MPI:
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 // Lecture de la version du format de sauvegarde si c'est une reprise classique
451 // Depuis la 1.5.1, on marque le format de sauvegarde en tete des fichiers de sauvegarde
452 // afin de pouvoir faire evoluer plus facilement ce format dans le futur
453 // En outre avec la 1.5.1, les faces etant numerotees differemment, il est faux
454 // de faire une reprise d'un fichier de sauvegarde anterieur et c'est donc un moyen
455 // de prevenir les utilisateurs: il leur faudra faire une reprise xyz pour poursuivre
456 // avec la 1.5.1 un calcul lance avec une version anterieure
457 // Depuis la 1.5.5, Il y a pas une version de format pour le xyz
458 fic.valeur() >> motlu;
459 if (motlu != "FORMAT_SAUVEGARDE:")
460 {
461 if (format_rep == "xyz")
462 {
463 // We close and re-open the file:
464 fic->close();
465 fic->ouvrir(restart_filename_);
466 restart_version_ = 151;
467 }
468 else
469 {
470 Cerr << "-------------------------------------------------------------------------------------" << finl;
471 Cerr << "The resumption file " << restart_filename_ << " can not be read by this version of TRUST" << finl;
472 Cerr << "which is a later version than 1.5. Indeed, the numbering of the faces have changed" << finl;
473 Cerr << "and it would produce an erroneous resumption. If you want to use this version," << finl;
474 Cerr << "you must do a resumption of the file .xyz saved during the previous calculation" << finl;
475 Cerr << "because this file is independent of the numbering of the faces." << finl;
476 Cerr << "The next backup will be made in a format compatible with the new" << finl;
477 Cerr << "numbering of the faces and you can then redo classical resumptions." << finl;
478 Cerr << "-------------------------------------------------------------------------------------" << finl;
480 }
481 }
482 else
483 {
484 fic.valeur() >> restart_version_;
485 checkVersion(restart_filename_);
486 }
487
488 // Restart computation from checkpoint file
489 pb_base_->reprendre(fic.valeur());
490 }
491
492 restart_done_ = true;
493 restart_in_progress_ = true;
494}
495
496////////////////////////////////////////////////
497// Lecture des options de sauvegarde d'un calcul
498////////////////////////////////////////////////
499void Save_Restart::lire_sauvegarde(Entree& is, Motcle& motlu)
500{
501 // restart_file=1: le fichier est ecrasee a chaque sauvegarde (et ne donc contient qu'un seul instant)
502 if (motlu == "sauvegarde_simple")
503 simple_restart_ = true;
504 is >> checkpoint_format_;
505 if ((Motcle(checkpoint_format_) != "binaire") && (Motcle(checkpoint_format_) != "formatte") &&
506 (Motcle(checkpoint_format_) != "xyz") && (Motcle(checkpoint_format_) != "single_hdf") &&
507 (Motcle(checkpoint_format_) != "pdi") && (Motcle(checkpoint_format_) != "pdi_expert") )
508 {
509 checkpoint_filename_ = checkpoint_format_;
510 checkpoint_format_ = "binaire";
511 }
512 else
513 {
514 if( Motcle(checkpoint_format_) == "pdi_expert" )
515 {
516 lire_pdi_sauvegarde_reprise(is, motlu, checkpoint_filename_, yaml_fname_);
517 checkpoint_format_ = "pdi";
518 }
519 else
520 {
521 if( Motcle(checkpoint_format_) == "single_hdf" )
522 {
523 Cerr << "==============================================================================" << finl;
524 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
525 Cerr << "WARNING::you are using a deprecated backup file format. Please switch to PDI." << finl;
526 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
527 Cerr << "==============================================================================" << finl;
528 }
529 is >> checkpoint_filename_;
530 }
531 }
532}
533
535{
536 // XXX Elie Saikali : for PolyMAC_MPFA => No xyz for the moment
537 if (pb_base_->discretisation().is_PolyMAC_MPFA())
538 {
539 Cerr << "Problem " << pb_base_->le_nom() << " with the discretization "
540 << pb_base_->discretisation().que_suis_je() << " => EcritureLectureSpecial = 0 !" << finl;
542 }
543 checkpoint_format_ = "binaire";
544 checkpoint_filename_ = Objet_U::nom_du_cas();
545 checkpoint_filename_ += "_";
546 checkpoint_filename_ += pb_base_->le_nom();
547 checkpoint_filename_ += ".sauv";
548
549 while (1)
550 {
551 if ((motlu == "reprise") || (motlu == "resume_last_time"))
552 lire_reprise(is, motlu);
553 else if (motlu == "sauvegarde" || motlu == "sauvegarde_simple")
554 lire_sauvegarde(is, motlu);
555 else if (motlu == "}")
556 break;
557 else
558 {
559 Cerr << "Error in Save_Restart::lire_sauvegarde_reprise" << finl;
560 Cerr << "We expected } instead of " << motlu << " to mark the end of the data set" << finl;
562 }
563 is >> motlu;
564 }
565
566 ficsauv_.detach();
567 // Force sauvegarde hdf au dela d'un certain nombre de rangs MPI:
568 if (checkpoint_format_ != "xyz" && Process::force_single_file(Process::nproc(), checkpoint_filename_))
569 checkpoint_format_ = "pdi";
570
571 if ((Motcle(checkpoint_format_) != "binaire") && (Motcle(checkpoint_format_) != "formatte") &&
572 (Motcle(checkpoint_format_) != "xyz") && (Motcle(checkpoint_format_) != "pdi") &&
573 (Motcle(checkpoint_format_) != "single_hdf"))
574 {
575 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;
577 }
578
579 if (pb_base_->schema_temps().temps_init() <= -DMAXFLOAT)
580 {
581 pb_base_->schema_temps().set_temps_init() = 0;
582 pb_base_->schema_temps().set_temps_courant() = 0;
583 }
584
585 if (reprise_effectuee())
586 {
587 // on teste si dt_ev existe sinon on met reprise a 2
588 // on recrera l'entete dans dt_ev sinon l'entete est fausse en reprise de pb_couple
589 Nom fichier(Objet_U::nom_du_cas());
590 fichier += ".dt_ev";
591 struct stat f;
592 if (stat(fichier, &f))
593 reprise_effectuee() = 2;
594 }
595}
596
597/*! @brief Ecriture sur fichier en vue d'une reprise (sauvegarde)
598 *
599 */
601{
602 int pdi_format = Motcle(checkpoint_format_) == "pdi";
603 if(pdi_format)
604 {
606 {
607 std::string yaml_fname = yaml_fname_.getString();
608 if(yaml_fname == "??")
609 {
610 Ecrire_YAML yaml_file;
611 yaml_fname = "save_" + pb_base_->le_nom().getString() + ".yml";
612 yaml_file.add_pb_base(pb_base_, checkpoint_filename_);
613 yaml_file.write_checkpoint_file(yaml_fname);
614 }
615 TRUST_2_PDI::init(yaml_fname);
616 }
617
618 if(!config_file_created_)
619 {
620 int nb_proc = Process::nproc();
621 IntTab nodeRanks(nb_proc);
623 envoyer_gather(nodeRanks, nodeRanks, 0);
624 // Creating and filling the configuration checkpoint file
625 // which contains all the information about the nodes partition used for checkpoint
627 {
628 TRUST_2_PDI pdi_interface;
629 pdi_interface.write("nb_proc", &nb_proc);
630 pdi_interface.trigger("InitConfig");
631
633 pdi_interface.write("nb_nodes", &nb_nodes);
634 pdi_interface.trigger("WriteConfig");
635 pdi_interface.TRUST_start_sharing("nodeRanks", nodeRanks.data());
636 pdi_interface.trigger("WriteNodeRanks");
637 pdi_interface.stop_sharing_last_variable();
638 }
639 config_file_created_ = true;
640 }
641
642 // if we are dealing with a coupled problem, the initialization might have been done twice
643 // in which case we don't want to overwrite the file
644 if(Process::node_master() && !ficsauv_created_)
645 {
646 TRUST_2_PDI pdi_interface;
647 // if a file with the same name already exists, delete it and create a new one
648 int non_const_sr = simple_restart_;
649 pdi_interface.TRUST_start_sharing("simple_sauvegarde", &non_const_sr);
650 std::string event = "init_" + pb_base_->le_nom().getString();
651 pdi_interface.trigger(event);
652 pdi_interface.stop_sharing_last_variable();
653
654 // format information
655 int version = version_format_PDI();
656 pdi_interface.write("version", &version);
657 ficsauv_created_ = true;
658 }
659 }
660 else if (!ficsauv_ && !osauv_hdf_)
661 {
662 // Si le fichier de sauvegarde n'a pas ete ouvert alors on cree le fichier de sauvegarde:
663 if (Motcle(checkpoint_format_) == "formatte")
664 {
665 ficsauv_.typer("EcrFicCollecte");
666 //
667 // Even in 64b, a save/restart SAUV file never actually requires 64b indices since all the information
668 // saved is per proc. So we might as well save some space (not so much actually, since most of the data
669 // saved are double values).
670 //
671 ficsauv_->set_64b(false);
672 ficsauv_->ouvrir(checkpoint_filename_);
673 ficsauv_->setf(ios::scientific);
674 }
675 else if (Motcle(checkpoint_format_) == "binaire")
676 {
677 ficsauv_.typer("EcrFicCollecteBin");
678 ficsauv_->set_64b(false); // see comment above!
679 ficsauv_->ouvrir(checkpoint_filename_);
680 }
681 else if (Motcle(checkpoint_format_) == "xyz")
682 {
683 ficsauv_.typer(EcritureLectureSpecial::get_Output());
684 ficsauv_->ouvrir(checkpoint_filename_);
685 }
686 else if (Motcle(checkpoint_format_) == "single_hdf")
687 osauv_hdf_ = new Sortie_Brute;
688 else
689 {
690 Cerr << "Error in Save_Restart::sauver() " << finl;
691 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;
692 Cerr << "But it is :" << checkpoint_format_ << finl;
694 }
695 // Si c'est la premiere sauvegarde, on note en en-tete le format de sauvegarde
696 if (Motcle(checkpoint_format_) == "xyz")
697 {
699 ficsauv_.valeur() << "format_sauvegarde:" << finl << version_format_sauvegarde() << finl;
700 }
701 else if ((Motcle(checkpoint_format_) == "single_hdf"))
702 *osauv_hdf_ << "format_sauvegarde:" << finl << version_format_sauvegarde() << finl;
703 else
704 ficsauv_.valeur() << "format_sauvegarde:" << finl << version_format_sauvegarde() << finl;
705 }
706
707 // On realise l'ecriture de la sauvegarde
708 int bytes;
709 EcritureLectureSpecial::mode_ecr = (Motcle(checkpoint_format_) == "xyz");
711 if(pdi_format)
712 {
713 TRUST_2_PDI pdi_interface;
714 int tmp = 1;
715 pdi_interface.TRUST_start_sharing("TYPES", &tmp);
716
717 Sortie_Nulle useless;
718 bytes = pb_base_->sauvegarder(useless);
719
720 // backup of the unknown fields (which are local to each processor so it will involve a parallel writing)
721 std::string f_event = "local_backup_" + pb_base_->le_nom().getString();
722 pdi_interface.trigger(f_event);
724 {
725 // backup of the data that are global to everyone so we just need one proc (the master of the node) to write it
726 std::string s_event = "global_backup_" + pb_base_->le_nom().getString();
727 pdi_interface.trigger(s_event);
728
729 // we save the types of fields we want to save (not all of them actually, only the ones that are necessary for restart)
730 std::string t_event = pb_base_->le_nom().getString() + "_get_types";
731 pdi_interface.trigger(t_event);
732 }
733 pdi_interface.stop_sharing();
734 }
735 else if (Motcle(checkpoint_format_) == "single_hdf")
736 bytes = pb_base_->sauvegarder(*osauv_hdf_);
737 else
738 bytes = pb_base_->sauvegarder(ficsauv_.valeur());
741
742 // Si c'est une sauvegarde simple, on referme immediatement et proprement le fichier
743 if (simple_restart_ && !pdi_format)
744 {
745 if (Motcle(checkpoint_format_) == "xyz")
746 {
748 ficsauv_.valeur() << Nom("fin");
749 (ficsauv_.valeur()).flush();
750 (ficsauv_.valeur()).syncfile();
751 }
752 else if (Motcle(checkpoint_format_) == "single_hdf")
753 {
754 *osauv_hdf_ << Nom("fin");
755 FichierHDFPar fic_hdf;
756 fic_hdf.create(checkpoint_filename_);
757 fic_hdf.create_and_fill_dataset_MW("/sauv", *osauv_hdf_);
758 fic_hdf.close();
759 delete osauv_hdf_;
760 osauv_hdf_ = 0;
761 }
762 else
763 {
764 ficsauv_.valeur() << Nom("fin");
765 (ficsauv_.valeur()).flush();
766 }
767 ficsauv_.detach();
768 }
769 return bytes;
770}
771
773{
774 // On ferme proprement le fichier de sauvegarde
775 // Si c'est une sauvegarde_simple, le fin a ete mis a chaque appel a ::sauver()
776 if(Motcle(checkpoint_format_) == "pdi" && TRUST_2_PDI::is_PDI_initialized())
778 else if (!simple_restart_ && (ficsauv_ || osauv_hdf_) )
779 {
780 if (Motcle(checkpoint_format_) == "xyz")
781 {
783 ficsauv_.valeur() << Nom("fin");
784 (ficsauv_.valeur()).flush();
785 (ficsauv_.valeur()).syncfile();
786 }
787 else if (Motcle(checkpoint_format_) == "single_hdf")
788 {
789 *osauv_hdf_ << Nom("fin");
790 FichierHDFPar fic_hdf;
791 fic_hdf.create(checkpoint_filename_);
792 fic_hdf.create_and_fill_dataset_MW("/sauv", *osauv_hdf_);
793 fic_hdf.close();
794 delete osauv_hdf_;
795 osauv_hdf_ = 0;
796 }
797 else
798 {
799 ficsauv_.valeur() << Nom("fin");
800 (ficsauv_.valeur()).flush();
801 }
802
803 ficsauv_.detach();
804 }
805 // Si la sauvegarde est classique et que l'utilisateur n'a pas desactive la sauvegarde finale xyz
806 // alors on effectue la sauvegarde finale xyz
807 if (Motcle(checkpoint_format_) != "xyz")
808 {
810 sauver_xyz(1);
811 else
812 Cerr << "As saving .xyz file disabled since 1.9.7, add into your datafile \"EcritureLectureSpecial 1\" to enable it again if wanted." << finl;
813 }
814
815 for(int i=0; i<pb_base_->nombre_d_equations(); i++)
816 pb_base_->equation(i).close_save_file();
817}
int get_node_id() const
Retrieve ID of my numa node.
Definition Comm_Group.h:199
int get_number_of_nodes() const
Definition Comm_Group.h:204
classe Ecrire_YAML Use this to generate a yaml file that will then be read by the PDI library (for ch...
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()
Renvoie le mode d'ecriture utilise (pour pouvoir le modifier).
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)
Cette classe implemente les operateurs et les methodes virtuelles de la classe EFichier de la facon s...
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
Un tableau d'objets de la classe Motcle.
Definition Motcle.h:63
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
Renvoie *this;.
Definition Nom.cpp:563
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
virtual int reprendre(Entree &)
Reprise d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:338
static const Comm_Group & get_node_group()
Renvoie une reference au groupe sur les noeuds.
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
static double mp_min(double)
Definition Process.cpp:386
static double mp_max(double)
Definition Process.cpp:376
static int node_master()
renvoie 1 si on est sur le processeur maitre du noeud numa, 0 sinon.
Definition Process.cpp:95
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static void barrier()
Synchronise tous les processeurs du groupe courant (attend que tous les processeurs soient arrives a ...
Definition Process.cpp:136
static bool force_single_file(const int ranks, const Nom &filename)
Definition Process.cpp:60
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
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
bool & reprise_effectuee()
void preparer_calcul()
int sauver() const
Ecriture sur fichier en vue d'une reprise (sauvegarde).
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
Verifie que la place necessaire existe sur le disque dur.
This derived class of Sortie stacks whatever it receives in an internal binary buffer.
Classe derivee de Sortie qui ne sort les donnees nulle part (c'est une poubelle) Classe utilisee dans...
_TYPE_ * data()
classe 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)