TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Champ_Fonc_MED.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 <Champ_Fonc_MED.h>
17#include <LireMED.h>
18#include <Char_ptr.h>
19#include <EFichier.h>
20#include <EChaine.h>
21#include <medcoupling++.h>
22#include <TRUST_2_MED.h>
23#include <Comm_Group_MPI.h>
24#ifdef MEDCOUPLING_
25#include <MEDLoader.hxx>
26#include <MEDCouplingField.hxx>
27#include <MEDCouplingFieldDouble.hxx>
28#ifdef MPI_
29#include <ParaMEDFileMesh.hxx>
30#endif
31#pragma GCC diagnostic ignored "-Wreorder"
32#include <MEDFileField.hxx>
33#include <communications.h>
34
35using MEDCoupling::MEDCouplingField;
36using MEDCoupling::MEDCouplingFieldDouble;
37using MEDCoupling::MCAuto;
38using MEDCoupling::DataArrayIdType;
39using MEDCoupling::GetTimeAttachedOnFieldIteration;
40using MEDCoupling::GetAllFieldNamesOnMesh;
41using MEDCoupling::MEDFileFieldMultiTS;
42using MEDCoupling::MEDFileField1TS;
43using MEDCoupling::MEDFileMesh;
44#endif
45
46// XD champ_fonc_med field_base champ_fonc_med BRACE Field to read a data field in a MED-format file .med at a specified
47// XD_CONT time. It is very useful, for example, to resume a calculation with a new or refined geometry. The field
48// XD_CONT post-processed on the new geometry at med format is used as initial condition for the resume.
49Implemente_instanciable(Champ_Fonc_MED,"Champ_Fonc_MED",Champ_Fonc_base);
50
52{
53 return s << que_suis_je() << " " << le_nom();
54}
55
57{
58 param.ajouter_flag("use_existing_domain", &use_existing_domain_); // XD_ADD_P flag
59 // XD_CONT whether to optimize the field loading by indicating that the field is supported by the same mesh that was
60 // XD_CONT initially loaded as the domain
61 param.ajouter_flag("last_time", &last_time_only_); // XD_ADD_P flag
62 // XD_CONT to use the last time of the MED file instead of the specified time. Mutually exclusive with 'time'
63 // XD_CONT parameter.
64 param.ajouter("decoup", &nom_decoup_, Param::OPTIONAL); // XD_ADD_P chaine
65 // XD_CONT specify a partition file.
66 param.ajouter("mesh", &nom_maillage_, Param::OPTIONAL); // XD_ADD_P chaine
67 // XD_CONT Name of the mesh supporting the field. This is the name of the mesh in the MED file, and if this mesh was
68 // XD_CONT also used to create the TRUST domain, loading can be optimized with option 'use_existing_domain'.
69 param.ajouter("domain", &nom_dom_, Param::REQUIRED); // XD_ADD_P chaine
70 // XD_CONT Name of the domain supporting the field. This is the name of the mesh in the MED file, and if this mesh was
71 // XD_CONT also used to create the TRUST domain, loading can be optimized with option 'use_existing_domain'.
72 param.ajouter("file", &nom_fichier_med_, Param::REQUIRED); // XD_ADD_P chaine
73 // XD_CONT Name of the .med file.
74 param.ajouter("field", &nom_champ_, Param::REQUIRED); // XD_ADD_P chaine
75 // XD_CONT Name of field to load.
76 param.ajouter("loc", &loc_, Param::OPTIONAL); // XD_ADD_P chaine(into=["som","elem"])
77 // XD_CONT To indicate where the field is localised. Default to 'elem'.
78 param.ajouter("time", &temps_, Param::OPTIONAL); // XD_ADD_P double
79 // XD_CONT Timestep to load from the MED file. Mutually exclusive with 'last_time' flag.
80}
81
83{
84#ifdef MEDCOUPLING_
85 Nom chaine_lue;
86 bool nom_decoup_lu = false;
87 nom_decoup_ = "";
88
89 is>>chaine_lue;
90 if (chaine_lue == "{") // New syntax !!
91 {
92 Nom s = "{ ";
93 int cnt = 1;
94 while (cnt)
95 {
96 Nom motlu;
97 is >> motlu;
98 if (motlu == "{") cnt++;
99 if (motlu == "}") cnt --;
100 s += Nom(" ") + motlu;
101 }
102 Param param(que_suis_je());
103 set_param(param);
104
105 EChaine is2(s);
106 loc_ = "";
107 constexpr double MIN_INF = -1.0e+300;
108 temps_ = MIN_INF;
109 param.lire_avec_accolades(is2);
110 // Localisation is elem by default
111 if (loc_ == "") loc_ = "elem";
112 if (nom_decoup_ != "") nom_decoup_lu = true;
113 // At least one time needed!
114 if (!last_time_only_ && temps_ == MIN_INF) // no time was provided
115 {
116 Cerr << "ERROR: reading 'Champ_fonc_MED': no time was provided! Either 'last_time' or 'time' parameter must be specified!" << finl;
117 Process::exit(-1);
118 }
119 if (last_time_only_ && temps_ != MIN_INF) // too many time options
120 {
121 Cerr << "ERROR: reading 'Champ_fonc_MED': both 'time' and 'last_time' were provided! Choose only one!" << finl;
122 Process::exit(-1);
123 }
124
125 }
126 else // Old syntax?
127 {
128 Cerr << "ERROR: reading 'Champ_fonc_MED': Expected opening brace '{' - are you using the new syntax?" << finl;
129 Cerr << "If you are still using the old syntax (before TRUST v1.9.3), \nyou can use -convert_data option of your application script:" << finl;
130 Cerr << " trust -convert_data " << Objet_U::nom_du_cas() << ".data" << finl;
131 Process::exit(-1);
132 }
133
134 //
135 // Finished interpreting ... processing now:
136 //
137 if (!nom_decoup_lu)
138 nom_decoup_ = Nom("decoup/") + nom_dom_ + ".txt"; //valeur par defaut de nom_decoup
139
140 traite_nom_fichier_med(nom_fichier_med_);
141 // La lecture de fichiers multiples .med fonctionne: voir cas test Champ_fonc_MED_Parallele
142 // Un test est fait plus loin pour bien verifier que les partitionnement se recouvrent pour cela
143 int multiple_med = 0;
144 Nom tmp(nom_fichier_med_);
145 tmp.prefix("0001.med");
147 {
148 multiple_med = 1;
149 /*
150 // Ajout d'un test bloquant pour empecher la lecture de fichiers 000n.med
151 Cerr << "Error, Champ_Fonc_MED can't read, for the moment, partitioned MED files." << finl;
152 Cerr << "Try to build a single MED file by:" << finl;
153 Cerr << "A) Using LATA format for the previous calculation." << finl;
154 Cerr << "B) Convert the LATA files into a single MED file with Lata_to_MED keyword." << finl;
155 Cerr << "C) Use this single MED file with Champ_Fonc_MED keyword." << finl;
156 exit(); */
157 }
158 multiple_med = mp_max(multiple_med);
160
161 int field_size;
162 bool domain_exist=( interprete().objet_existant(nom_dom_) && sub_type(Domaine, interprete().objet(nom_dom_)) );
164 {
165 if (!domain_exist)
166 {
167 Cerr << "The domain " << nom_dom_ << " does not exist !!!! In Champ_Fonc_MED " << nom_fichier_med_ << " " << nom_dom_
168 << " " << nom_champ_ << " " << loc_ << " " << temps_ << finl;
169 exit();
170 }
171 else
172 {
173 // use_existing_domain utilisable en parallele uniquement si le process 0 gere tout le domaine ou si decoup specifie:
174 const Domaine& le_domaine=ref_cast(Domaine, interprete().objet(nom_dom_));
175 if (Process::is_parallel() && mp_max((int)(le_domaine.nb_som()>0)) != 0 && !nom_decoup_lu)
176 {
177 Cerr << "Warning, you can't use use_existing_domain on a partitionned domain like " << nom_dom_ << finl;
178 Cerr << "It is not parallelized yet... So we use MED mesh, which is not optimal." << finl;
179 Cerr << "Try suppress use_existing_domain option." << finl;
180 //Process::exit();
181 use_existing_domain_ = false;
182 }
183 }
184 }
185 if (domain_exist && use_existing_domain_)
186 {
187 Cerr<<nom_dom_<<" was not read into the med file because it already exists." <<finl;
188
189 const Domaine& le_domaine=ref_cast(Domaine, interprete().objet(nom_dom_));
190
191#ifndef NDEBUG
192 // In debug, check that we really have the same domain.
193 // Only doable in sequential, since in //, dom=full_domain, un_dom=local_domain
194 if (nproc()==1)
195 {
196 Cerr << "Checking whether domain in the file "<<nom_fichier_med_<<" and domain "<<nom_dom_<<" are the same (coords,connectivity) ..."<<finl;
197 LireMED liremed(nom_fichier_med_, nom_maillage_ == "??" ? nom_dom_ : nom_maillage_);
198 dom_med_.nommer(nom_dom_);
199 liremed.associer_domaine(dom_med_);
200 liremed.retrieve_MC_objects();
201 const MEDCouplingUMesh* new_um = liremed.get_mc_mesh();
202 const MEDCouplingUMesh* root_um = le_domaine.get_mc_mesh();
203 try
204 {
205 DataArrayIdType *dnup1=nullptr, *dnup2=nullptr;
206 // Less strict checkGeoEquivalWith (levOfCheck = 12 instead of 2). we use now "nodal" comparison.
207 // Two cells are considered equal if they are based on same nodes and have the same type.
208 // This is the weakest policy, it can be used by users not sensitive to cell orientation.
209 // if levOfCheck set to 2, some F5 and G3 tests fail
210
211 root_um->checkGeoEquivalWith(new_um, /* levOfCheck= */ 12, Objet_U::precision_geom, dnup1, dnup2);
212 //MCAuto<DataArrayIdType> dnu1(dnup1), dnu2(dnup2);
213 if (dnup2) dnup2->decrRef();
214 if (dnup1) dnup1->decrRef();
215 }
216 catch(INTERP_KERNEL::Exception& e)
217 {
218 Cerr << "Comparison of the two domains failed, with the following message from MEDCoupling::checkGeoEquivalWith()" << finl;
219 Cerr << e.what() << finl;
221 }
222 dom_med_=Domaine(); // Reset
223 }
224#endif
225 field_size = creer(nom_fichier_med_,le_domaine,loc_,temps_sauv_);
226 }
227 else
228 {
229 if (domain_exist && !use_existing_domain_)
230 Cerr<<"INFO: You can toggle the flag 'use_existing_domain' in 'Champ_Fonc_MED' to optimize reading since it seems that the domain already exists."<<finl;
231 LireMED liremed(nom_fichier_med_, nom_maillage_ == "??" ? nom_dom_ : nom_maillage_);
232 dom_med_.nommer(nom_dom_);
233 //Nom nom_dom_trio_non_nomme;
234 // Remplit dom:
235 liremed.associer_domaine(dom_med_);
236 liremed.lire_geom(false); // false: do not create sub-dom files
237 if (multiple_med)
238 {
239 // On verifie que l'on a bien des recouvrements identiques (verification imparfaite sur les BoundingBox)
240 DoubleTab BB1 = dom_med_.getBoundingBox();
241 const Domaine& dom_calcul = ref_cast(Domaine, interprete().objet(nom_dom_));
242 DoubleTab BB2 = dom_calcul.getBoundingBox();
243 for (int i=0; i<dimension; i++)
244 for (int j=0; j<2; j++)
245 if (est_different(BB1(i,j), BB2(i,j)))
246 {
247 Cerr << "Error, Champ_Fonc_MED can't read the partitionned MED files." << finl;
248 Cerr << "=> it seems that the MED partition is different than the '" << dom_calcul.le_nom() << "' domain partition." << finl;
250 }
251 Cerr << "Ok MED partition matches the domain partition so reading multiple MED files..." << finl;
252 }
253 // MODIF ELI LAUCOIN (06/03/2012) :
254 // j'ajoute l'attribut temps_sauv_
256 }
257 if (last_time_only_)
258 {
259 temps_=temps_sauv_[temps_sauv_.size_array()-1];
260 Cout << "The resumption time is "<<temps_<<finl;
261 }
262 // FIN MODIF ELI LAUCOIN (06/03/2012)
263 /* si on est en parallele : creation du filtre */
264 if (Process::is_parallel() && field_size < 0)
265 {
266 EFichier fdec;
267 fdec.ouvrir(nom_decoup_);
268 // Cas ou le maillage du fichier .med suit la numerotation du maillage initial (necessite le fichier du decoupage pour retrouver la numerotation)
269 if (fdec.good())
270 {
271 int dec_size=-1;
272 if(loc_ == "elem")
273 {
274 ArrOfInt dec;
275 fdec >> dec;
276 dec_size = dec.size_array();
277 for (int i = 0; i < dec_size; i++)
278 if (dec[i] == Process::me()) filter.push_back(i);
279 }
280 else if(loc_ == "som")
281 {
282 int nbNodes;
283 fdec >> nbNodes;
284 std::vector<std::set<int>> dec(nbNodes);
285 for(int n=0; n<nbNodes; n++)
286 {
287 int node,size;
288 fdec >> node >> size;
289 for(int p=0; p<size; p++)
290 {
291 int proc;
292 fdec >> proc;
293 dec[node].insert(proc);
294 }
295 }
296 dec_size = (int)dec.size();
297 for (int n=0; n < dec_size; n++)
298 for(std::set<int>::iterator it = dec[n].begin(); it!=dec[n].end(); ++it)
299 if (*it == Process::me()) filter.push_back(n);
300 }
301 else
302 {
303 Cerr << "Champ_Fonc_MED on parallel domain : decoup file only handled for field located on nodes or on cells!" << finl;
305 }
306 }
307 else // Cas ou le maillage .med suit la numerotation du maillage decoupe
308 {
309 int nb_item = le_champ().valeurs().dimension(0);
310 trustIdType first_item = mppartial_sum(nb_item);
311 for (int i=0; i<nb_item; i++)
312 filter.push_back(first_item);
313 }
314 Cerr << "Creating a filter to access efficiently values in " << nom_fichier_med_ << finl;
315 if ((int) filter.size() != le_champ().valeurs().dimension(0))
316 {
317 Cerr << "Champ_Fonc_MED on parallel domain : inconsistency between filter and domain (not the same number of entities)!" << finl;
319 }
320 }
321 else if (field_size != le_champ().valeurs().dimension(0))
322 {
323 Cerr << "Champ_Fonc_MED on existing domain : inconsistency between domain file and field (not the same number of entities)!" << finl;
325 }
329#endif
330
331 return is ;
332}
333
335{
336 if (t<0)
337 {
338 // Si t negatif convention (non indique dans la doc Trust) pour specifier un numero de pas de temps:
339 int given_it = -(int) t - 1;
340 lire(-1, given_it);
341 }
342 else
343 lire(t);
344}
345
346#ifdef MED_
347med_geometry_type type_geo_trio_to_type_med(const Nom& type);
348#ifdef MEDCOUPLING_
349INTERP_KERNEL::NormalizedCellType type_geo_trio_to_type_medcoupling(const Nom& type, int& mesh_dimension);
350#endif
351#endif
352
353void Champ_Fonc_MED::lire(double t, int given_it)
354{
355 if (domainebidon_inst.nb_elem()==0) // Cas d'un domaine vide
356 {
357 // Mise a jour:
359 le_champ().Champ_Fonc_base::mettre_a_jour(t);
360 return;
361 }
362#ifdef MED_
363#ifdef MEDCOUPLING_
364 // Read a field
365 std::string meshName = nom_maillage_ == Nom() ? mon_dom->le_nom().getString() : nom_maillage_.getString();
366 std::string fieldName = nom_champ_dans_fichier_med_.getString();
367 std::string fileName = nom_fichier_med_.getString();
368 // Etude des conditions pour chercher ou nom un champ dans le fichier MED:
369 bool search_field = true;
370 nb_dt = temps_sauv_.size_array();
371 if (nb_dt>0)
372 {
373 // nb_dt nombre de pas de temps dans le fichier MED
374 // ndt taille du tableau temps_sauv contenant les pas de temps du champ dans le fichier MED
375 // tmax dernier temps du tableau temps_sauv ?
376 // dt ?
377 // t temps courant pour lequel on veut remplir le champ
378 // last_time_only_ specifie dans le jeu de donnees ou non
379 double tmax = temps_sauv_[nb_dt - 1];
380 double dt = temps_sauv_[nb_dt - 1];
381 if (((nb_dt == 1) && (!est_egal(dt, t))) || ((last_time_only_) && (!est_egal(tmax, t))))
382 {
383 Cout << "We assume that the field " << fieldName << " is stationary." << finl;
384 search_field = false;
385 }
386 }
387 if (search_field)
388 {
389 if (temps_sauv_.size_array()==0)
390 temps_sauv_ = lire_temps_champ(fileName, fieldName);
391 unsigned int nn = temps_sauv_.size_array();
392 if (given_it == -1)
393 {
394 for (given_it = 0; given_it < (int) nn; given_it++)
395 if (est_egal(temps_sauv_[given_it], t)) break;
396 if (given_it == (int)nn)
397 {
398 Cerr << "Error. Time " << t << " not found in the times list of the " << fileName << " file" << finl;
399 for (unsigned int n=0; n<nn; n++)
400 Cerr << temps_sauv_[n] << finl;
402 }
403 }
404 int iteration = time_steps_[given_it].first;
405 int order = time_steps_[given_it].second;
406
407 if(filter.size()) // Partial reading of field (only field values are loaded, not its structure!)
408 {
409#ifdef MPI_
410 MEDFileUtilities::AutoFid fid(MEDCoupling::OpenMEDFileForRead(fileName));
411 int mesh_dimension = -1;
412 std::vector<std::pair<MEDCoupling::TypeOfField,INTERP_KERNEL::NormalizedCellType>> tmp= { { field_type, type_geo_trio_to_type_medcoupling(mon_dom->type_elem()->que_suis_je(), mesh_dimension) } };
413 INTERP_KERNEL::AutoCppPtr<MEDCoupling::MEDFileEntities> entities(MEDCoupling::MEDFileEntities::BuildFrom(&tmp));
414 MCAuto<MEDCoupling::MEDFileAnyTypeField1TS> fieldFile = MEDCoupling::MEDFileAnyTypeField1TS::NewAdv(fid, fieldName, iteration, order, entities, filter);
415 MCAuto<MEDCoupling::MEDFileField1TS> ret(MEDCoupling::DynamicCast<MEDCoupling::MEDFileAnyTypeField1TS, MEDCoupling::MEDFileField1TS>(fieldFile));
416 if (!ret)
417 Process::exit("MED field: wrong type!");
418 MEDCoupling::DataArrayDouble *field_values = ret->getUndergroundDataArray();
419 std::copy(field_values->begin(),field_values->end(),
420 le_champ().valeurs().addr());
421#endif
422 }
423 else
424 {
425 MCAuto<MEDCouplingField> ffield;
426 bool has_field = ffield_!=nullptr;
427 if (!has_field) ffield = lire_champ(fileName, meshName, fieldName, iteration, order);
428 Cerr << " at time " << t << " ... " << finl;
429 MEDCouplingFieldDouble * field = dynamic_cast<MEDCouplingFieldDouble *>((MEDCouplingField *)(has_field?ffield_:ffield));
430 if (field == 0)
431 {
432 Cerr << "ERROR reading MED field! Not a MEDCouplingFieldDouble!!" << finl;
433 Process::exit(-1);
434 }
435 assert(field->getNumberOfTuplesExpected() == le_champ().valeurs().dimension(0));
436 assert((int) field->getNumberOfComponents() ==
437 (le_champ().valeurs().nb_dim() == 1 ? 1 : le_champ().valeurs().dimension(1)));
438 MEDCoupling::DataArrayDouble *field_values = field->getArray();
439 std::copy(field_values->begin(),field_values->end(),
440 le_champ().valeurs().addr());
441 }
442 }
443#endif // MEDCOUPLING_
444 // Mise a jour:
446 le_champ().Champ_Fonc_base::mettre_a_jour(t);
447#else // MED_
448 med_non_installe();
449#endif
450}
451
452int Champ_Fonc_MED::creer(const Nom& nom_fic, const Domaine& un_dom, const Motcle& localisation, ArrOfDouble& temps_sauv)
453{
454#ifdef MED_
455 nom_fichier_med_ = nom_fic;
456 mon_dom=un_dom;
457 const Nom& type_elem=un_dom.type_elem()->que_suis_je();
458 Nom type_champ;
460#ifdef MEDCOUPLING_
461 // MEDCoupling
462 int mesh_dimension = -1;
463 cell_type = type_geo_trio_to_type_medcoupling(type_elem, mesh_dimension);
464 if (localisation != Nom())
465 {
466 if (localisation == "som")
467 {
468 field_type = MEDCoupling::ON_NODES;
469 if ((cell_type == INTERP_KERNEL::NORM_QUAD4) || (cell_type == INTERP_KERNEL::NORM_HEXA8))
470 type_champ = "Champ_Fonc_Q1_MED";
471 else
472 type_champ = "Champ_Fonc_P1_MED";
473 }
474 else if (localisation == "elem")
475 {
476 field_type = MEDCoupling::ON_CELLS;
477 type_champ = "Champ_Fonc_P0_MED";
478 }
479 else
480 {
481 Cerr << localisation << " localization unknown." << finl;
482 exit();
483 }
484 }
485 std::string meshName = nom_maillage_ == "??" ? mon_dom->le_nom().getString() : nom_maillage_.getString();
486 std::string fileName = nom_fic.getString();
487 // Try to guess the field name in the MED file:
488 Noms fieldNamesGuess;
489 fieldNamesGuess.add((Motcle)nom_champ_dans_fichier_med_+"_"+mon_dom->le_nom());
490 if (localisation != Nom())
491 fieldNamesGuess.add((Motcle)nom_champ_dans_fichier_med_+"_"+localisation+"_"+mon_dom->le_nom());
492 fieldNamesGuess.add((Motcle)nom_champ_dans_fichier_med_);
493 if (!fieldNamesGuess.contient_(nom_champ_dans_fichier_med_))
494 fieldNamesGuess.add(nom_champ_dans_fichier_med_);
495 bool ok = false;
496 std::vector<std::string> fieldNames = GetAllFieldNamesOnMesh(fileName, meshName);
497 for (int i=0; i<fieldNamesGuess.size(); i++)
498 {
499 if (std::find(fieldNames.begin(), fieldNames.end(), fieldNamesGuess[i].getString()) != fieldNames.end())
500 {
501 nom_champ_dans_fichier_med_ = fieldNamesGuess[i];
502 ok = true;
503 break;
504 }
505 }
506 if (!ok)
507 {
508 Cerr << "Unable to find into file '" << fileName << "' a field named like :" << finl;
509 Cerr << " " << fieldNamesGuess << finl;
510 Cerr << "supported by mesh '" << meshName << "'" << finl;
511 Cerr << finl;
512 Cerr << "This file contains the field(s) named:" << finl;
513 for (unsigned i=0; i<fieldNames.size(); i++)
514 Cerr << fieldNames[i] << finl;
516 }
517 else
518 Cerr << "Ok, we find into file " << fileName << " a field named " << nom_champ_dans_fichier_med_ << finl;
519
520 std::string fieldName = nom_champ_dans_fichier_med_.getString();
521 int nbcomp,size;
522 lire_donnees_champ(fileName,meshName,fieldName,temps_sauv,size,nbcomp,type_champ);
523#endif // MEDCOUPLING_
524 // Definition:
525 vrai_champ_.typer(type_champ);
526 fixer_nb_comp(nbcomp);
527 le_champ().fixer_nb_comp(nbcomp);
528 domainebidon_inst.associer_domaine(un_dom);
530 le_champ().fixer_nb_valeurs_nodales(type_champ == "Champ_Fonc_P0_MED" ? un_dom.nb_elem() : un_dom.nb_som());
531 //pour forcer la lecture lors du mettre a jour
532 changer_temps(-1e3);
534 return size;
535#else // MED_
536 med_non_installe();
537 return 0;
538#endif
539}
540
541#ifdef MEDCOUPLING_
542// Remplissage des temps du champ fieldName depuis le fichier fileName
543ArrOfDouble Champ_Fonc_MED::lire_temps_champ(const std::string& fileName, const std::string& fieldName)
544{
545 ArrOfDouble temps_sauv;
546 MCAuto<MEDFileFieldMultiTS> ft1(MEDFileFieldMultiTS::New(fileName, fieldName));
547 std::vector<double> tps;
548 time_steps_ = ft1->getTimeSteps(tps);
549 unsigned int nn = (unsigned)tps.size();
550 temps_sauv.resize_array(nn);
551 for (unsigned it = 0; it < nn; it++)
552 temps_sauv[it] = tps[it];
553 return temps_sauv;
554}
555
556// Lecture du dernier champ dans le fichier juste pour decouvrir et stocker:
557// les temps (temps_sauv)
558// sa taille (size)
559// le nombre de composantes (nbcomp)
560// le type (type_champ)
561void Champ_Fonc_MED::lire_donnees_champ(const std::string& fileName, const std::string& meshName, const std::string& fieldName,
562 ArrOfDouble& temps_sauv, int& size, int& nbcomp, Nom& type_champ)
563{
564 temps_sauv = lire_temps_champ(fileName, fieldName);
565 unsigned int nn = temps_sauv.size_array();
566 int last_iter = time_steps_[nn-1].first;
567 int last_order = time_steps_[nn-1].second;
568 // Only one MCAuto below to avoid double deletion:
569 if (is_parallel()) // don't read the whole file in parallel mode
570 {
571 MCAuto<MEDFileField1TS> field = MEDFileField1TS::New(fileName, fieldName, last_iter, last_order);
572 nbcomp = (int) field->getNumberOfComponents();
574 size = -1;
575 else
576 {
577 MCAuto<MEDFileMesh> mesh = MEDFileMesh::New(fileName, meshName, field->getMeshIteration(), field->getMeshOrder());
578 size = field_type == MEDCoupling::ON_NODES ? (int)mesh->getNumberOfNodes() : (int)mesh->getNumberOfCellsAtLevel(0);
579 }
580 }
581 else
582 {
583 ffield_ = lire_champ(fileName, meshName, fieldName, last_iter, last_order);
584 MEDCouplingFieldDouble * field = dynamic_cast<MEDCouplingFieldDouble *>((MEDCouplingField *)ffield_);
585 if (field == 0)
586 {
587 Cerr << "ERROR reading MED field! Not a MEDCouplingFieldDouble!!" << finl;
588 Process::exit(-1);
589 }
590 size = (int)field->getNumberOfTuplesExpected();
591 nbcomp = (int)field->getNumberOfComponents();
592 if (nn>1) ffield_ = nullptr; // Plusieurs champs donc on ne stocke pas le dernier, il faudra relire le bon
593 }
594
595 if (field_type == MEDCoupling::ON_CELLS)
596 type_champ = "Champ_Fonc_P0_MED";
597 else if (field_type == MEDCoupling::ON_NODES)
598 type_champ = cell_type == INTERP_KERNEL::NORM_QUAD4 || cell_type == INTERP_KERNEL::NORM_HEXA8 ? "Champ_Fonc_Q1_MED" : "Champ_Fonc_P1_MED";
599}
600
601/**
602 * @brief Read a MED field from a MED file and return it as a MEDCoupling field.
603 *
604 * This method reads the field @p fieldName stored in the MED file @p fileName on the mesh
605 * named @p meshName for the given time step (@p iteration, @p order).
606 *
607 * @param[in] fileName Path to the MED file to read.
608 * @param[in] meshName Name of the mesh on which the field is defined (as stored in the MED file).
609 * @param[in] fieldName Name of the field to read.
610 * @param[in] iteration Time step / iteration index to read (MEDCoupling convention).
611 * @param[in] order Order within the iteration to read (MEDCoupling convention).
612 *
613 * @return A smart-pointer-like handle (MCAuto) to the read @c MEDCouplingField.
614 *
615 * @note If @p meshName matches domaine().le_nom(), the method calls domaine().build_mc_mesh()
616 * before checking whether the MED mesh is ready, enabling fast mode when possible.
617 */
618MCAuto<MEDCouplingField> Champ_Fonc_MED::lire_champ(const std::string& fileName, const std::string& meshName,
619 const std::string& fieldName, const int iteration, const int order)
620{
621 // Pour lecture plus rapide du field sans lecture du mesh si le maillage MED est deja disponible:
622 if (meshName == domaine().le_nom() && !domaine().is_mc_mesh_ready()) domaine().build_mc_mesh();
623 bool fast = domaine().is_mc_mesh_ready();
624 Cerr << "Reading" << (fast ? " (fast)" : "") << " the field " << fieldName << " on the " << meshName << " mesh into " << fileName << " file" << finl;
625 MCAuto<MEDCouplingField> ffield;
626 if (fast) // Lecture plus rapide du field sans lecture du mesh associe
627 {
628 MCAuto<MEDFileField1TS> file = MEDFileField1TS::New(fileName, fieldName, iteration, order);
629 ffield = file->getFieldOnMeshAtLevel(field_type, domaine().get_mc_mesh(), 0);
630 }
631 else // Lecture ~deux fois plus lente du field avec lecture du mesh associe
632 {
633 ffield = ReadField(field_type, fileName, meshName, 0, fieldName, iteration, order);
634 }
635
636 return ffield;
637}
638#endif // MEDCOUPLING_
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
classe Champ_Fonc_MED Load a field from a MED file for a given time.
const Domaine & domaine() const override
std::vector< trustIdType > filter
virtual void lire(double tps, int given_iteration=-1)
MCAuto< MEDCouplingField > ffield_
ArrOfDouble temps_sauv_
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
int creer(const Nom &, const Domaine &dom, const Motcle &localisation, ArrOfDouble &temps_sauv)
void mettre_a_jour(double) override
Mise a jour en temps du champ.
Domaine_VF_inst domainebidon_inst
virtual const Champ_Fonc_base & le_champ() const
virtual void set_param(Param &param) const override
Nom nom_champ_dans_fichier_med_
classe Champ_Fonc_base Classe de base des champs qui sont fonction d'une grandeur calculee
void associer_domaine_dis_base(const Domaine_dis_base &) override
void mettre_a_jour(double temps) override
Mise a jour en temps du champ.
int fixer_nb_valeurs_nodales(int nb_noeuds) override
Fixe le nombre de degres de liberte par composante.
virtual double changer_temps(const double t)
Fixe le temps auquel se situe le champ.
void corriger_unite_nom_compo()
cette methode va fixer les unites et le nom des compos elle n'est pas const en realite !...
DoubleTab getBoundingBox() const
Definition Domaine.cpp:884
int_t nb_elem() const
Definition Domaine.h:131
void build_mc_mesh(bool virt=false) const
Build the MEDCoupling mesh corresponding to the TRUST mesh.
Definition Domaine.cpp:1327
bool is_mc_mesh_ready() const
Definition Domaine.h:355
int_t nb_som() const
Renvoie le nombre de sommets du domaine.
Definition Domaine.h:121
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
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 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.
static int objet_existant(const Nom &)
Renvoie 1 si l'objet existe, 0 sinon voir Interprete_bloc::objet_global_existant().
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
const std::string & getString() const
Definition Nom.h:92
const Nom & le_nom() const override
Renvoie *this;.
Definition Nom.cpp:563
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
int contient_(const char *const ch) const
Definition Noms.cpp:60
const Interprete & interprete() const
Definition Objet_U.cpp:212
static int dimension
Definition Objet_U.h:99
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 double precision_geom
Definition Objet_U.h:86
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
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
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ OPTIONAL
Definition Param.h:115
@ REQUIRED
Definition Param.h:115
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 int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
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
Classe de base des flux de sortie.
Definition Sortie.h:52
Iterator_ end()
Definition TRUSTArray.h:112
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133