TrioCFD 1.9.9_beta
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 Writes a medium object to an output stream.
43 *
44 * Writes the characteristics of the medium:
45 * - density
46 * - conductivity
47 * - heat capacity
48 * - beta_th
49 * - porosity
50 *
51 * @param (Sortie& os) the output stream for writing
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 Reading of a medium from an input stream.
63 *
64 * Format:
65 * {
66 * physical_quantity field_type field_reading_block
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) the input stream for reading the medium parameters
72 * @return (Entree&) the modified input stream
73 * @throws opening brace expected
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// Useful method for F5! F5 does not call Milieu_base::set_param but 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 // for F5, gravity is added here ...
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: no time to make it cleaner, I do as in Fluide_Incompressible::discretiser to handle a conductivity read from a MED file. Test: Reprise_grossier_fin_VEF
132 // ToDo: rewrite these two discretiser methods
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) // For anisotropic case
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 // the real name will be given later
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 : I reset nb_comp = 1, otherwise it blocks in Solveur_Masse_base => tab_divide_any_shape
207 // because we do not have line_size % line_size_vx == 0 (case nb_comp >1 for rho and cp)
208 // TODO : FIXME : a generic case must be coded in DoubleVect::tab_divide_any_shape... good luck
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// Useful method for F5! F5 does not call Milieu_base::discretiser but 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 // We build porosite_face_ with a parallel descriptor
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_) // Read via 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(); // Initialize!
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 // We will now use porosites_champ!
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.; // Initialize to 1 ...
298 porosites_.remplir_champ(zvf, ch_porosites_->valeurs(), porosite_face_);
299 }
300 else // Not defined by the user
301 {
302 // We will now use porosites_champ!
303 dis.discretiser_champ("champ_elem", zdb_.valeur(), fld_name, fld_unit, 1, temps, ch_porosites_);
304 ch_porosites_->valeurs() = 1.; // Initialize to 1 ...
305 }
306
307 // We add for all cases
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(); /* otherwise it is already filled ... */
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 // We build porosite_face_ with a parallel descriptor
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.; /* hydraulic diameters are initialized to 0 */
335
336 if (ch_diametre_hyd_) // Read via 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 // Not defined by the user
360 {
361 dis.discretiser_champ("champ_elem", zdb_.valeur(), fld_name, fld_unit, 1, temps, ch_diametre_hyd_);
362 ch_diametre_hyd_->valeurs() = 0.; // Initialize to 0 ...
363 }
364
365 champs_compris_.ajoute_champ(ch_diametre_hyd_.valeur());
366
367 if (has_hydr_diam_) calculate_face_hydr_diam(); /* otherwise it is already filled ... */
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: to be checked if useful... not used for now
390}
391
392void Milieu_base::verifie_champ_porosites()
393{
394 // XXX : Elie Saikali : Previously we tested this:
395 // assert(mp_min_vect(porosites_champ->valeurs()) >= 0. && mp_max_vect(porosites_champ->valeurs()) <= 1.);
396 // encountered an F5 case with printf("%.9g\n", 1.0 - mp_max_vect) = -2.88657986e-15
397 // tried comparing with std::numeric_limits<double>::epsilon() but the overflow is larger !!
398 // so I clean the field like this for now ... if it is reasonable!
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 // does nothing!!!
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") // for FT for now ...
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 Associates gravity by dynamically checking the type of the object to associate.
482 *
483 * If the object is of type OWN_PTR(Champ_Don_base) or Champ_Don_base
484 * the association succeeds, otherwise it fails.
485 *
486 * @param (Objet_U& ob) a TRUST object representing a gravity field
487 * @return (int) 1 if the association succeeded, 0 otherwise.
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 Associates (assigns) a gravity field to the medium.
509 *
510 * @param (Champ_Don_base& gravite) given field representing gravity
511 */
513{
514 // We verify that gravity has the correct 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 Computes alpha=lambda/(rho*Cp).
531 *
532 * Depending on lambda, rho and Cp, alpha can be typed as
533 * a uniform field or a piecewise uniform field.
534 *
535 * @throws if a precondition is violated
536 * @throws if alpha cannot be computed because the types of the fields
537 * lambda, rho, Cp are incompatible or not handled.
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); // for F5!
617}
618
619// Utility method for F5! F5 does not call Milieu_base::mettre_a_jour but 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 /* not needed I think but leaving as comment ;-) */
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 // If the unknown is on the device, copy the data there too:
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 (field not read)" << 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 Returns the gravity of the medium if it has been associated, raises an error otherwise (const version).
710 *
711 * @return (Champ_Don_base&) the field representing the gravity of the medium
712 * @throws if no gravity is associated with the medium
713 */
715{
716 if (!ch_g_ && !g_via_associer_)
717 {
718 Cerr << "The gravity has not been associated with the medium" << finl;
720 }
721
722 return ch_g_ ? ch_g_.valeur() : g_via_associer_.valeur();
723}
724
725/*! @brief Returns the gravity of the medium if it has been associated, raises an error otherwise.
726 *
727 * @return (Champ_Don_base&) the field representing the gravity of the medium
728 */
730{
731 if (!ch_g_ && !g_via_associer_)
732 {
733 Cerr << "The gravity has not been associated with the medium" << finl;
735 }
736
737 return ch_g_ ? ch_g_.valeur() : g_via_associer_.valeur();
738}
739
740int Milieu_base::initialiser(const double temps)
741{
742 Cerr << que_suis_je() << " Milieu_base:::initialiser" << finl;
743 if (sub_type(Champ_Don_base, ch_rho_.valeur())) ref_cast(Champ_Don_base, ch_rho_.valeur()).initialiser(temps);
744
745 if (ch_g_) ch_g_->initialiser(temps);
746
747 if (g_via_associer_) g_via_associer_->initialiser(temps);
748
749 if (ch_lambda_) ch_lambda_->initialiser(temps);
750
751 if (ch_Cp_) ch_Cp_->initialiser(temps);
752
753 if (ch_beta_th_) ch_beta_th_->initialiser(temps);
754
755 if ( (bool(ch_lambda_)) && (bool(ch_Cp_)) && (bool(ch_rho_)) )
756 {
758 ch_alpha_->changer_temps(temps);
759 ch_alpha_fois_rho_->changer_temps(temps);
760 }
761
763
764 int err=0;
765 Nom msg;
767
768 return initialiser_porosite(temps);
769}
770
771// method useful for F5! F5 does not call Milieu_base::initialiser but Milieu_base::initialiser_porosite ...
773{
774 // TODO : XXX : to check for ICoCo ? it should be initialized in main ?
776 ch_porosites_->initialiser(temps);
777 ch_diametre_hyd_->initialiser(temps);
778 return 1;
779}
780
782{
783 const Domaine_VF& zvf = ref_cast(Domaine_VF, zdb_.valeur());
784 const DoubleVect& fs = zvf.face_surfaces();
786 for (int i = 0; i < fs.size_array(); i++) section_passage_face_[i] = fs[i] * porosite_face_[i];
787}
788
789/*! @brief Returns the mass density of the medium (const version).
790 *
791 * @return (Champ_base&) the field representing the mass density
792 */
794{
795 return ch_rho_.valeur();
796}
797
798/*! @brief Returns the mass density of the medium.
799 *
800 * @return (Champ_base&) the field representing the mass density
801 */
803{
804 return ch_rho_.valeur();
805}
806
807/*! @brief Returns the diffusivity of the medium (const version).
808 *
809 * @return (Champ_Don_base&) the field representing the diffusivity
810 */
812{
813 return ch_alpha_.valeur();
814}
815
816/*! @brief Returns the diffusivity of the medium.
817 *
818 * @return (Champ_Don_base&) the field representing the diffusivity
819 */
821{
822 return ch_alpha_.valeur();
823}
824
826{
827 return ch_alpha_fois_rho_.valeur();
828}
829
834
835/*! @brief Returns the conductivity of the medium (const version).
836 *
837 * @return (Champ_Don_base&) the field representing the conductivity
838 */
840{
841 return ch_lambda_.valeur();
842}
843
844/*! @brief Returns the conductivity of the medium.
845 *
846 * @return (Champ_Don_base&) the field representing the conductivity
847 */
849{
850 return ch_lambda_.valeur();
851}
852
853/*! @brief Returns the heat capacity of the medium (const version).
854 *
855 * @return (Champ_Don_base&) the field representing the heat capacity
856 */
858{
859 return ch_Cp_.valeur();
860}
861
862/*! @brief Returns the heat capacity of the medium.
863 *
864 * @return (Champ_Don_base&) the field representing the heat capacity
865 */
870
871/*! @brief Returns beta_t of the medium (const version).
872 *
873 * @return (Champ_Don_base&) the field representing beta_t
874 */
876{
877 return ch_beta_th_.valeur();
878}
879
880/*! @brief Returns beta_t of the medium.
881 *
882 * @return (Champ_Don_base&) the field representing beta_t
883 */
885{
886 return ch_beta_th_.valeur();
887}
888
889/*! @brief Returns 1 if gravity has been initialized.
890 *
891 * @return (int) 1 if g is non-null
892 */
894{
895 return (ch_g_ || g_via_associer_) ? 1 : 0;
896}
897
899{
900 return champs_compris_.get_champ(nom);
901}
902
903bool Milieu_base::has_champ(const Motcle& nom, OBS_PTR(Champ_base) &ref_champ) const
904{
905 return champs_compris_.has_champ(nom, ref_champ);
906}
907
908bool Milieu_base::has_champ(const Motcle& nom) const
909{
910 return champs_compris_.has_champ(nom);
911}
912
914{
915 if (opt == DESCRIPTION)
916 Cerr << que_suis_je() << " : " << champs_compris_.liste_noms_compris() << finl;
917 else
918 nom.add(champs_compris_.liste_noms_compris());
919}
920
921/*! @brief Returns 0 if the medium is already associated with a problem, 1 otherwise.
922 *
923 * @return (int)
924 */
926{
927 if (deja_associe_==1)
928 return 0;
929 deja_associe_=1;
930 return 1;
931}
932
934{
935 std::string nom_inco(eqn->inconnue().le_nom().getString());
936 // E. Saikali
937 // At the initialization step, FT problem can have several equations with same unknown name "concentration"
938 if (equation_.count(nom_inco) && eqn->probleme().que_suis_je() != "Probleme_FT_Disc_gen")
939 {
940 Cerr << que_suis_je() << " multiple equations solve the unknown " << eqn->inconnue().le_nom() << " !" << finl;
942 }
943 equation_[nom_inco] = eqn;
944}
945
946const Equation_base& Milieu_base::equation(const std::string& inco) const
947{
948 return *equation_.at(inco);
949}
950
952{
953 id_composite_ = i;
954}
955
956void Milieu_base::nommer(const Nom& nom)
957{
958 nom_ = nom;
959}
961{
962 return nom_;
963}
964
class Champ_Don_base base class of Given Fields (not calculated)
class Champ_Fonc_MED Load a field from a MED file for a given time.
Class Champ_Fonc_Tabule Derived class of Champ_Fonc_base representing.
Class Champ_Inc_base.
Champ_Uniforme Represents a field that is constant in space and time.
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
class Champ_input_P0
class Discretisation_base This class represents a spatial discretization scheme, which
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
Returns the total number of faces.
Definition Domaine_VF.h:481
int face_voisins(int num_face, int i) const
Returns the neighbouring element of num_face in direction i.
Definition Domaine_VF.h:418
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
class Equation_base The role of an equation is the calculation of one or more fields....
virtual const Champ_Inc_base & inconnue() const =0
Probleme_base & probleme()
Returns the problem associated with the equation.
const Nom & le_nom() const override
Returns the name of the field.
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)
Transforms v into a parallel array having the structure md.
: This class is an OWN_PTR but the pointed object is shared among multiple
Definition MD_Vector.h:48
Milieu_base This class is the base of the (physical) medium hierarchy.
Definition Milieu_base.h:50
void ecrire(Sortie &) const
Writes a medium object to an output stream.
virtual int est_deja_associe()
Returns 0 if the medium is already associated with a problem, 1 otherwise.
virtual void associer_equation(const Equation_base *eqn) const
DoubleVect diametre_hydraulique_face_
virtual int initialiser(const double temps)
void nommer(const Nom &) override
Assigns a name to the Objet_U. Virtual method to override.
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
Returns the heat capacity of the medium (const version).
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
Returns beta_t of the medium (const version).
DoubleVect porosite_face_
void set_id_composite(const int i)
virtual const Champ_Don_base & conductivite() const
Returns the conductivity of the medium (const version).
void discretiser_diametre_hydro(const Probleme_base &pb, const Discretisation_base &dis)
virtual void associer_gravite(const Champ_Don_base &)
Associates (assigns) a gravity field to the medium.
virtual void verifier_coherence_champs(int &err, Nom &message)
virtual const Champ_Don_base & diffusivite() const
Returns the diffusivity of the medium (const version).
virtual const Champ_base & masse_volumique() const
Returns the mass density of the medium (const version).
int lire_motcle_non_standard(const Motcle &, Entree &) override
Reads non-simple-type parameters of an Objet_U from an input stream.
virtual void set_additional_params(Param &param) const
Champs_compris champs_compris_
int associer_(Objet_U &) override
Associates gravity by dynamically checking the type of the object to associate.
void check_gravity_vector() const
virtual void set_param(Param &param) const override
virtual void calculer_alpha()
Computes 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
Returns 1 if gravity has been initialized.
void fill_section_passage_face()
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
virtual const Champ_Don_base & gravite() const
Returns the gravity of the medium if it has been associated, raises an error otherwise (const version...
A character string (Nom) in uppercase.
Definition Motcle.h:26
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
const std::string & getString() const
Definition Nom.h:92
An array of character strings (VECT(Nom)).
Definition Noms.h:26
Base class for TRUST objects (Objet_U).
Definition Objet_U.h:68
friend class Entree
Definition Objet_U.h:71
static int dimension
Definition Objet_U.h:94
friend class Sortie
Definition Objet_U.h:70
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
static const Nom & nom_du_cas()
Returns a constant reference to the case name. This method is static.
Definition Objet_U.cpp:145
Objet_U()
Default constructor: assigns a unique identifier to the object (object_id_) and registers the object ...
Definition Objet_U.cpp:54
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
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
class Probleme_base It is a Probleme_U that is not a coupling.
const Schema_Temps_base & schema_temps() const
Returns the time scheme associated with the problem.
const Domaine_dis_base & domaine_dis() const
Returns the discretized domain associated with the problem (const version).
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
double temps_courant() const
Returns the current time.
Base class for output streams.
Definition Sortie.h:52
_SIZE_ size_array() const