TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Format_Post_Lata.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 <EcrFicPartageMPIIO.h>
17#include <Format_Post_Lata.h>
18#include <EcrFicPartageBin.h>
19#include <communications.h>
20#include <Fichier_Lata.h>
21#include <EFichier.h>
22#include <sys/stat.h>
23#include <Param.h>
24#include <string> // Necessaire avec xlC pour std::getline
25
26Implemente_instanciable_sans_constructeur(Format_Post_Lata,"Format_Post_Lata",Format_Post_base);
27
28#define _LATA_INT_TYPE_ trustIdType
29
30/*! @brief Constructeur par defaut: format_ ASCII et options_para_ = SINGLE_FILE
31 *
32 */
37
38/*! @brief Remet l'objet dans l'etat obtenu par le constructeur par defaut.
39 *
40 */
42{
43 lata_basename_ = "??";
44 format_ = ASCII;
46 status = RESET;
48 tinit_ = -1.;
49 temps_courant_ = -1.;
50}
51
52void Format_Post_Lata::resetTime(double t, const std::string dirname)
53{
54 temps_courant_ = -1; // not using t - this will come from outside when calling 'ecrire_temps'
55}
56
58{
59 Process::exit("Format_Post_Lata::printOn : error");
60 return os;
61}
62
63/*! @brief Lecture des parametres du postraitement au format "jeu de donnees" Le format attendu est le suivant:
64 *
65 * {
66 * nom_fichier nom champ obligatoire
67 * [ format ascii|binaire ] valeur par defaut : ascii
68 * [ parallel single_file|multiple_files ] valeur par defaut : single_file
69 * }
70 *
71 */
73{
74 assert(status == RESET);
77 return is;
78}
79
81{
82 Cerr << "Format_Post_Lata::set_param: Not implemented." << finl;
84}
85
87{
88 Cerr << "Format_Post_Lata::lire_motcle_non_standard: Not implemented." << finl;
90 return 0;
91}
92
93/*! @brief Renvoie l'extension conventionnelle des fichiers lata : ".lata"
94 *
95 */
97{
98 static const char * ext = ".lata";
99 return ext;
100}
101
102/*! @brief Renvoie le nom d'un fichier sans le path : on enleve les caracteres avant le dernier /
103 *
104 */
105const char * Format_Post_Lata::remove_path(const char * filename)
106{
107 int i = (int)strlen(filename);
108 while (i > 0 && filename[i-1] != '/')
109 i--;
110 return filename + i;
111}
112
113/*! @brief Ouvre le fichier maitre en mode ERASE et ecrit l'entete du fichier lata (sur le processeur maitre seulement).
114 *
115 * void Format_Post_Lata::ecrire_entete_lata()
116 *
117 */
118int Format_Post_Lata::ecrire_entete(const double temps_courant, const int reprise, const int est_le_premier_post)
119{
121 return 1;
122}
123
124int Format_Post_Lata::completer_post(const Domaine&, const int , const Nature_du_champ&, const int , const Noms&, const Motcle&, const Nom&)
125{
126 return 1;
127}
128
129int Format_Post_Lata::preparer_post(const Nom& , const int , const int , const double )
130{
131 return 1;
132}
133
134namespace
135{
136
137template<typename TYP, typename LATA_TYP>
138void fill_tmp_array(const TRUSTTab<TYP,int>& tab, int upper, int offset, bool decal_fort, trustIdType decalage_partiel, LATA_TYP *tmp);
139
140template<typename TYP>
141typename std::enable_if_t<std::is_same<TYP, int>::value || std::is_same<TYP, trustIdType>::value, void>
142fill_tmp_array(const TRUSTTab<TYP,int>& tab, int upper, int offset, bool decal_fort, trustIdType decalage_partiel, _LATA_INT_TYPE_ *tmp)
143{
144 trustIdType decal_fort_val = decal_fort ? 1 : 0;
145 const TYP *data = tab.addr();
146 for (int i = 0; i < upper; i++)
147 {
148 // valeur a ecrire (conversion en numerotation fortran si besoin)
149 _LATA_INT_TYPE_ x = data[i+offset];
150 if (x > -1)
151 x += decalage_partiel;
152 else
153 x += decal_fort_val;
154 tmp[i] = x;
155 }
156}
157
158template<>
159void fill_tmp_array<double, float>(const TRUSTTab<double,int>& tab, int upper, int offset, bool , trustIdType , float *tmp)
160{
161 const double *data = tab.addr();
162 for (int i = 0; i < upper; i++)
163 tmp[i] = (float) data[i+offset]; // downcast to float
164}
165
166/** Generic method to write the block corresponding to an array of data in a LATA file
167 */
168template<typename TYP, typename LATA_TYP>
169trustIdType write_T_tab(Fichier_Lata& fichier, bool decal_fort, trustIdType decalage_partiel, const TRUSTTab<TYP,int>& tab, int& nb_colonnes, const Format_Post_Lata::Options_Para& option)
170{
171 int nb_lignes = tab.dimension(0);
172 int line_size = 1;
173 const int nb_dim = tab.nb_dim();
174
175 for (int i = 1; i < nb_dim; i++)
176 line_size *= tab.dimension(i);
177
178 trustIdType nb_lignes_tot = 0;
179
180 const int tab_size = line_size * nb_lignes;
181 trustIdType nb_octets = tab_size * (trustIdType) sizeof(LATA_TYP);
182 switch(option)
183 {
186 nb_lignes_tot = Process::mp_sum(nb_lignes);
187 // En parallele, tous les tableaux doivent avoir le meme nombre de colonnes (ou etre vides).
188 nb_colonnes = Process::mp_max(line_size);
189 nb_octets = nb_colonnes * nb_lignes_tot * (trustIdType) sizeof(LATA_TYP);
190 assert(nb_lignes == 0 || line_size == nb_colonnes);
191 break;
193 nb_lignes_tot = nb_lignes;
194 nb_colonnes = line_size;
195 break;
196 default:
197 Cerr << "Format_Post_Lata_write_tab: error nb_lignes_tot" << finl;
199 }
200
201 SFichier& sfichier = fichier.get_SFichier();
202
203 // Debut de bloc fortran
204 if (fichier.is_master())
205 sfichier << nb_octets << finl;
206
207 // Ecriture des donnees.
208 if (sub_type(EcrFicPartageMPIIO, sfichier))
209 {
210 // On convertit le tout en LATA_TYP
211 LATA_TYP *tmp = new LATA_TYP[tab_size];
212 fill_tmp_array(tab, tab_size, 0, decal_fort, decalage_partiel, tmp);
213 sfichier.put(tmp, tab_size, line_size);
214 delete[] tmp;
215 // Fin de bloc fortran
216 if (fichier.is_master())
217 sfichier << nb_octets << finl;
218 }
219 else
220 {
221 // On convertit le tout en _INT_TYPE_ par paquet de N valeurs
222 // Buffer dont la taille est un multiple de line_size:
223 const int N = 16384;
224 int bufsize = (N / line_size + 1) * line_size;
225 LATA_TYP *tmp = new LATA_TYP[bufsize];
226 for (int i = 0; i < tab_size; i += bufsize)
227 {
228 int j_max = bufsize;
229 if (j_max > tab_size - i)
230 j_max = tab_size - i;
231
232 // Conversion du bloc en LATA_TYP:
233 fill_tmp_array(tab, j_max, i, decal_fort, decalage_partiel, tmp);
234
235 // Ecriture avec retour a la ligne a chaque ligne du tableau
236 sfichier.put(tmp, j_max, line_size);
237 }
238 delete[] tmp;
239 fichier.syncfile();
240 // Fin de bloc fortran
241 if (fichier.is_master())
242 sfichier << nb_octets << finl;
243 fichier.syncfile();
244 }
245 return nb_lignes_tot;
246}
247
248} // end anonymous namespace
249
250
251/*! @brief fichier est un fichier lata de donnees (pas le fichier maitre) on y ecrit le tableau tab tel quel (en binaire ou ascii et sur un ou
252 *
253 * plusieurs fichiers en parallel).
254 * nb_colonnes est rempli avec le produit des tab.dimension(i) pour i>0
255 *
256 */
257trustIdType Format_Post_Lata::write_doubletab(Fichier_Lata& fichier, const DoubleTab& tab, int& nb_colonnes, const Options_Para& option)
258{
259 return ::write_T_tab<double, float>(fichier, 0, 0, tab, nb_colonnes, option);
260}
261
262
263/*! @brief Ecriture d'un tableau d'entiers dans le fichier fourni.
264 *
265 * Les valeurs ecrites sont les valeurs du tableau auquelles ont ajoute "decalage". Cette valeur est utilisee pour passer en numerotation
266 * fortran (ajouter 1), ou pour passer en numerotation globale (ajouter le nombre d'elements sur les processeurs precedents).
267 *
268 * On renvoie dans nb_colonnes la somme des dimension(i) pour i>0.
269 * Valeur de retour: somme des dimension(0) ecrits (selon que tous les processeurs ecrivent sur le meme fichier ou pas).
270 */
271trustIdType Format_Post_Lata::write_inttab(Fichier_Lata& fichier, bool decal_fort, trustIdType decalage_partiel, const IntTab& tab, int& nb_colonnes, const Options_Para& option)
272{
273 return ::write_T_tab<int, _LATA_INT_TYPE_>(fichier, decal_fort, decalage_partiel, tab, nb_colonnes, option);
274}
275
276/*! @brief Initialisation de la classe avec des parametres par defaut (format ASCII, SINGLE_FILE)
277 *
278 */
280{
281 assert(status == RESET);
282 initialize_lata(file_basename, ASCII, SINGLE_FILE);
283 return 1;
284}
285
286int Format_Post_Lata::initialize(const Nom& file_basename, const int format, const Nom& option_para)
287{
288 assert(status == RESET);
289 // Changement du format LATA (par defaut binaire)
291 if (format == 0)
292 format_ = ASCII;
293
294 if (Motcle(option_para) == "MPI-IO")
296 else if (Motcle(option_para) == "SIMPLE")
298 else if (Motcle(option_para) == "MULTIPLE")
300 else
301 {
302 Cerr << "The option " << option_para << " for lata format for the parallel is not correct." << finl;
304 }
305
306 initialize_lata(file_basename, format_, options_para_);
307
308 return 1;
309}
310
311/*! @brief Initialisation de la classe, ouverture du fichier et ecriture de l'entete.
312 *
313 */
314int Format_Post_Lata::initialize_lata(const Nom& file_basename, const Format format, const Options_Para options_para)
315{
316 assert(status == RESET);
317 lata_basename_ = file_basename;
318 format_ = format;
319 options_para_ = options_para;
321 return 1;
322}
323
324/*! @brief Modifying name of the post file, plus some clever management of previously saved data in case of restart.
325 */
326int Format_Post_Lata::modify_file_basename(const Nom file_basename, bool for_restart, const double tinit)
327{
328 Nom post_file;
329 post_file = file_basename + extension_lata();
330 // On verifie que le fichier maitre existe et a une entete correcte
331 bool master_file_exists = false;
333 {
334 struct stat f;
335 if (stat(post_file, &f) == 0)
336 {
337 EFichier tmp(post_file);
338 Nom cle;
339 tmp >> cle;
340 if (cle.debute_par("LATA"))
341 {
342 if (tinit == -1)
343 master_file_exists = true;
344 else
345 {
346 tmp >> cle;
347 while (!tmp.eof() && cle != "TEMPS")
348 tmp >> cle;
349 if (cle == "TEMPS")
350 {
351 double temps;
352 tmp >> temps;
353 // On verifie le temps du fichier de reprise
354 if (temps < tinit)
355 master_file_exists = true;
356 }
357 }
358 }
359 tmp.close();
360 }
361 }
362
363 // Saving what was there before:
364 master_file_exists = (bool) Process::mp_max((int)master_file_exists);
365 if (Process::je_suis_maitre() && master_file_exists && !restart_already_moved_ && for_restart)
366 {
367 Nom before_restart;
368 before_restart = file_basename + ".before_restart" + extension_lata();
369 rename(post_file, before_restart);
370 Cerr << "File " << post_file << " is moved to " << before_restart << " with times<=tinit=" << tinit << finl;
371 reconstruct(post_file, before_restart, tinit);
372 }
373 if (for_restart)
375
376 Process::barrier(); // really necessary?
377
378 lata_basename_ = file_basename;
379
380 if (master_file_exists && for_restart)
381 {
382 lata_basename_ += ".after_restart";
383 if (tinit == -1)
384 finir_sans_reprise(post_file);
385 }
386 return 1;
387}
388
389// Copie du debut du fichier before_restart dans post_file (jusqu'au TEMPS=tinit)
390int Format_Post_Lata::reconstruct(const Nom post_file, const Nom before_restart, const double tinit)
391{
392 EFichier LataOld(before_restart);
393 SFichier LataNew(post_file);
394 LataNew.setf(ios::scientific);
395 LataNew.precision(8);
396 std::string line;
397 Nom mot;
398 double temps;
399 tinit_ = tinit;
400 while (!LataOld.eof())
401 {
402 LataOld >> mot; // je lis le premier mot de la ligne dans .before_restart.lata
403 if (mot != "FIN") // Si le mot n'est pas FIN
404 {
405 if (mot == "TEMPS") // Si le mot suivant est TEMPS
406 {
407 LataOld >> temps;
408 if (temps == tinit) // Si le temps trouvee = tinit alors j'arrete
409 break;
410 std::getline(LataOld.get_ifstream(), line); // je lis le reste de la ligne
411 LataNew.get_ofstream() << mot << " " << temps << line << std::endl; // et j'ecris le tout dans le lata
412 }
413 else
414 {
415 std::getline(LataOld.get_ifstream(), line); // je lis le reste de la ligne
416 LataNew.get_ofstream() << mot << line << std::endl; // et j'ecris le tout dans le lata
417 }
418 }
419 else
420 {
421 break; // Sinon j'arrete
422 }
423 }
424 LataNew.close();
425 LataOld.close();
426 Cerr << "File " << post_file << " is rebuilt but truncated to times<tinit=" << tinit << finl;
427 return 1;
428}
429
431{
432 Nom post_file;
433 post_file = lata_basename_ + extension_lata();
435 {
436 struct stat f;
437 if (stat(post_file, &f) == 0) // if file exists
438 {
439 EFichier Lata(file_basename);
440 SFichier LataRep(post_file, ios::app);
441 LataRep.setf(ios::scientific);
442 LataRep.precision(8);
443 std::string line;
444 Nom mot;
445 double temps;
446 while (!Lata.eof())
447 {
448 Lata >> mot; // je lis le premier mot de la ligne dans .lata
449 if (mot == "TEMPS") // Si le mot suivant n'est pas TEMPS
450 {
451 Lata >> temps;
452 if (temps == tinit_) // Si le temps trouvee = tinit alors
453 {
454 std::getline(Lata.get_ifstream(), line);
455 LataRep.get_ofstream() << mot << " " << temps << line << std::endl; // je peux commencer a ecrire
456 break;
457 }
458 }
459 }
460 while (!Lata.eof())
461 {
462 std::getline(Lata.get_ifstream(), line); // je lis le reste du .lata
463 LataRep.get_ofstream() << line << std::endl; // et j'ecris le tout dans le after_restart.lata
464 }
465 Lata.close();
466 LataRep.close();
467 Cerr << "File " << post_file << " is built with times from tinit=" << tinit_ << finl;
468 }
469 }
470 return 1;
471}
472
473/*! Write the "fileoffset=..." when needed in master lata file
474 */
475void Format_Post_Lata::ecrire_offset(SFichier& sfichier, long int offset_single_lata)
476{
478 sfichier << " file_offset=" << offset_single_lata;
479 else
480 {
481#ifdef INT_is_64_
482 // 64b binary file start with the tag "INT64" which is 6 bytes long with the \0 terminating char.
483 // In ASCII this is not needed.
484 if(format_ == BINAIRE)
485 sfichier << " file_offset=6";
486#endif
487 }
488}
489
490// E Saikali : on ajoute cette liste qui est utile pour un probleme couple dans le cas ou on ecrit dans meme fichier
491static Noms liste_single_lata_ecrit;
492
493/*! @brief Low level routine to write a mesh into a LATA file.
494 *
495 * Also called directly in TrioCFD, by Postraitement_ft_lata for interface writing.
496 */
497void Format_Post_Lata::ecrire_domaine_low_level(const Nom& id_domaine, const DoubleTab& sommets, const IntTab& elements, const Motcle& type_element)
498{
499 const int dim = sommets.dimension(1);
500 Motcle type_elem(type_element);
501
502 // GF Pour assuerer la lecture avec le plugin lata
503 if (type_element == "PRISME") type_elem = "PRISM6";
504
505 trustIdType nb_som_tot, nb_elem_tot; // Nombre de sommets/elements dans le fichier
506
507 // Construction du nom du fichier de geometrie
508 Nom basename_geom(lata_basename_), extension_geom(extension_lata());
509
510 if (un_seul_fichier_lata_) extension_geom += "_single";
511 else
512 {
513 extension_geom += ".";
514 extension_geom += id_domaine;
515 extension_geom += ".";
516 char str_temps[100] = "0.0";
517 if (temps_courant_ >= 0.)
518 snprintf(str_temps, 100, "%.10f", temps_courant_);
519 extension_geom += Nom(str_temps);
520 }
521
522 Nom nom_fichier_geom;
523 trustIdType decalage_sommets = 1, decalage_elements = 1;
524
525 {
526 const bool not_in_list = !liste_single_lata_ecrit.contient_(lata_basename_),
527 should_erase = (!un_seul_fichier_lata_) ? true /* Always erase */ : (offset_elem_ < 0 && not_in_list);
528
529 Fichier_Lata fichier_geom(basename_geom, extension_geom, should_erase ? Fichier_Lata::ERASE : Fichier_Lata::APPEND, format_, options_para_);
530
531 // on ajout dans la liste si pas dedans et si un_seul_fichier_lata_ !!!
532 if (not_in_list && un_seul_fichier_lata_) liste_single_lata_ecrit.add(lata_basename_); // BOOM !
533
534 nom_fichier_geom = fichier_geom.get_filename();
535 int nb_col;
536
538 if (fichier_geom.is_master())
539 offset_som_ = fichier_geom.get_SFichier().get_ofstream().tellp();
540
541 // Coordonnees des sommets
542 if (axi)
543 {
544 DoubleTab sommets2(sommets);
545 int ns = sommets2.dimension_tot(0);
546 for (int s = 0; s < ns; s++)
547 {
548 double r = sommets(s, 0), theta = sommets(s, 1);
549 sommets2(s, 0) = r * cos(theta);
550 sommets2(s, 1) = r * sin(theta);
551 }
552 nb_som_tot = write_doubletab(fichier_geom, sommets2, nb_col, options_para_);
553 }
554 else
555 nb_som_tot = write_doubletab(fichier_geom, sommets, nb_col, options_para_);
556
557 assert(nb_som_tot == 0 || nb_col == dim);
558
559 // Elements : Les indices de sommets, elements et autres dans le fichier lata commencent a 1 :
561 {
562 // Tous les processeurs ecrivent dans un fichier unique, il faut renumeroter les indices pour passer en numerotation globale.
563 // Le processeur 0 numerote ses sommets de 1 a n0
564 // Le processeur 1 numerote ses sommets de n0+1 a n0+n1, etc...
565 // Decalage a ajouter aux indices pour avoir une numerotation globale.
566 const int nbsom = sommets.dimension(0);
567 decalage_sommets += mppartial_sum(nbsom);
568 const int nbelem = elements.dimension(0);
569 decalage_elements += mppartial_sum(nbelem);
570 }
571
573 {
574 if (fichier_geom.is_master())
575 offset_elem_ = fichier_geom.get_SFichier().get_ofstream().tellp();
576
577 nb_elem_tot = write_inttab(fichier_geom, true, decalage_sommets, elements, nb_col, options_para_);
578 }
579 else
580 {
581 Fichier_Lata fichier_geom_elem(basename_geom, extension_geom + Nom(".elem"), Fichier_Lata::ERASE, format_, options_para_);
582 nb_elem_tot = write_inttab(fichier_geom_elem, true, decalage_sommets, elements, nb_col, options_para_);
583 }
584 }
585
586 {
587 // Attention, il faut refermer le fichier avant d'appeler ecrire_item_int qui va ouvrir a nouveau le fichier.
589 SFichier& sfichier = fichier_lata.get_SFichier();
590
591 if (fichier_lata.is_master())
592 {
593 sfichier << "GEOM " << id_domaine;
594 sfichier << " type_elem=" << type_elem << finl;
595
596 // SOMMETS support
597 sfichier << "CHAMP SOMMETS " << remove_path(nom_fichier_geom);
598 sfichier << " geometrie=" << id_domaine;
599 sfichier << " size=" << nb_som_tot;
600 sfichier << " composantes=" << dim;
601 ecrire_offset(sfichier, offset_som_);
602 sfichier << finl;
603
604 // ELEMENTS support
605 sfichier << "CHAMP ELEMENTS " << remove_path(nom_fichier_geom);
606 if (!un_seul_fichier_lata_) sfichier << ".elem";
607 sfichier << " geometrie=" << id_domaine;
608 sfichier << " size=" << nb_elem_tot << " composantes=" << elements.dimension(1);
609
610 ecrire_offset(sfichier, offset_elem_);
611
612
613 switch(sizeof(_LATA_INT_TYPE_))
614 {
615 case 4:
616 sfichier << " format=INT32" << finl;
617 break;
618 case 8:
619 sfichier << " format=INT64" << finl;
620 break;
621 default:
622 Cerr << "Error in Format_Post_Lata::ecrire_entete\n" << " sizeof(int) not supported" << finl;
624 }
625
626 }
627 fichier_lata.syncfile();
628 }
629
630 // En mode parallele, on ecrit en plus des fichiers contenant les donnees paralleles sur les sommets, les elements et les faces...
633 {
634 TIDTab data(1,2);
635 data(0, 0) = decalage_sommets;
636 data(0, 1) = sommets.dimension(0);
637 ecrire_item_tid("JOINTS_SOMMETS",
638 id_domaine,
639 "", /* id_domaine */
640 "", /* localisation */
641 "", /* reference */
642 data,
643 0); /* reference_size */
644 data(0, 0) = decalage_elements;
645 data(0, 1) = elements.dimension(0);
646 ecrire_item_tid("JOINTS_ELEMENTS",
647 id_domaine,
648 "", /* id_domaine */
649 "", /* localisation */
650 "", /* reference */
651 data,
652 0); /* reference_size */
653 }
654}
655
656/*! @brief voir Format_Post_base::ecrire_domaine On accepte l'ecriture d'un domaine dans un pas de temps, mais
657 *
658 * les id_domaines doivent etre tous distincts.
659 * Ecrit le fichier "basename(_XXXXX).lata.nom_domaine", qui contient la liste des sommets et la liste des elements.
660 * Si le PE est maitre, ouvre le fichier maitre en mode APPEND et ajoute une reference a ce fichier.
661 */
662int Format_Post_Lata::ecrire_domaine(const Domaine& domaine,const int est_le_premier_post)
663{
664 if (status == RESET)
665 {
666 Cerr << "Error in Format_Post_Lata::ecrire_domaine\n" << " status = RESET. Uninitialized object" << finl;
668 }
669 Motcle type_elem = domaine.type_elem()->que_suis_je();
670
671 ecrire_domaine_low_level(domaine.le_nom(), domaine.les_sommets(), domaine.les_elems(), type_elem);
672
673 // Si on a des frontieres domaine, on les ecrit egalement
674 const LIST(OBS_PTR(Domaine)) bords= domaine.domaines_frontieres();
675 for (int i=0; i<bords.size(); i++)
676 ecrire_domaine(bords[i].valeur(),est_le_premier_post);
677
678 return 1; // ok tout va bien
679}
680
681/*! @brief commence l'ecriture d'un nouveau pas de temps En l'occurence pour le format LATA:
682 *
683 * Ouvre le fichier maitre en mode APPEND et ajoute une ligne
684 * "TEMPS xxxxx" si ce temps n'a pas encore ete ecrit
685 *
686 */
687int Format_Post_Lata::ecrire_temps(const double temps)
688{
690 return 1;
691}
692
693/*! @brief voir Format_Post_base::ecrire_champ
694 *
695 */
696int Format_Post_Lata::ecrire_champ(const Domaine& domaine, const Noms& unite_, const Noms& noms_compo, int ncomp, double temps, const Nom& id_du_champ, const Nom& id_du_domaine,
697 const Nom& localisation, const Nom& nature, const DoubleTab& valeurs)
698{
699 Motcle id_du_champ_modifie(id_du_champ), iddomaine(id_du_domaine);
700
701 //On utilise prefix avec un argument en majuscule
702 if ((Motcle) localisation == "SOM")
703 {
704 id_du_champ_modifie.prefix(id_du_domaine);
705 id_du_champ_modifie.prefix(iddomaine);
706 id_du_champ_modifie.prefix("_SOM_");
707 }
708 else if ((Motcle) localisation == "ELEM")
709 {
710 id_du_champ_modifie.prefix(id_du_domaine);
711 id_du_champ_modifie.prefix(iddomaine);
712 id_du_champ_modifie.prefix("_ELEM_");
713 }
714 else if ((Motcle) localisation == "FACES")
715 {
716 id_du_champ_modifie.prefix(id_du_domaine);
717 id_du_champ_modifie.prefix(iddomaine);
718 id_du_champ_modifie.prefix("_FACES_");
719 }
720 Nom& id_champ = id_du_champ_modifie;
721
722 // Construction du nom du fichier
723 Nom basename_champ(lata_basename_), extension_champ(extension_lata());
724
725 if (un_seul_fichier_lata_) extension_champ += "_single";
726 else
727 {
728 extension_champ += ".";
729 extension_champ += id_champ;
730 extension_champ += ".";
731 extension_champ += localisation;
732 extension_champ += ".";
733 extension_champ += id_du_domaine;
734 extension_champ += ".";
735 char str_temps[100] = "0.0";
736 if (temps >= 0.)
737 snprintf(str_temps, 100, "%.10f", temps);
738 extension_champ += str_temps;
739 }
740
741 Nom filename_champ;
742 trustIdType size_tot;
743 int nb_compo;
744 {
745 const bool not_in_list = !liste_single_lata_ecrit.contient_(lata_basename_),
746 should_erase = (!un_seul_fichier_lata_) ? true /* Always erase */ : (offset_elem_ < 0 && not_in_list);
747
748 Fichier_Lata fichier_champ(basename_champ, extension_champ, should_erase ? Fichier_Lata::ERASE : Fichier_Lata::APPEND, format_, options_para_);
749
750 // on ajout dans la liste si pas dedans et si un_seul_fichier_lata_ !!!
751 if (not_in_list && un_seul_fichier_lata_) liste_single_lata_ecrit.add(lata_basename_); // BOOM !
752
753 // XXX Elie Saikali : attention offset ici avant write_doubletab ! sinon decalage d'un champ !
755 if (fichier_champ.is_master())
756 offset_elem_ = fichier_champ.get_SFichier().get_ofstream().tellp();
757
758 filename_champ = fichier_champ.get_filename();
759 size_tot = write_doubletab(fichier_champ, valeurs, nb_compo, options_para_);
760 }
761
762 // Ouverture du fichier .lata en mode append.
763 // Ajout de la reference au champ
765 SFichier& sfichier = fichier.get_SFichier();
766 if (fichier.is_master())
767 {
768 sfichier << "Champ " << id_champ << " ";
769 sfichier << remove_path(filename_champ);
770 sfichier << " geometrie=" << id_du_domaine;
771 sfichier << " localisation=" << localisation;
772 sfichier << " size=" << size_tot;
773 sfichier << " nature=" << nature;
774 sfichier << " noms_compo=" << noms_compo[0];
775 for (int k = 1; k < noms_compo.size(); k++)
776 sfichier << "," << noms_compo[k];
777
778 sfichier << " composantes=" << nb_compo;
779
780 ecrire_offset(sfichier, offset_elem_);
781
782 sfichier << finl;
783 }
784 fichier.syncfile();
785
786 return 1;
787}
788
789/*! @brief voir Format_Post_base::ecrire_champ ATTENTION: si "reference" est non vide on ajoute 1 a toutes les
790 *
791 * valeurs pour passer en numerotation fortran, et si de plus on ecrit un fichier lata unique pour tous les processeurs, on ajoute un
792 * decalage a toutes les valeurs (renumerotation des indices pour passer en numerotation globale, voir le codage de ecrire_domaine par exemple)
793 *
794 */
795template<typename TYP>
796int Format_Post_Lata::ecrire_item_integral_T(const Nom& id_item, const Nom& id_du_domaine, const Nom& id_domaine, const Nom& localisation,
797 const Nom& reference, const TRUSTVect<TYP, int>& val, const int reference_size)
798{
799 // Construction du nom du fichier
800 Nom basename_champ(lata_basename_), extension_champ(extension_lata());
801
802 if (un_seul_fichier_lata_) extension_champ += "_single";
803 else
804 {
805 extension_champ += ".";
806 //extension_champ += id_champ;
807 extension_champ += id_item;
808 extension_champ += ".";
809 extension_champ += localisation;
810 extension_champ += ".";
811 extension_champ += id_du_domaine;
812 extension_champ += ".";
813 char str_temps[100] = "0.0";
814 if (temps_courant_ >= 0.)
815 snprintf(str_temps, 100, "%.10f", temps_courant_);
816 extension_champ += Nom(str_temps);
817 }
818
819 Nom filename_champ;
820 trustIdType size_tot;
821 int nb_compo = 0; // filled by ::write_T_tab() below, but my compiler doesn't see it since I templatized it.
822 const TRUSTTab<TYP, int> valeurs = static_cast<const TRUSTTab<TYP, int>&>(val);
823 {
824 const bool not_in_list = !liste_single_lata_ecrit.contient_(lata_basename_),
825 should_erase = (!un_seul_fichier_lata_) ? true /* Always erase */ : (offset_elem_ < 0 && not_in_list);
826
827 Fichier_Lata fichier_champ(basename_champ, extension_champ, should_erase ? Fichier_Lata::ERASE : Fichier_Lata::APPEND, format_, options_para_);
828
829 // on ajout dans la liste si pas dedans et si un_seul_fichier_lata_ !!!
830 if (not_in_list && un_seul_fichier_lata_) liste_single_lata_ecrit.add(lata_basename_); // BOOM !
831
833 if (fichier_champ.is_master())
834 offset_elem_ = fichier_champ.get_SFichier().get_ofstream().tellp();
835
836 filename_champ = fichier_champ.get_filename();
837 // On suppose que si reference est non vide, c'est un indice dans un autre tableau, donc numerotation fortran :
838 bool decal = false;
839 trustIdType decal_partiel = 0;
840 if (reference != "")
841 {
842 decal = true;
843 decal_partiel = 1;
845 {
846 // Tous les processeurs ecrivent dans un fichier unique, il faut renumeroter les indices pour passer en numerotation globale.
847 // Decalage a ajouter aux indices pour avoir une numerotation globale.
848 decal_partiel += mppartial_sum(reference_size);
849 }
850 }
851 size_tot = ::write_T_tab<TYP, _LATA_INT_TYPE_>(fichier_champ, decal, decal_partiel, valeurs, nb_compo, options_para_);
852 }
853
854 {
855 // Ouverture du fichier .lata en mode append. Ajout de la reference au champ
856 Fichier_Lata_maitre fichier(lata_basename_, extension_lata(), Fichier_Lata::APPEND, options_para_);
857 SFichier& sfichier = fichier.get_SFichier();
858 if (fichier.is_master())
859 {
860 sfichier << "Champ " << id_item << " ";
861 sfichier << remove_path(filename_champ);
862 sfichier << " geometrie=" << id_du_domaine;
863
864 if (localisation != "") sfichier << " localisation=" << localisation;
865
866 sfichier << " size=" << size_tot;
867 sfichier << " composantes=" << nb_compo;
868 if (reference != "") sfichier << " reference=" << reference;
869
870 ecrire_offset(sfichier, offset_elem_);
871
872 const int sz = (int) sizeof(_LATA_INT_TYPE_);
873 switch(sz)
874 {
875 case 4:
876 sfichier << " format=int32";
877 break;
878 case 8:
879 sfichier << " format=int64";
880 break;
881 default:
882 Cerr << "Error in Format_Post_Lata::ecrire_champ_lata\n" << " Integer type not supported: size=" << sz << finl;
883 exit();
884 }
885 sfichier << finl;
886 }
887 fichier.syncfile();
888 }
889
890 // Astuce pour les donnees paralleles des faces:
891 if ((id_item == "FACES" && Process::is_parallel()) && (options_para_ == SINGLE_FILE || options_para_ == SINGLE_FILE_MPIIO))
892 {
893 const int n = valeurs.dimension(0);
894 TIDTab data(1,2);
895 data(0, 0) = 1 + mppartial_sum(n);
896 data(0, 1) = n;
897 ecrire_item_tid("JOINTS_FACES",
898 id_du_domaine,
899 "", /* id_domaine */
900 "", /* localisation */
901 "", /* reference */
902 data,
903 0); /* reference_size */
904 }
905 return 1;
906}
907
908int Format_Post_Lata::ecrire_item_int(const Nom& id_item, const Nom& id_du_domaine, const Nom& id_domaine, const Nom& localisation,
909 const Nom& reference, const IntVect& val, const int reference_size)
910{
911 return ecrire_item_integral_T(id_item, id_du_domaine, id_domaine, localisation, reference, val, reference_size);
912}
913
914int Format_Post_Lata::ecrire_item_tid(const Nom& id_item, const Nom& id_du_domaine, const Nom& id_domaine, const Nom& localisation,
915 const Nom& reference, const TIDVect& val, const int reference_size)
916{
917 return ecrire_item_integral_T(id_item, id_du_domaine, id_domaine, localisation, reference, val, reference_size);
918}
919
920int Format_Post_Lata::ecrire_entete_lata(const Nom& base_name, const Options_Para& option, const Format& format, const int est_le_premier_post)
921{
922 if (est_le_premier_post)
923 {
924 // Determination du format binaire:
925 // big endian => l'entier 32 bits "1" s'ecrit 0x00 0x00 0x00 0x01
926 // little endian => 0x01 0x00 0x00 0x00
927 const unsigned int one = 1;
928 const int big_endian = (*((unsigned char*) &one) == 0) ? 1 : 0;
929
930 // Effacement du fichier .lata et ecriture de l'entete
932
933 SFichier& sfichier = fichier.get_SFichier();
934 if (fichier.is_master())
935 {
936 sfichier << "LATA_V2.1 TRUST version " << TRUST_VERSION << finl;
937 sfichier << Objet_U::nom_du_cas() << finl;
938 sfichier << "Trio_U verbosity=0" << finl;
939
940 sfichier << "Format ";
941 switch(format)
942 {
943 case ASCII:
944 sfichier << "ASCII,";
945 break;
946 case BINAIRE:
947 sfichier << "BINAIRE,";
948 if (big_endian)
949 sfichier << "BIG_ENDIAN,";
950 else
951 sfichier << "LITTLE_ENDIAN,";
952 break;
953 default:
954 Cerr << "Error in Format_Post_Lata::ecrire_entete\n" << " format not supported" << finl;
955 exit();
956 }
957 switch(sizeof(_LATA_INT_TYPE_))
958 {
959 case 4:
960 sfichier << "INT32,";
961 break;
962 case 8:
963 sfichier << "INT64,";
964 break;
965 default:
966 Cerr << "Error in Format_Post_Lata::ecrire_entete\n" << " sizeof(int) not supported" << finl;
967 exit();
968 }
969 sfichier << "F_INDEXING,C_ORDERING,F_MARKERS_SINGLE,REAL32" << finl;
970 }
971 fichier.syncfile();
972
973 }
974
975 return 1;
976}
977
978int Format_Post_Lata::ecrire_temps_lata(const double temps, double& temps_format, const Nom& base_name, Status& stat, const Options_Para& option)
979{
980 assert(stat != RESET);
981 // On ecrit le temps que si ce n'est pas le meme...
982 if (stat != WRITING_TIME || temps_format != temps)
983 {
984 temps_format = temps;
985 // Ouverture du fichier .lata en mode append
987 if (fichier.is_master())
988 fichier.get_SFichier() << "TEMPS " << temps << finl;
989 fichier.syncfile();
990 stat = WRITING_TIME;
991 }
992 return 1;
993}
994
995int Format_Post_Lata::finir(const int est_le_dernier_post)
996{
997 if (est_le_dernier_post)
998 {
1000 SFichier& sfichier = fichier.get_SFichier();
1001 if (fichier.is_master()) sfichier << "FIN" << finl;
1002 fichier.syncfile();
1003 }
1004 return 1;
1005}
Fichier en lecture Cette classe est a la classe C++ ifstream ce que la classe Entree est a la.
Definition EFichier.h:29
Class to use MPI-IO to write in a single file.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
: Specialisation du Fichier_Lata pour le fichier maitre: toujours en ASCII.
virtual int is_master() const
Si le fichier est de type partage, renvoie 1 si me() est egal au master du groupe et 0 sinon,...
virtual SFichier & get_SFichier()
virtual const Nom & get_filename() const
Renvoie le nom du fichier avec le path.
virtual void syncfile()
Si le fichier est de type partage, appelle la methode syncfile(), sinon ne fait rien.
: Classe de postraitement des champs euleriens au format lata
void reset() override
Remet l'objet dans l'etat obtenu par le constructeur par defaut.
int ecrire_entete(const double temps_courant, const int reprise, const int est_le_premier_post) override
Ouvre le fichier maitre en mode ERASE et ecrit l'entete du fichier lata (sur le processeur maitre seu...
static const char * remove_path(const char *filename)
Renvoie le nom d'un fichier sans le path : on enleve les caracteres avant le dernier /.
bool un_seul_fichier_lata_
int ecrire_item_int(const Nom &id_item, const Nom &id_du_domaine, const Nom &id_domaine, const Nom &localisation, const Nom &reference, const IntVect &data, const int reference_size) override
Ecriture d'un tableau d'entiers dans le fichier de postraitement.
virtual int initialize_lata(const Nom &file_basename, const Format format=ASCII, const Options_Para options_para=SINGLE_FILE)
Initialisation de la classe, ouverture du fichier et ecriture de l'entete.
int modify_file_basename(const Nom file_basename, bool for_restart, const double tinit) override
Modifying name of the post file, plus some clever management of previously saved data in case of rest...
double temps_courant_
Options_Para options_para_
int preparer_post(const Nom &id_du_domaine, const int est_le_premier_post, const int reprise, const double t_init) override
static trustIdType write_doubletab(Fichier_Lata &fichier, const DoubleTab &tab, int &nb_colonnes, const Options_Para &option)
fichier est un fichier lata de donnees (pas le fichier maitre) on y ecrit le tableau tab tel quel (en...
long int offset_som_
int ecrire_item_tid(const Nom &id_item, const Nom &id_du_domaine, const Nom &id_domaine, const Nom &localisation, const Nom &reference, const TIDVect &data, const int reference_size)
long int offset_elem_
Format format_
virtual int finir_sans_reprise(const Nom file_basename)
double tinit_
static int ecrire_entete_lata(const Nom &base_name, const Options_Para &option, const Format &format, const int est_le_premier_post)
Format
@ BINAIRE
@ ASCII
virtual int reconstruct(const Nom file_basename, const Nom, const double tinit)
Nom lata_basename_
Options_Para
@ SINGLE_FILE_MPIIO
@ SINGLE_FILE
@ MULTIPLE_FILES
int ecrire_domaine(const Domaine &domaine, const int est_le_premier_post) override
voir Format_Post_base::ecrire_domaine On accepte l'ecriture d'un domaine dans un pas de temps,...
Format_Post_Lata()
Constructeur par defaut: format_ ASCII et options_para_ = SINGLE_FILE.
Status
@ WRITING_TIME
@ RESET
@ INITIALIZED
int completer_post(const Domaine &dom, const int axi, const Nature_du_champ &nature, const int nb_compo, const Noms &noms_compo, const Motcle &loc_post, const Nom &le_nom_champ_post) override
bool restart_already_moved_
void set_param(Param &param) const override
int ecrire_temps(const double temps) override
commence l'ecriture d'un nouveau pas de temps En l'occurence pour le format LATA:
int ecrire_champ(const Domaine &domaine, const Noms &unite_, const Noms &noms_compo, int ncomp, double temps_, const Nom &id_du_champ, const Nom &id_du_domaine, const Nom &localisation, const Nom &nature, const DoubleTab &data) override
voir Format_Post_base::ecrire_champ
static trustIdType write_inttab(Fichier_Lata &fichier, bool decal_fort, trustIdType decalage_partiel, const IntTab &tab, int &nb_colonnes, const Options_Para &option)
Ecriture d'un tableau d'entiers dans le fichier fourni.
Status status
void ecrire_domaine_low_level(const Nom &id_dom, const DoubleTab &sommets, const IntTab &elements, const Motcle &type_elem)
Low level routine to write a mesh into a LATA file.
int initialize_by_default(const Nom &file_basename) override
Initialisation de la classe avec des parametres par defaut (format ASCII, SINGLE_FILE).
int finir(const int est_le_dernier_post) override
int initialize(const Nom &file_basename, const int format, const Nom &option_para) override
static int ecrire_temps_lata(const double temps, double &temps_format, const Nom &base_name, Status &stat, const Options_Para &option)
static const char * extension_lata()
Renvoie l'extension conventionnelle des fichiers lata : ".lata".
void resetTime(double t, const std::string dirname) override
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
Classe de base des formats de postraitements pour les champs (lata, med, cgns, lml,...
OBS_PTR(Domaine_dis_base) domaine_dis_
Reference to the discretized domain - used for face fields.
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
virtual int debute_par(const char *const n) const
Definition Nom.cpp:319
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
int contient_(const char *const ch) const
Definition Noms.cpp:60
friend class Entree
Definition Objet_U.h:76
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
static int axi
Definition Objet_U.h:101
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
static trustIdType mppartial_sum(trustIdType i)
Calul de la somme partielle de i sur les processeurs 0 a me()-1 (renvoie 0 sur le processeur 0).
Definition Process.cpp:396
static double mp_max(double)
Definition Process.cpp:376
static bool is_parallel()
Definition Process.cpp:110
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
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
Cette classe est a la classe C++ ofstream ce que la classe Sortie est a la classe C++ ostream Elle re...
Definition SFichier.h:27
void precision(int pre) override
void setf(IOS_FORMAT code) override
Classe de base des flux de sortie.
Definition Sortie.h:52
virtual int put(const unsigned *ob, std::streamsize n, std::streamsize nb_colonnes=1)
Definition Sortie.cpp:101
_TYPE_ * addr()
: Tableau a n entrees pour n<= 4.
Definition TRUSTTab.h:31
int nb_dim() const
Definition TRUSTTab.h:199
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133