TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Champ_Fonc_reprise_IJK.cpp
1/****************************************************************************
2* Copyright (c) 2015 - 2016, 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 <Champ_Fonc_reprise_IJK.h>
17#include <Probleme_base.h>
18#include <EcritureLectureSpecial.h>
19#include <Champ_Generique_base.h>
20#include <Entree_complete.h>
21#include <LecFicDistribueBin.h>
22#include <EFichierBin.h>
23#include <Domaine_VF.h>
24#include <MD_Vector.h>
25#include <MD_Vector_std.h>
26#include <MD_Vector_tools.h>
27#include <Octree_Double.h>
28#include <Perf_counters.h>
29#include <SFichier.h>
30
31extern void convert_to(const char *s, double& ob);
32Implemente_instanciable(Champ_Fonc_reprise_IJK,"Champ_Fonc_reprise_IJK",Champ_Fonc_base);
33
35{
36 return s << que_suis_je() << " " << le_nom();
37}
38
40{
41 Cerr<<"Usage : Champ_Fonc_reprise_IJK fichier.xyz nom_pb nom_inco"<<finl;
42 Nom nom_fic,nom_pb;
43 Nom nom_champ_inc;
44
45 // Lecture
46
47 s>>nom_fic;
48 s>>nom_pb>>nom_champ_inc;
49
50 // On recupere le pb, puis ensuite on cherche le champ; on recupere le domaine_dis
51 const Probleme_base& pb =ref_cast(Probleme_base,Interprete::objet(nom_pb));
52 OBS_PTR(Champ_base) ref_ch;
53
54 ref_ch = pb.get_champ(Motcle(nom_champ_inc));
55 if (sub_type(Champ_Inc_base,ref_ch.valeur()) && nom_champ_inc == Nom("vitesse"))
56 Cerr << nom_champ_inc << " is an unknown of problem " << nom_pb << " and is 'vitesse'!" << finl;
57 else
58 {
59 Cerr << nom_champ_inc << " is not 'vitesse' (this is the only unknown supported for now)!! " << nom_pb << finl;
61 }
62
63 // Ouverture du fichier
64 statistics().create_custom_counter("Temporary counter",2,"IJK");
65 statistics().begin_count("Temporary counter",statistics().get_last_opened_counter_level()+1);
66 EFichier fic_rep;
67 fic_rep.set_bin(1);
68 fic_rep.ouvrir(nom_fic);
69 if(fic_rep.fail())
70 {
71 Cerr<<"Error while opening the file of resumption : " <<nom_fic<<finl;
73 }
74
75 EFichier& fich = fic_rep;
76
77 if (fich.eof())
78 {
79 Cerr << "Error in Champ_Fonc_reprise_IJK::reprendre" << finl;
80 Cerr << "The resumption file does not exist" << finl;
81 Cerr << "or could not be opened correctly." << finl;
83 }
84
85// Nom ident_lu;
86// fich >> ident_lu;
87// if (ident_lu != "xyz_ijk:")
88// {
89// Cerr << "Wrong file format. Expected XYZ_IJK."<<finl;
90// Process::exit();
91// }
92
94 // on cree un champ comme le ch_ref;
95 vrai_champ_.typer(ref_ch->que_suis_je());
96 const Champ_Inc_base& ch_inc=ref_cast(Champ_Inc_base,ref_ch.valeur());
97 Champ_Inc_base& v_champ=vrai_champ_.valeur();
98 le_champ().associer_domaine_dis_base(pb.domaine_dis());
99
101 v_champ.nommer(ch_inc.le_nom());
102 v_champ.fixer_nb_comp(ch_inc.nb_comp());
104
105 nb_compo_ = ch_inc.nb_comp();
106
107 // Reading file data:
108 reprendre_IJK(fich, le_champ());
109
110 Cerr << "End of resuming the file " << nom_fic << " after " << statistics().get_time_since_last_open("Temporary counter") << " s" << finl;
111 statistics().end_count("Temporary counter");
112
113 return s ;
114}
115
116/*! @brief Reciproque de la methode ecrit(...), lit uniquement les items sequentiels (donc pas les items communs recus d'un autre processeur)
117 *
118 * On verifie a la fin qu'on a bien lu exactement le nombre d'items attendus, s'il en manque
119 * c'est que le epsilon n'est pas bon (ou qu'on a change le maillage...)
120 *
121 * Valeur de retour: nombre total d'items sequentiels lus (sur tous les procs)
122 */
123static trustIdType lire_special(Entree& fich, const DoubleTab& coords, DoubleTab& val, const double epsilon)
124{
125 const int dim = coords.dimension(1);
126 const int nb_dim = val.nb_dim();
127 const int nb_comp = (nb_dim == 1) ? 1 : val.dimension(1);
128
129// SFichier toto;
130// toto.set_bin(0);
131// toto.ouvrir("/tmp/toto.dbg");
132// coords.ecrit(toto);
133
134 const MD_Vector& md_vect = val.get_md_vector();
135 // Dans un premier temps, 1 si l'item est a lire, 0 s'il est lu par un autre processeur.
136 // Une fois que l'item est lu, on met le flag a 2.
137 ArrOfInt items_to_read;
138 const int n_to_read = md_vect->get_sequential_items_flags(items_to_read);
139 Octree_Double octree;
140 // Build an octree with "thick" nodes (epsilon size)
141 octree.build_nodes(coords, 0 /* do not include virtual elements */, epsilon);
142 const ArrOfInt& floor_elements = octree.floor_elements();
143
144 // Le fichier contient ce nombre de lignes pour cette partie du tableau (nombre total d'items sequentiels)
145 const trustIdType ntot = Process::mp_sum(n_to_read);
146
147 // On lit dans le fichier par blocs de buflines_max parce qu'il y a
148 // un broadcast reseau a chaque comm:
149 const int buflines_max = 2048; // pas trop, histoire d'avoir plusieurs blocs dans les cas tests
150 DoubleTab buffer(buflines_max, dim + nb_comp);
151 int bufptr = buflines_max;
152 ArrOfInt items;
153
154 double max_epsilon_needed = epsilon;
155 // Combien de fois on a trouve plusieurs candidats a moins de epsilon ?
156 int error_too_many_matches = 0;
157 // Combien de fois on est tombe plusieurs fois sur le meme sommet a lire ?
158 int error_duplicate_read = 0;
159 // Combien d'items a-t-on lu ?
160 int count_items_read = 0;
161
162 // Boucle sur les items sequentiels du fichier:
163 trustIdType pourcent=0;
164 for (trustIdType i = 0; i < ntot; i++)
165 {
166 trustIdType tmp=(i*10)/(ntot-1);
167 if (tmp>pourcent || i==0)
168 {
169 pourcent=tmp;
170 Cerr<<"\r"<<pourcent*10<<"% of data has been found."<<flush;
171 }
172 if (bufptr == buflines_max)
173 {
174 bufptr = 0;
175 trustIdType n = std::min<trustIdType>(buflines_max, ntot - i) * (dim + nb_comp);
176 assert(n <= buffer.size_array());
177 fich.get(buffer.addr(), n);
178 }
179 const double x = buffer(bufptr, 0);
180 const double y = buffer(bufptr, 1);
181 const double z = (dim == 3) ? buffer(bufptr, 2) : 0.;
182 double eps = 1.0e-04;
183 if ((std::fabs(x - (-0.2 + 0.00625*0.5)) < eps) && (std::fabs(y - (-0.2 + 0.00625*0.5)) < eps) && (std::fabs(z) < eps))
184 Cerr << "tiens tiens ..." << finl;
185 // Recherche des items correspondant potentiellement au point (x,y,z)
186 int index = -1;
187 int nb_items_proches = octree.search_elements(x, y, z, index);
188 if (nb_items_proches == 0)
189 {
190 Cerr << "pas ditems proches" << finl;
191 }
192
193 if (nb_items_proches > 0)
194 {
195 items.resize_array(nb_items_proches, RESIZE_OPTIONS::NOCOPY_NOINIT);
196 // Voir doc de Octree_Double::search_elements: on copie les indices des items proches dans items:
197 for (int j = 0; j < nb_items_proches; j++)
198 items[j] = floor_elements[index++];
199 // On reduit la liste pour avoir uniquement les items a moins de epsilon
200 const int item_le_plus_proche = octree.search_nodes_close_to(x, y, z, coords, items, epsilon);
201 nb_items_proches = items.size_array();
202 if (nb_items_proches == 1)
203 {
204 const int flag = items_to_read[item_le_plus_proche];
205 if (flag == 1)
206 {
207 // Ok, il faut lire cette valeur
208 items_to_read[item_le_plus_proche] = 2;
209 count_items_read++;
210 if (nb_dim == 1)
211 {
212 val(item_le_plus_proche) = buffer(bufptr, dim);
213 }
214 else
215 {
216 for (int j = 0; j < nb_comp; j++)
217 val(item_le_plus_proche, j) = buffer(bufptr, dim + j);
218 }
219 }
220 else if (flag == 0)
221 {
222 // Cet item n'est pas a moi, ne pas le lire
223 }
224 else
225 {
226 // Erreur, on a deja lu cet item !!! epsilon est trop grand (ou erreur a la sauvegarde ???)
227 error_duplicate_read++;
228 }
229 }
230 else if (nb_items_proches == 0)
231 {
232 // ok, le sommet est sur un autre processeur (ou epsilon trop petit ??)
233 Cerr << "pas ditems proches 2" << finl;
234 }
235 else
236 {
237 // Erreur: epsilon est trop grand, on a plusieurs candidats a moins de epsilon
238 // Calcul de la distance avec le deuxieme plus proche pour afficher un message d'erreur a la fin:
239 for (int ii = 0; ii < nb_items_proches; ii++)
240 {
241 const int i_coord = items[ii];
242 if (i_coord == item_le_plus_proche)
243 continue; // celui-la est sans doute le bon, il faut un epsilon superieur a cette valeur la...
244 double xx = 0;
245 for (int j = 0; j < dim; j++)
246 {
247 double yy = coords(i_coord, j) - buffer(bufptr, j);
248 xx += yy * yy;
249 }
250 // On propose de mettre un epsilon au maximum egal a 1/10 de la distance avec le deuxieme point le plus proche:
251 xx = sqrt(xx) * 0.1;
252 if (max_epsilon_needed > xx)
253 max_epsilon_needed = xx;
254 }
255 error_too_many_matches++;
256 }
257 }
258 bufptr++;
259 }
260 Cerr << finl;
261 // Erreurs ?
262 bool err = (count_items_read != n_to_read) || (error_too_many_matches > 0) || (error_duplicate_read > 0);
263 err = Process::mp_or(err);
264 if (err)
265 {
266 error_too_many_matches = static_cast<int>(Process::mp_sum(error_too_many_matches));
267 error_duplicate_read = static_cast<int>(Process::mp_sum(error_duplicate_read));
268 max_epsilon_needed = static_cast<int>(Process::mp_min(max_epsilon_needed));
270 {
271 if (error_too_many_matches)
272 {
273 Cerr << "Error in EcritureLectureSpecial: error_too_many_matches = " << error_too_many_matches
274 << ", epsilon is too large. Suggested value: " << max_epsilon_needed << finl;
275 if (max_epsilon_needed==0)
276 {
277 Cerr << "It could be because your mesh has two boundaries which match exactly." << finl;
278 Cerr << "It is possible to do calculation with this property but xyz restart process" << finl;
279 Cerr << "is impossible because it can't detect the differences between faces of the two boundaries..." << finl;
280 Cerr << "Try to do a classic restart with .sauv files." << finl;
281 }
282 }
283 else if (error_duplicate_read)
284 {
285 Cerr << "Error in EcritureLectureSpecial: error_duplicate_read = " << error_duplicate_read
286 << ", probably epsilon too large. " << finl;
287 }
288 else
289 {
290 Cerr << "Error in EcritureLectureSpecial: Some items were not found: epsilon too small (or changed the mesh ?)" << finl;
291 }
292 }
295 }
296 return ntot;
297}
298
299
301{
302 int nb_val_nodales_old = nb_valeurs_nodales();
303
304 const Domaine_VF& zvf=ref_cast(Domaine_VF,ch.domaine_dis_base());
305 DoubleTab& val = ch.valeurs();
306
307 /* [ABN] ce qui suit est une version allegee de
308 static int lecture_special_part2(const Domaine_VF& zvf, Entree& fich, DoubleTab& val)
309 en depilant tous les appels sous-jacents.
310 */
311
312 const MD_Vector& md = val.get_md_vector();
313 trustIdType ntot = 0;
314
315 if (!md)
316 {
317 Cerr << "Champ_Fonc_reprise_IJK::reprendre_IJK: error, cannot read intno an array with no metadata" << finl;
319 }
320 const trustIdType nb_items_seq = md->nb_items_seq_tot();
321 if (nb_items_seq == 0)
322 return;
323
324 if (sub_type(MD_Vector_base, md.valeur()))
325 {
326
327 if (md != zvf.face_sommets().get_md_vector())
328 {
329 Cerr << "Champ_Fonc_reprise_IJK::reprendre_IJK: Problem! Expected face descriptor."<< finl;
331 }
332 const DoubleTab& coords = zvf.xv(); // Descripteur des face
333 const double epsilon = zvf.domaine().epsilon();
334 ntot += lire_special(fich, coords, val, epsilon);
335 }
336 else
337 {
338 Cerr << "Champ_Fonc_reprise_IJK::reprendre_IJK: Problem in the resumption. Not a MD_Vector_base." << finl;
340 }
341
342 if (ntot != nb_items_seq)
343 {
344 Cerr << "Champ_Fonc_reprise_IJK::reprendre_IJK: Internal error" << finl;
346 }
347
348
349 if (nb_val_nodales_old != nb_valeurs_nodales())
350 {
351 Cerr << "Champ_Fonc_reprise_IJK::reprendre_IJK: Problem in the resumption "<< finl;
352 Cerr << "The field wich is read, does not have same number of nodal values" << finl;
353 Cerr << "that the field created by the discretization " << finl;
355 }
356 Cerr << "Resume of the field " << nom_ << " performed." << finl;
357}
358
363
int nb_valeurs_nodales() const override
Renvoie le nombre de degre de liberte par composante: le nombre de noeuds.
classe Champ_Fonc_base Classe de base des champs qui sont fonction d'une grandeur calculee
void mettre_a_jour(double temps) override
Mise a jour en temps du champ.
classe Champ_Fonc_reprise_IJK Cette classe permet de relire un champ de vitesse SEULEMENT sauvegarde ...
void mettre_a_jour(double) override
Mise a jour en temps du champ.
void reprendre_IJK(Entree &fich, Champ_base &chp)
void associer_domaine_dis_base(const Domaine_dis_base &) override
int fixer_nb_valeurs_nodales(int) override
virtual int fixer_nb_valeurs_temporelles(int)
Fixe le nombre de valeurs temporelles a conserver.
int nb_valeurs_nodales() const override
Returns the number of "real" geometric positions of the degrees of freedom, or -1 if not applicable (...
virtual DoubleTab & valeurs()=0
Champ_base()
Constructeur par defaut d'un Champ_base.
virtual const Domaine_dis_base & domaine_dis_base() const
class Domaine_VF
Definition Domaine_VF.h:44
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
int face_sommets(int i, int j) const
renvoie le numero du ieme sommet de la face num_face.
Definition Domaine_VF.h:583
double epsilon() const
const Domaine & domaine() const
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::in)
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual int get(int *ob, std::streamsize n)
Definition Entree.cpp:222
void set_bin(bool bin) override
Change le mode d'ecriture du fichier.
Definition Entree.cpp:291
virtual void fixer_nb_comp(int i)
Fixe le nombre de composantes du champ.
const Nom & le_nom() const override
Renvoie le nom du champ.
void nommer(const Nom &) override
Donne un nom au champ.
virtual int nb_comp() const
Definition Field_base.h:56
int nb_compo_
Definition Field_base.h:95
static Objet_U & objet(const Nom &)
Voir Interprete_bloc::objet_global() BM: la classe Interprete n'est pas le meilleur endroit pour cett...
Base class for distributed vectors parallel descriptors.
int get_sequential_items_flags(ArrOfBit &flags, int line_size=1) const
virtual trustIdType nb_items_seq_tot() const
: Cette classe est un OWN_PTR mais l'objet pointe est partage entre plusieurs
Definition MD_Vector.h:48
const MD_Vector_base & valeur() const
Definition MD_Vector.h:77
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
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
const ArrOfInt_t & floor_elements() const
static int_t search_nodes_close_to(double x, double y, double z, const DoubleTab_t &coords, ArrOfInt_t &node_list, double epsilon)
Methode hors classe Cherche parmi les sommets de la liste node_list ceux qui sont a une.
void build_nodes(const DoubleTab_t &coords, const bool include_virtual, const double epsilon=0.)
construit un octree contenant les points de coordonnees coords.
int_t search_elements(double x, double y, double z, int_t &index) const
cherche les elements ou les points contenus dans l'octree_floor qui contient le point (x,...
void begin_count(const STD_COUNTERS &std_cnt, int counter_lvl=-100000)
double get_time_since_last_open(const STD_COUNTERS &name)
Give as a double the time (in second) elapsed in the operation tracked by the standard counter call n...
void end_count(const std::string &custom_count_name, int count_increment=1, long int quantity_increment=0)
End the count of a counter and update the counter values.
void create_custom_counter(std::string counter_description, int counter_level, std::string counter_family="None", bool is_comm=false, bool is_gpu=false)
Create a new counter and add it to the map of custom counters.
const Champ_base & get_champ(const Motcle &nom) const override
const Domaine_dis_base & domaine_dis() const
Renvoie le domaine discretise associe au probleme.
static double mp_min(double)
Definition Process.cpp:386
static bool mp_or(bool)
Definition Process.cpp:418
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
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
int nb_dim() const
Definition TRUSTTab.h:199
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
virtual const MD_Vector & get_md_vector() const
Definition TRUSTVect.h:123