TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Milieu_base.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_Input_P0_Composite.h>
17#include <Discretisation_tools.h>
18#include <Discretisation_base.h>
19#include <Champ_Fonc_Tabule.h>
20#include <Schema_Temps_base.h>
21#include <Champ_Uniforme.h>
22#include <Champ_Fonc_MED.h>
23#include <Probleme_base.h>
24#include <Equation_base.h>
25#include <Milieu_base.h>
26#include <EChaine.h>
27#include <Device.h>
28#include <Param.h>
29
30
31Implemente_base(Milieu_base,"Milieu_base",Objet_U);
32// XD milieu_base objet_u milieu_base INHERITS_BRACE Basic class for medium (physics properties of medium).
33
35{
36 os << "{" << finl;
37 ecrire(os);
38 os << "}" << finl;
39 return os;
40}
41
42/*! @brief Ecrit un objet milieu sur un flot de sortie.
43 *
44 * Ecrit les caracteristiques du milieu:
45 * - masse volumique
46 * - conductivite
47 * - capacite calorifique
48 * - beta_th
49 * - porosite
50 *
51 * @param (Sortie& os) le flot de sortie pour l'ecriture
52 */
54{
55 os << "rho " << ch_rho_<< finl;
56 os << "lambda " << ch_lambda_ << finl;
57 os << "Cp " << ch_Cp_ << finl;
58 os << "beta_th " << ch_beta_th_ << finl;
59 os << "porosite " << ch_porosites_ << finl;
60}
61
62/*! @brief Lecture d'un milieu sur un flot d'entree.
63 *
64 * Format:
65 * {
66 * grandeur_physique type_champ bloc de lecture du champ
67 * }
68 * cf set_param method to know the understood keywords
69 * cf Param class to know possible options reading
70 *
71 * @param (Entree& is) le flot d'entree pour la lecture des parametres du milieu
72 * @return (Entree&) le flot d'entree modifie
73 * @throws accolade ouvrante attendue
74 */
76{
77 Cerr << "Reading of data for a " << que_suis_je() << " medium" << finl;
78 Param param(que_suis_je());
79 set_param(param);
80 param.lire_avec_accolades_depuis(is);
83 if (ch_g_) champs_don_.add(ch_g_.valeur());
84 if (ch_alpha_) champs_don_.add(ch_alpha_.valeur());
85 if (ch_lambda_) champs_don_.add(ch_lambda_.valeur());
86 if (ch_Cp_) champs_don_.add(ch_Cp_.valeur());
87 if (ch_beta_th_) champs_don_.add(ch_beta_th_.valeur());
88 if (ch_porosites_) champs_don_.add(ch_porosites_.valeur());
89 if (ch_diametre_hyd_) champs_don_.add(ch_diametre_hyd_.valeur());
90 return is;
91}
92
93void Milieu_base::set_param(Param& param) const
94{
95 param.ajouter("rho", &ch_rho_); // XD_ADD_P field_base
96 // XD_CONT Density (kg.m-3).
97 param.ajouter("lambda", &ch_lambda_); // XD_ADD_P field_base
98 // XD_CONT Conductivity (W.m-1.K-1).
99 param.ajouter("Cp", &ch_Cp_); // XD_ADD_P field_base
100 // XD_CONT Specific heat (J.kg-1.K-1).
101 param.ajouter("beta_th", &ch_beta_th_);
103}
104
105// methode utile pour F5 ! F5 n'appelle pas Milieu_base::set_param mais Milieu_base::set_additional_params ...
107{
108 param.ajouter("diametre_hyd_champ", &ch_diametre_hyd_); // XD_ADD_P field_base
109 // XD_CONT Hydraulic diameter field (optional).
110 param.ajouter("porosites_champ", &ch_porosites_); // XD_ADD_P field_base
111 // XD_CONT The porosity is given at each element and the porosity at each face, Psi(face), is calculated by the
112 // XD_CONT average of the porosities of the two neighbour elements Psi(elem1), Psi(elem2) :
113 // XD_CONT Psi(face)=2/(1/Psi(elem1)+1/Psi(elem2)). This keyword is optional.
114 param.ajouter("porosites", &porosites_); // XD_ADD_P porosites
115 // XD_CONT Porosities.
116 // pour F5 je mets la gravite ici ...
117 param.ajouter("gravite", &ch_g_); // XD_ADD_P field_base
118 // XD_CONT Gravity field (optional).
119}
120
122{
123 return -1;
124}
125
127{
128 Cerr << "Medium discretization." << finl;
129 const Domaine_dis_base& domaine_dis=pb.domaine_dis();
130
131 // PL: pas le temps de faire plus propre, je fais comme dans Fluide_Incompressible::discretiser pour gerer une conductivite lue dans un fichier MED. Test: Reprise_grossier_fin_VEF
132 // ToDo: reecrire ces deux methodes discretiser
133
134 // E. Saikali : The thermal conductivity and diffusivity fields are considered as multi_scalaire fields, sure if the number of components read
135 // in the data file for lambda > 1, i.e: case of anisotropic diffusion !
136
137 int lambda_nb_comp = 0;
138
139 if(ch_lambda_)
140 {
141 // Returns number of components of lambda field
142 lambda_nb_comp = ch_lambda_->nb_comp( );
143 if (sub_type(Champ_Fonc_MED,ch_lambda_.valeur()))
144 {
145 double temps=ch_lambda_->temps();
146 Cerr<<"Convert Champ_fonc_MED lambda in Champ_Don..."<<finl;
147 OWN_PTR(Champ_Don_base) ch_lambda_prov;
148 dis.discretiser_champ("champ_elem",domaine_dis,"neant","neant",lambda_nb_comp,temps,ch_lambda_prov);
149 ch_lambda_prov->affecter(ch_lambda_.valeur());
150 ch_lambda_.detach();
151 ch_alpha_.detach();
152 dis.discretiser_champ("champ_elem",domaine_dis,"neant","neant",lambda_nb_comp,temps,ch_lambda_);
153 ch_lambda_->valeurs()=ch_lambda_prov->valeurs();
154 }
155
156 if(lambda_nb_comp >1) // Pour anisotrope
157 ch_lambda_->fixer_nature_du_champ(multi_scalaire);
158
159 dis.nommer_completer_champ_physique(domaine_dis,"conductivite","W/m/K",ch_lambda_.valeur(),pb);
160
161 // le vrai nom sera donne plus tard
162 if (sub_type(Champ_Fonc_Tabule,ch_lambda_.valeur()))
163 {
164 double temps=ch_lambda_->temps();
165 dis.discretiser_champ("champ_elem",domaine_dis,"neant","neant",lambda_nb_comp,temps,ch_alpha_);
166 dis.discretiser_champ("champ_elem",domaine_dis,"neant","neant",lambda_nb_comp,temps,ch_alpha_fois_rho_);
167 }
168 champs_compris_.ajoute_champ(ch_lambda_.valeur());
169 }
170 if (!ch_alpha_&&(bool(ch_lambda_)))
171 {
172 double temps=ch_lambda_->temps();
173 // ch_alpha (i.e. diffusivite_thermique) will have same component number as ch_lambda
174 dis.discretiser_champ("champ_elem",domaine_dis,"neant","neant",lambda_nb_comp,temps,ch_alpha_);
175 dis.discretiser_champ("champ_elem",domaine_dis,"neant","neant",lambda_nb_comp,temps,ch_alpha_fois_rho_);
176 }
177 if (ch_alpha_)
178 {
179 dis.nommer_completer_champ_physique(domaine_dis,"diffusivite_thermique","m2/s",ch_alpha_.valeur(),pb);
180 dis.nommer_completer_champ_physique(domaine_dis,"alpha_fois_rho","kg/ms",ch_alpha_fois_rho_.valeur(),pb);
181 champs_compris_.ajoute_champ(ch_alpha_.valeur());
182 champs_compris_.ajoute_champ(ch_alpha_fois_rho_.valeur());
183 }
184 if (ch_beta_th_)
185 {
186 dis.nommer_completer_champ_physique(domaine_dis,"dilatabilite","K-1",ch_beta_th_.valeur(),pb);
187 champs_compris_.ajoute_champ(ch_beta_th_.valeur());
188 }
189 if (ch_Cp_)
190 {
191 dis.nommer_completer_champ_physique(domaine_dis,"capacite_calorifique","J/kg/K",ch_Cp_.valeur(),pb);
192 champs_compris_.ajoute_champ(ch_Cp_.valeur());
193 }
194 if (ch_rho_)
195 {
196 dis.nommer_completer_champ_physique(domaine_dis,"masse_volumique","kg/m^3",ch_rho_,pb);
197 champs_compris_.ajoute_champ(ch_rho_);
198 }
199 if (ch_rho_ && ch_Cp_)
200 {
201 assert (ch_rho_->nb_comp() == ch_Cp_->nb_comp());
203 {
204 const double temps = pb.schema_temps().temps_courant();
205 // E. Saikali
206 // XXX : j'ai remis nb_comp = 1, sinon ca bloque dans Solveur_Masse_base => tab_divide_any_shape
207 // parce qu'on a pas line_size % line_size_vx == 0 (cas nb_comp >1 pour rho et cp
208 // TODO : FIXME : faut coder un cas generique dans DoubleVect::tab_divide_any_shape... bon courage
209 dis.discretiser_champ(dis.is_dg() ? "champ_elem" : "temperature", domaine_dis, "rho_cp_comme_T", "J/m^3/K", 1 /* rho->nb_comp() */, temps, ch_rho_Cp_comme_T_);
210 dis.discretiser_champ( "champ_elem", domaine_dis, "rho_cp_elem", "J/m^3/K", 1 /* rho->nb_comp() */, temps, ch_rho_Cp_elem_);
211 }
212 champs_compris_.ajoute_champ(ch_rho_Cp_comme_T_.valeur());
213 champs_compris_.ajoute_champ(ch_rho_Cp_elem_.valeur());
214 }
215
216 discretiser_porosite(pb,dis);
218}
219
220// methode utile pour F5 ! F5 n'appelle pas Milieu_base::discretiser mais Milieu_base::discretiser_porosite ...
222{
223 if (!zdb_) zdb_ = pb.domaine_dis();
224 const double temps = pb.schema_temps().temps_courant();
225 Nom fld_name = "porosite_volumique", fld_unit = "rien";
226
227 // On construit porosite_face_ avec un descripteur parallele
228 const MD_Vector& md = ref_cast(Domaine_VF, zdb_.valeur()).md_vector_faces();
229 if (!porosite_face_.get_md_vector())
230 {
231 MD_Vector_tools::creer_tableau_distribue(md, porosite_face_, RESIZE_OPTIONS::NOCOPY_NOINIT);
232 assert (ref_cast(Domaine_VF, zdb_.valeur()).nb_faces_tot() == porosite_face_.size_totale());
233 }
234 porosite_face_ = 1.;
235
236 if (ch_porosites_) // Lu par porosites_champ
237 {
238 assert (!is_user_porosites());
239 if (porosites_.is_read())
240 {
241 Cerr << "WHAT ?? You can not define in your medium both porosites_champ & porosites ! Remove one of them !" << finl;
243 }
244
245 is_field_porosites_ = true;
246
247 if (sub_type(Champ_input_P0, ch_porosites_.valeur()))
248 {
249 Cerr << "To control the porosity field from ICoCo, please use Champ_Input_P0_Composite and not Champ_input_P0 !" << finl;
251 }
252 else if (sub_type(Champ_Input_P0_Composite, ch_porosites_.valeur()))
253 {
255 if (!ch_in.is_initialized())
256 {
257 Cerr << "To control the porosity field from ICoCo, please define the initial field in your Champ_Input_P0_Composite !" << finl;
259 }
260
261 ch_porosites_->fixer_unite(fld_unit);
262 ch_porosites_->valeurs() = ch_in.initial_values(); // On initialise !
263 }
264 else if (sub_type(Champ_Fonc_MED,ch_porosites_.valeur()))
265 {
266 Cerr<<"Convert Champ_fonc_MED " << fld_name << " to a OWN_PTR(Champ_Don_base) ..."<<finl;
267 OWN_PTR(Champ_Don_base) tmp_fld;
268 dis.discretiser_champ("champ_elem",zdb_.valeur(),"neant",fld_unit,1,temps,tmp_fld);
269 tmp_fld->affecter(ch_porosites_.valeur()); // interpolate ...
270 ch_porosites_.detach();
271 dis.discretiser_champ("champ_elem",zdb_.valeur(),fld_name,fld_unit,1,temps,ch_porosites_);
272 ch_porosites_->valeurs() = tmp_fld->valeurs();
273 }
274 else if (sub_type(Champ_Uniforme,ch_porosites_.valeur())) // blabla ...
275 {
276 const double val = ch_porosites_->valeurs()(0,0);
277 ch_porosites_.detach();
278 dis.discretiser_champ("champ_elem",zdb_.valeur(),fld_name,fld_unit,1,temps,ch_porosites_);
279 ch_porosites_->valeurs() = val;
280 }
281 else
282 dis.nommer_completer_champ_physique(zdb_.valeur(), fld_name, fld_unit, ch_porosites_.valeur(), pb);
283 }
284 else if (porosites_.is_read()) // via porosites
285 {
286 assert (!is_field_porosites());
287 if (ch_porosites_)
288 {
289 Cerr << "WHAT ?? You can not define in your medium both porosites_champ & porosites ! Remove one of them !" << finl;
291 }
292
293 is_user_porosites_ = true;
294 // On va utiliser porosites_champ maintenant !
295 dis.discretiser_champ("champ_elem", zdb_.valeur(), fld_name, fld_unit, 1, temps, ch_porosites_);
296 Domaine_VF& zvf = ref_cast_non_const(Domaine_VF, zdb_.valeur());
297 ch_porosites_->valeurs() = 1.; // On initialise a 1 ...
298 porosites_.remplir_champ(zvf, ch_porosites_->valeurs(), porosite_face_);
299 }
300 else // Pas defini par l'utilisateur
301 {
302 // On va utiliser porosites_champ maintenant !
303 dis.discretiser_champ("champ_elem", zdb_.valeur(), fld_name, fld_unit, 1, temps, ch_porosites_);
304 ch_porosites_->valeurs() = 1.; // On initialise a 1 ...
305 }
306
307 // On ajoute pour tous les cas
308 if (sub_type(Champ_Input_P0_Composite, ch_porosites_.valeur()))
309 {
310 Champ_input_P0& ch_in = ref_cast(Champ_input_P0,ref_cast(Champ_Input_P0_Composite, ch_porosites_.valeur()).input_field());
311 ch_in.add_synonymous(fld_name); // So that it can be known also ;-)
312 champs_compris_.ajoute_champ(ch_in);
313 }
314 else champs_compris_.ajoute_champ(ch_porosites_.valeur());
315
316 verifie_champ_porosites();
317 if (is_field_porosites()) calculate_face_porosity(); /* sinon c'est deja rempli ... */
319}
320
322{
323 if (!zdb_) zdb_ = pb.domaine_dis();
324 const double temps = pb.schema_temps().temps_courant();
325 Nom fld_name = "diametre_hydraulique", fld_unit = "m";
326
327 // On construit porosite_face_ avec un descripteur parallele
328 const MD_Vector& md = ref_cast(Domaine_VF, zdb_.valeur()).md_vector_faces();
329 if (!diametre_hydraulique_face_.get_md_vector())
330 {
332 assert (ref_cast(Domaine_VF, zdb_.valeur()).nb_faces_tot() == diametre_hydraulique_face_.size_totale());
333 }
334 diametre_hydraulique_face_ = 0.; /* les diametres hydrauliques valent 0 */
335
336 if (ch_diametre_hyd_) // Lu par diametre_hyd_champ
337 {
338 has_hydr_diam_ = true;
339 if (sub_type(Champ_Fonc_MED, ch_diametre_hyd_.valeur()))
340 {
341 Cerr << "Convert Champ_fonc_MED " << fld_name << " to a OWN_PTR(Champ_Don_base) ..." << finl;
342 OWN_PTR(Champ_Don_base) tmp_fld;
343 dis.discretiser_champ("champ_elem", zdb_.valeur(), "neant", fld_unit, 1, temps, tmp_fld);
344 tmp_fld->affecter(ch_diametre_hyd_.valeur()); // interpolate ...
345 ch_diametre_hyd_.detach();
346 dis.discretiser_champ("champ_elem", zdb_.valeur(), fld_name, fld_unit, 1, temps, ch_diametre_hyd_);
347 ch_diametre_hyd_->valeurs() = tmp_fld->valeurs();
348 }
349 else if (sub_type(Champ_Uniforme, ch_diametre_hyd_.valeur())) // blabla ...
350 {
351 const double val = ch_diametre_hyd_->valeurs()(0, 0);
352 ch_diametre_hyd_.detach();
353 dis.discretiser_champ("champ_elem", zdb_.valeur(), fld_name, fld_unit, 1, temps, ch_diametre_hyd_);
354 ch_diametre_hyd_->valeurs() = val;
355 }
356 else
357 dis.nommer_completer_champ_physique(zdb_.valeur(), fld_name, fld_unit, ch_diametre_hyd_.valeur(), pb);
358 }
359 else // Pas defini par l'utilisateur
360 {
361 dis.discretiser_champ("champ_elem", zdb_.valeur(), fld_name, fld_unit, 1, temps, ch_diametre_hyd_);
362 ch_diametre_hyd_->valeurs() = 0.; // On initialise a 0 ...
363 }
364
365 champs_compris_.ajoute_champ(ch_diametre_hyd_.valeur());
366
367 if (has_hydr_diam_) calculate_face_hydr_diam(); /* sinon c'est deja rempli ... */
368}
369
371{
372 assert(has_hydr_diam_);
373 const Domaine_VF& zvf = ref_cast(Domaine_VF, zdb_.valeur());
374 const IntTab& f_e = zvf.face_voisins();
375 const int nb_face_tot = zvf.nb_faces_tot();
376 assert(diametre_hydraulique_face_.size_totale() == nb_face_tot);
377 int e;
378 for (int f = 0; f < nb_face_tot; f++)
379 {
380 double nv = 0.0;
381 for (int i = 0; i < 2; i++)
382 if ((e = f_e(f, i)) > -1)
383 {
385 nv += 1.0;
386 }
388 }
389 // diametre_hydraulique_face_.echange_espace_virtuel(); // Elie : a voir si utile ... je l'utilise pas pour l'instant
390}
391
392void Milieu_base::verifie_champ_porosites()
393{
394 // XXX : Elie Saikali : Avant on testait ca :
395 // assert(mp_min_vect(porosites_champ->valeurs()) >= 0. && mp_max_vect(porosites_champ->valeurs()) <= 1.);
396 // tomber sur un cas F5 avec printf("%.9g\n", 1.0 - mp_max_vect) = -2.88657986e-15
397 // essayer de comparer avec std::numeric_limits<double>::epsilon() mais l'overflow est > !!
398 // du coup je nettoie le champ comme ca pour le moment ... si c'est raisonable !
399 const double min_por = mp_min_vect(ch_porosites_->valeurs()), max_por = mp_max_vect(ch_porosites_->valeurs());
400
401 if (min_por >= 0.0 && max_por <= 1.0) { /* do nothing */ }
402 else if (min_por >= -1.e-12 && max_por <= 1. + 1.e-12 ) nettoie_champ_porosites();
403 else
404 {
405 Cerr << "WHAT ?? Your porosity field contains values < 0 or > 1 !!!! You should do something !" << finl;
407 }
408}
409
410void Milieu_base::nettoie_champ_porosites()
411{
412 Cerr << "************************************************************************" << finl;
413 Cerr << " We detected some element-porosity values which are slighly < 0 or > 1 !" << finl;
414 Cerr << finl;
415 printf("Overflow : 1 - MAX = %.9g\n", 1.0 - mp_max_vect(ch_porosites_->valeurs()));
416 printf("Overflow : MIN - 0 = %.9g\n", mp_min_vect(ch_porosites_->valeurs()) - 0.);
417 Cerr << finl;
418 Cerr << " We will clean the field to prevent overflows and numerical issues ... " << finl;
419 Cerr << "************************************************************************" << finl;
420
421 for (int i = 0; i < ch_porosites_->valeurs().dimension_tot(0); i++)
422 {
423 if (ch_porosites_->valeurs()(i) < 0.) ch_porosites_->valeurs()(i) = 0.;
424 if (ch_porosites_->valeurs()(i) > 1.) ch_porosites_->valeurs()(i) = 1.;
425 }
426
427 assert(mp_min_vect(ch_porosites_->valeurs()) >= 0.0 && mp_max_vect(ch_porosites_->valeurs()) <= 1.0);
428}
429
431{
432 if (err==1)
433 {
434 Cerr<<"Error while reading the physical properties of a "<<que_suis_je()<<" medium."<<finl;
435 Cerr<<msg<<finl;
437 }
438 else if (err==2)
439 {
440 Cerr<<"Warning while reading the physical properties of a "<<que_suis_je()<<" medium."<<finl;
441 Cerr<<msg<<finl;
442 }
443 else
444 Cerr<<"The physical properties of a "<<que_suis_je()<<" medium have been successfully checked."<<finl;
445}
446
448{
449 // ne fait rien!!!
450}
451
453{
454 if (ch_g_)
455 if(Objet_U::dimension != ch_g_->nb_comp())
456 {
457 Cerr << "The dimension is " << Objet_U::dimension << " and you create a gravity vector with " << ch_g_->nb_comp() << " components." << finl;
459 }
460}
461
463{
464 if (ch_rho_ && ch_lambda_ && ch_Cp_)
465 creer_alpha();
466}
467
468void Milieu_base::warn_old_syntax()
469{
470 if (que_suis_je() != "Fluide_Diphasique") // pour le FT pour le moment ...
471 {
472 Cerr << "YOU ARE USING AN OLD SYNTAX IN YOUR DATA FILE AND THIS IS NO MORE SUPPORTED !" << finl;
473 Cerr << "STARTING FROM TRUST-v1.9.3 : GRAVITY SHOULD BE READ INSIDE THE MEDIUM AND NOT VIA ASSOSCIATION ... " << finl;
474 Cerr << "HAVE A LOOK TO ANY TRUST TEST CASE TO SEE HOW IT SHOULD BE DONE ($TRUST_ROOT/tests/) ... " << finl;
475 Cerr << "OR RUN -convert_data OPTION OF YOUR APPLICATION SCRIPT, FOR TRUST FOR EXAMPLE:" << finl;
476 Cerr << " trust -convert_data " << Objet_U::nom_du_cas() << ".data" << finl;
478 }
479}
480
481/*! @brief Associe la gravite en controlant dynamiquement le type de l'objet a associer.
482 *
483 * Si l'objet est du type OWN_PTR(Champ_Don_base) ou Champ_Don_base
484 * l'association reussit, sinon elle echoue.
485 *
486 * @param (Objet_U& ob) un objet TRUST devant representer un champ de gravite
487 * @return (int) 1 si l'association a reussie, 0 sinon.
488 */
490{
491 if (sub_type(Champ_Don_base,ob))
492 {
493 warn_old_syntax();
494 via_associer_ = true;
495 associer_gravite(ref_cast(Champ_Don_base, ob));
496 return 1;
497 }
498 if (dynamic_cast <Champ_Don_base*>(&ob) != nullptr)
499 {
500 warn_old_syntax();
501 via_associer_ = true;
502 associer_gravite(dynamic_cast<Champ_Don_base&>(ob));
503 return 1;
504 }
505 return 0;
506}
507
508/*! @brief Associe (affecte) un champ de gravite au milieu.
509 *
510 * @param (Champ_Don_base& gravite) champ donne representant la gravite
511 */
513{
514 // On verifie que la gravite est de la bonne dimension
515 if (Objet_U::dimension!=la_gravite.nb_comp())
516 {
517 Cerr << "The dimension is " << Objet_U::dimension << " and you create a gravity vector with " << la_gravite.nb_comp() << " components." << finl;
518 exit();
519 }
520 g_via_associer_ = la_gravite;
521
522 if (via_associer_ && ch_g_)
523 {
524 assert (g_via_associer_);
525 Cerr << "WHAT ?? Remove the associer gravity line from your jdd because it is already in the medium !!!" << finl;
527 }
528}
529
530/*! @brief Calcul de alpha=lambda/(rho*Cp).
531 *
532 * Suivant lambda, rho et Cp alpha peut-etre type comme
533 * un champ uniforme ou un champ uniforme par morceau.
534 *
535 * @throws violation d'une precondition
536 * @throws impossible de calculer alpha car le type des champs
537 * lambda,rho,Cp n'est pas compatible ou pas gere.
538 */
540{
541 if(ch_lambda_)
542 {
543 DoubleTab& tabalpha = ch_alpha_->valeurs(), &tab_lambda_sur_cp = ch_alpha_fois_rho_->valeurs();
544
545 tabalpha = ch_lambda_->valeurs();
546 tab_lambda_sur_cp = ch_lambda_->valeurs();
547
548 // [ABN]: allows variable rho, Cp at this level (will be used by Solide_Milieu_Variable for instance).
549 if (sub_type(Champ_Uniforme,ch_rho_.valeur()))
550 tabalpha /= ch_rho_->valeurs()(0,0);
551 else
552 tab_divide_any_shape(tabalpha,ch_rho_->valeurs());
553
554 if (sub_type(Champ_Uniforme,ch_Cp_.valeur()))
555 {
556 tabalpha /= ch_Cp_->valeurs()(0,0);
557 tab_lambda_sur_cp /= ch_Cp_->valeurs()(0,0);
558 }
559 else
560 {
561 tab_divide_any_shape(tabalpha,ch_Cp_->valeurs());
562 tab_divide_any_shape(tab_lambda_sur_cp,ch_Cp_->valeurs());
563 }
564 }
565 else
566 Cerr << "alpha calculation is not possible since lambda is not known." << finl;
567}
568
570{
571 assert(is_field_porosites());
572 const Domaine_VF& zvf = ref_cast(Domaine_VF, zdb_.valeur());
573
574 // update porosite_faces
575 const int nb_face_tot = zvf.nb_faces_tot();
576 assert (nb_face_tot == porosite_face_.size_totale());
577 const IntTab& face_voisins = zvf.face_voisins();
578
579 for (int face = 0; face < nb_face_tot; face++)
580 {
581 const int elem1 = face_voisins(face, 1), elem2 = face_voisins(face, 0);
582 if ((elem1 != -1) && (elem2 != -1))
583 porosite_face_(face) = 2. / (1. / ch_porosites_->valeurs()(elem1) + 1. / ch_porosites_->valeurs()(elem2));
584 else if (elem1 != -1)
585 porosite_face_(face) = ch_porosites_->valeurs()(elem1);
586 else
587 porosite_face_(face) = ch_porosites_->valeurs()(elem2);
588 }
589 porosite_face_.echange_espace_virtuel();
590}
591
593{
594 //Cerr << que_suis_je() << "Milieu_base::mettre_a_jour" << finl;
595 if (ch_rho_) ch_rho_->mettre_a_jour(temps);
596
597 if (ch_g_) ch_g_->mettre_a_jour(temps);
598
599 if (g_via_associer_) g_via_associer_->mettre_a_jour(temps);
600
601 if (ch_lambda_) ch_lambda_->mettre_a_jour(temps);
602
603 if (ch_Cp_) ch_Cp_->mettre_a_jour(temps);
604
605 if (ch_beta_th_) ch_beta_th_->mettre_a_jour(temps);
606
607 if ( (bool(ch_lambda_)) && (bool(ch_Cp_)) && (bool(ch_rho_)) )
608 {
610 ch_alpha_->changer_temps(temps);
611 ch_alpha_fois_rho_->changer_temps(temps);
612 }
613
615
616 mettre_a_jour_porosite(temps); // pour F5 !
617}
618
619// methode utile pour F5 ! F5 n'appelle pas Milieu_base::mettre_a_jour mais Milieu_base::mettre_a_jour_porosite ...
621{
623 if (is_field_porosites())
624 if (sub_type(Champ_Input_P0_Composite, ch_porosites_.valeur()))
625 {
626 Cerr << "Updating porosity values since Champ_input_P0 !! We update also the face_porosity & section_passage fields ..." << finl;
627 verifie_champ_porosites();
630 ch_porosites_->changer_temps(temps);
631 /* pas besoin je crois mais je laisse en commentaire ;-) */
632 // porosites_champ->valeurs().echange_espace_virtuel();
633 }
634
635 ch_porosites_->mettre_a_jour(temps); /* ne fait rien si Champ_Input_P0_Composite */
636 ch_diametre_hyd_->mettre_a_jour(temps);
637}
638
640{
641 // Si l'inconnue est sur le device, on copie les donnees aussi:
642 if (equation_.size() && (*(equation_.begin()->second)).inconnue().valeurs().isDataOnDevice())
643 {
644 mapToDevice(ch_rho_Cp_elem_->valeurs());
645 mapToDevice(ch_rho_Cp_comme_T_->valeurs());
646 }
647 ch_rho_Cp_elem_->changer_temps(temps);
648 ch_rho_Cp_elem_->changer_temps(temps);
649 DoubleTab& rho_cp=ch_rho_Cp_elem_->valeurs();
650 if (sub_type(Champ_Uniforme,ch_rho_.valeur()))
651 rho_cp=ch_rho_->valeurs()(0,0);
652 else
653 {
654 // AB: rho_cp = rho->valeurs() turns rho_cp into a 2 dimensional array with 1 compo. We want to stay mono-dim:
655 rho_cp = 1.;
656 tab_multiply_any_shape(rho_cp, ch_rho_->valeurs());
657 }
658 if (sub_type(Champ_Uniforme,ch_Cp_.valeur()))
659 rho_cp*=ch_Cp_->valeurs()(0,0);
660 else
661 tab_multiply_any_shape(rho_cp,ch_Cp_->valeurs());
662 ch_rho_Cp_comme_T_->changer_temps(temps);
663 ch_rho_Cp_comme_T_->changer_temps(temps);
664 const MD_Vector& md_som = ch_rho_Cp_elem_->domaine_dis_base().domaine().md_vector_sommets(),
665 &md_faces = ref_cast(Domaine_VF,ch_rho_Cp_elem_->domaine_dis_base()).md_vector_faces();
666 if (ch_rho_Cp_comme_T_->valeurs().get_md_vector() == ch_rho_Cp_elem_->valeurs().get_md_vector())
667 ch_rho_Cp_comme_T_->valeurs() = rho_cp;
668 else if (ch_rho_Cp_comme_T_->valeurs().get_md_vector() == md_som)
670 else if (ch_rho_Cp_comme_T_->valeurs().get_md_vector() == md_faces)
672 else
673 {
674 Cerr<< que_suis_je()<<(int)__LINE__<<finl;
676 }
677}
678
680{
681 if (ch_rho_) ch_rho_->abortTimeStep();
682}
683
684void Milieu_base::resetTime(double time)
685{
686 if (ch_rho_)
687 {
688 if (sub_type(Champ_Don_base, ch_rho_.valeur()))
689 ch_rho_->mettre_a_jour(time);
690 else if (sub_type(Champ_Inc_base, ch_rho_.valeur()))
691 ch_rho_->resetTime(time);
692 else
693 throw;
694 }
695}
696
698{
699 Cerr << "Milieu_base::creer_alpha (champ non lu)" << finl;
700 assert(ch_lambda_);
701 assert(ch_rho_);
702 assert(ch_Cp_);
705 ch_alpha_->nommer("alpha");
706 ch_alpha_fois_rho_->nommer("alpha_fois_rho");
707}
708
709/*! @brief Renvoie la gravite du milieu si elle a ete associe provoque une erreur sinon.
710 *
711 * (version const)
712 *
713 * @return (Champ_Don_base&) le champ representant la gravite du milieu
714 * @throws pas de gravite associee au milieu
715 */
717{
718 if (!ch_g_ && !g_via_associer_)
719 {
720 Cerr << "The gravity has not been associated with the medium" << finl;
722 }
723
724 return ch_g_ ? ch_g_.valeur() : g_via_associer_.valeur();
725}
726
727/*! @brief Renvoie la gravite du milieu si elle a ete associe provoque une erreur sinon.
728 *
729 * @return (Champ_Don_base&) le champ representant la gravite du milieu
730 */
732{
733 if (!ch_g_ && !g_via_associer_)
734 {
735 Cerr << "The gravity has not been associated with the medium" << finl;
737 }
738
739 return ch_g_ ? ch_g_.valeur() : g_via_associer_.valeur();
740}
741
742int Milieu_base::initialiser(const double temps)
743{
744 Cerr << que_suis_je() << " Milieu_base:::initialiser" << finl;
745 if (sub_type(Champ_Don_base, ch_rho_.valeur())) ref_cast(Champ_Don_base, ch_rho_.valeur()).initialiser(temps);
746
747 if (ch_g_) ch_g_->initialiser(temps);
748
749 if (g_via_associer_) g_via_associer_->initialiser(temps);
750
751 if (ch_lambda_) ch_lambda_->initialiser(temps);
752
753 if (ch_Cp_) ch_Cp_->initialiser(temps);
754
755 if (ch_beta_th_) ch_beta_th_->initialiser(temps);
756
757 if ( (bool(ch_lambda_)) && (bool(ch_Cp_)) && (bool(ch_rho_)) )
758 {
760 ch_alpha_->changer_temps(temps);
761 ch_alpha_fois_rho_->changer_temps(temps);
762 }
763
765
766 int err=0;
767 Nom msg;
769
770 return initialiser_porosite(temps);
771}
772
773// methode utile pour F5 ! F5 n'appelle pas Milieu_base::initialiser mais Milieu_base::initialiser_porosite ...
775{
776 // TODO : XXX : a voir si ICoCo ? faut l'initialiser dans le main ?
778 ch_porosites_->initialiser(temps);
779 ch_diametre_hyd_->initialiser(temps);
780 return 1;
781}
782
784{
785 const Domaine_VF& zvf = ref_cast(Domaine_VF, zdb_.valeur());
786 const DoubleVect& fs = zvf.face_surfaces();
788 for (int i = 0; i < fs.size_array(); i++) section_passage_face_[i] = fs[i] * porosite_face_[i];
789}
790
791/*! @brief Renvoie la masse volumique du milieu.
792 *
793 * (version const)
794 *
795 * @return (Champ_base&) le champ donne representant la masse volumique
796 */
798{
799 return ch_rho_.valeur();
800}
801
802/*! @brief Renvoie la masse volumique du milieu.
803 *
804 * @return (Champ_base&) le champ donne representant la masse volumique
805 */
807{
808 return ch_rho_.valeur();
809}
810
811/*! @brief Renvoie la diffusivite du milieu.
812 *
813 * (version const)
814 *
815 * @return (Champ_Don_base&) le champ donne representant la diffusivite
816 */
818{
819 return ch_alpha_.valeur();
820}
821
822/*! @brief Renvoie la diffusivite du milieu.
823 *
824 * @return (Champ_Don_base&) le champ donne representant la diffusivite
825 */
827{
828 return ch_alpha_.valeur();
829}
830
832{
833 return ch_alpha_fois_rho_.valeur();
834}
835
840
841/*! @brief Renvoie la conductivite du milieu.
842 *
843 * (version const)
844 *
845 * @return (Champ_Don_base&) le champ donne representant la conductivite
846 */
848{
849 return ch_lambda_.valeur();
850}
851
852/*! @brief Renvoie la conductivite du milieu.
853 *
854 * @return (Champ_Don_base&) le champ donne representant la conductivite
855 */
857{
858 return ch_lambda_.valeur();
859}
860
861/*! @brief Renvoie la capacite calorifique du milieu.
862 *
863 * (version const)
864 *
865 * @return (Champ_Don_base&) le champ donne representant la capacite calorifique
866 */
868{
869 return ch_Cp_.valeur();
870}
871
872/*! @brief Renvoie la capacite calorifique du milieu.
873 *
874 * @return (Champ_Don_base&) le champ donne representant la capacite calorifique
875 */
880
881/*! @brief Renvoie beta_t du milieu.
882 *
883 * (version const)
884 *
885 * @return (Champ_Don_base&) le champ donne representant beta_t
886 */
888{
889 return ch_beta_th_.valeur();
890}
891
892/*! @brief Renvoie beta_t du milieu.
893 *
894 * @return (Champ_Don_base&) le champ donne representant beta_t
895 */
897{
898 return ch_beta_th_.valeur();
899}
900
901/*! @brief Renvoie 1 si la gravite a ete initialisee
902 *
903 * @return (int) 1 si g.non_nul
904 */
906{
907 return (ch_g_ || g_via_associer_) ? 1 : 0;
908}
909
911{
912 return champs_compris_.get_champ(nom);
913}
914
915bool Milieu_base::has_champ(const Motcle& nom, OBS_PTR(Champ_base) &ref_champ) const
916{
917 return champs_compris_.has_champ(nom, ref_champ);
918}
919
920bool Milieu_base::has_champ(const Motcle& nom) const
921{
922 return champs_compris_.has_champ(nom);
923}
924
926{
927 if (opt == DESCRIPTION)
928 Cerr << que_suis_je() << " : " << champs_compris_.liste_noms_compris() << finl;
929 else
930 nom.add(champs_compris_.liste_noms_compris());
931}
932
933/*! @brief Renvoie 0 si le milieu est deja associe a un probleme, 1 sinon
934 *
935 * @return (int)
936 */
938{
939 if (deja_associe_==1)
940 return 0;
941 deja_associe_=1;
942 return 1;
943}
944
946{
947 std::string nom_inco(eqn->inconnue().le_nom().getString());
948 // E. Saikali
949 // At the initialization step, FT problem can have several equations with same unknown name "concentration"
950 if (equation_.count(nom_inco) && eqn->probleme().que_suis_je() != "Probleme_FT_Disc_gen")
951 {
952 Cerr << que_suis_je() << " multiple equations solve the unknown " << eqn->inconnue().le_nom() << " !" << finl;
954 }
955 equation_[nom_inco] = eqn;
956}
957
958const Equation_base& Milieu_base::equation(const std::string& inco) const
959{
960 return *equation_.at(inco);
961}
962
964{
965 id_composite_ = i;
966}
967
968void Milieu_base::nommer(const Nom& nom)
969{
970 nom_ = nom;
971}
973{
974 return nom_;
975}
976
classe Champ_Don_base classe de base des Champs donnes (non calcules)
classe Champ_Fonc_MED Load a field from a MED file for a given time.
Classe Champ_Fonc_Tabule Classe derivee de Champ_Fonc_base qui represente les.
Classe Champ_Inc_base.
classe Champ_Uniforme Represente un champ constant dans l'espace et dans le temps.
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
class Champ_input_P0
classe Discretisation_base Cette classe represente un schema de discretisation en espace,...
void nommer_completer_champ_physique(const Domaine_dis_base &domaine_vdf, const Nom &nom_champ, const Nom &unite, Champ_base &champ, const Probleme_base &pbi) const
virtual bool is_dg() const
void discretiser_champ(const Motcle &directive, const Domaine_dis_base &z, const Nom &nom, const Nom &unite, int nb_comp, int nb_pas_dt, double temps, OWN_PTR(Champ_Inc_base)&champ, const Nom &sous_type=NOM_VIDE) const
static void cells_to_faces(const Champ_base &He, Champ_base &Hf)
static void cells_to_nodes(const Champ_base &He, Champ_base &Hn)
class Domaine_VF
Definition Domaine_VF.h:44
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
int nb_faces_tot() const
renvoie le nombre total de faces.
Definition Domaine_VF.h:481
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
virtual const Champ_Inc_base & inconnue() const =0
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
const Nom & le_nom() const override
Renvoie le nom du champ.
virtual int nb_comp() const
Definition Field_base.h:56
virtual void add_synonymous(const Nom &nom)
Definition Field_base.h:53
static void creer_tableau_distribue(const MD_Vector &, Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
transforme v en un tableau parallele ayant la structure md.
: Cette classe est un OWN_PTR mais l'objet pointe est partage entre plusieurs
Definition MD_Vector.h:48
classe Milieu_base Cette classe est la base de la hierarchie des milieux (physiques)
Definition Milieu_base.h:50
void ecrire(Sortie &) const
Ecrit un objet milieu sur un flot de sortie.
virtual int est_deja_associe()
Renvoie 0 si le milieu est deja associe a un probleme, 1 sinon.
virtual void associer_equation(const Equation_base *eqn) const
DoubleVect diametre_hydraulique_face_
virtual int initialiser(const double temps)
void nommer(const Nom &) override
Donne un nom a l'Objet_U Methode virtuelle a surcharger.
void creer_alpha()
virtual void creer_champs_non_lus()
void discretiser_porosite(const Probleme_base &pb, const Discretisation_base &dis)
virtual const Equation_base & equation(const std::string &nom_inc) const
virtual void mettre_a_jour(double temps)
virtual void resetTime(double time)
virtual void preparer_calcul()
virtual void calculate_face_porosity()
virtual const Champ_Don_base & capacite_calorifique() const
Renvoie la capacite calorifique du milieu.
virtual void abortTimeStep()
virtual void update_rho_cp(double temps)
void get_noms_champs_postraitables(Noms &nom, Option opt=NONE) const override
int initialiser_porosite(const double temps)
bool has_champ(const Motcle &nom, OBS_PTR(Champ_base) &ref_champ) const override
OBS_PTR(Domaine_dis_base) zdb_
virtual void discretiser(const Probleme_base &pb, const Discretisation_base &dis)
OWN_PTR(Champ_base) ch_rho_
virtual void calculate_face_hydr_diam()
const Champ_base & get_champ(const Motcle &nom) const override
virtual const Champ_Don_base & diffusivite_fois_rho() const
virtual const Champ_Don_base & beta_t() const
Renvoie beta_t du milieu.
DoubleVect porosite_face_
void set_id_composite(const int i)
virtual const Champ_Don_base & conductivite() const
Renvoie la conductivite du milieu.
void discretiser_diametre_hydro(const Probleme_base &pb, const Discretisation_base &dis)
virtual void associer_gravite(const Champ_Don_base &)
Associe (affecte) un champ de gravite au milieu.
virtual void verifier_coherence_champs(int &err, Nom &message)
virtual const Champ_Don_base & diffusivite() const
Renvoie la diffusivite du milieu.
virtual const Champ_base & masse_volumique() const
Renvoie la masse volumique du milieu.
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.
virtual void set_additional_params(Param &param) const
Champs_compris champs_compris_
int associer_(Objet_U &) override
Associe la gravite en controlant dynamiquement le type de l'objet a associer.
void check_gravity_vector() const
virtual void set_param(Param &param) const override
virtual void calculer_alpha()
Calcul de alpha=lambda/(rho*Cp).
void mettre_a_jour_porosite(double temps)
std::map< std::string, const Equation_base * > equation_
DoubleVect section_passage_face_
virtual int a_gravite() const
Renvoie 1 si la gravite a ete initialisee.
void fill_section_passage_face()
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
virtual const Champ_Don_base & gravite() const
Renvoie la gravite du milieu si elle a ete associe provoque une erreur sinon.
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
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
friend class Entree
Definition Objet_U.h:76
static int dimension
Definition Objet_U.h:99
friend class Sortie
Definition Objet_U.h:75
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
Objet_U()
Constructeur par defaut : attribue un numero d'identifiant unique a l'objet (object_id_),...
Definition Objet_U.cpp:55
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(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
const Schema_Temps_base & schema_temps() const
Renvoie le schema en temps associe au probleme.
const Domaine_dis_base & domaine_dis() const
Renvoie le domaine discretise associe au probleme.
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
double temps_courant() const
Renvoie le temps courant.
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ size_array() const