TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Op_Diff_PolyMAC_CDO_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 <Modele_turbulence_scal_base.h>
17#include <Echange_externe_impose.h>
18#include <Op_Diff_PolyMAC_CDO_base.h>
19#include <Check_espace_virtuel.h>
20#include <Champ_Elem_PolyMAC_CDO.h>
21#include <Champ_Fonc_P0_base.h>
22#include <Domaine_Cl_PolyMAC_family.h>
23#include <Champ_Uniforme.h>
24#include <Milieu_base.h>
25
26Implemente_base(Op_Diff_PolyMAC_CDO_base, "Op_Diff_PolyMAC_CDO_base", Op_Diff_PolyMAC_CDO_Gen_base);
27
29
31
33{
34 update_nu();
35 const Domaine& mon_dom = le_dom_poly_->domaine();
36 double dt_stab = DMAXFLOAT;
37
38 const int nb_elem = mon_dom.nb_elem();
39
41 {
42 // Methode "standard" de calcul du pas de temps
43 // Ce calcul est tres conservatif: si le max de la diffusivite
44 // n'est pas atteint a l'endroit ou le min de delta_h_carre est atteint,
45 // le pas de temps est sous-estime.
46 const Champ_base& champ_diffusivite = diffusivite_pour_pas_de_temps();
47 const DoubleVect& valeurs_diffusivite = champ_diffusivite.valeurs();
48 double alpha_max = local_max_vect(valeurs_diffusivite);
49
50 // Detect if a heat flux is imposed on a boundary through Paroi_echange_externe_impose keyword
51 double h_imp_max = -1, h_imp_temp = -2;
52
53 const Domaine_Cl_PolyMAC_family& le_dom_cl_poly = la_zcl_poly_.valeur();
54 for (int i = 0; i < le_dom_cl_poly.nb_cond_lim(); i++)
55 {
56 // loop on boundaries
57 const Cond_lim_base& la_cl = le_dom_cl_poly.les_conditions_limites(i).valeur();
58
59 if (sub_type(Echange_externe_impose, la_cl))
60 {
61 const Echange_externe_impose& la_cl_int = ref_cast(Echange_externe_impose, la_cl);
62 const Champ_front_base& le_ch_front = ref_cast(Champ_front_base, la_cl_int.h_imp());
63 const DoubleVect& tab = le_ch_front.valeurs();
64 if (tab.size() != 0)
65 {
66 h_imp_temp = local_max_vect(tab); // get h_imp from datafile
67 h_imp_temp = std::fabs(h_imp_temp); // we should take the absolute value since it can be negative!
68 h_imp_max = (h_imp_temp > h_imp_max) ? h_imp_temp : h_imp_max; // Should we take the max if more than one bc has h_imp ?
69 }
70 }
71 } // End loop on boundaries
72 h_imp_max = Process::mp_max(h_imp_max);
73
74 if (alpha_max != 0.0 && nb_elem != 0)
75 {
76 double min_delta_h_carre = le_dom_poly_->carre_pas_du_maillage();
77 if (h_imp_max > 0.0) //a heat flux is imposed on a boundary condition
78 {
79 // get the thermal conductivity
80 const Equation_base& mon_eqn = le_dom_cl_poly.equation();
81 const Milieu_base& mon_milieu = mon_eqn.milieu();
82 const DoubleVect& tab_lambda = mon_milieu.conductivite().valeurs();
83 double max_conductivity = local_max_vect(tab_lambda);
84
85 // compute Biot number given by Bi = L*h/lambda.
86 double Bi = h_imp_max * sqrt(min_delta_h_carre) / max_conductivity;
87 // if Bi>1, replace conductivity by h_imp*h in diffusivity. We are very conservative since h_imp_max is not necessarily located where max_conductivity is.
88 if (Bi > 1.0)
89 alpha_max *= h_imp_max * sqrt(min_delta_h_carre) / max_conductivity;
90 }
91 dt_stab = min_delta_h_carre / (2. * dimension * alpha_max);
92 }
93
94 }
95 else
96 {
97 const int deux_dim = 2 * Objet_U::dimension;
98 const Champ_base& champ_diffu = diffusivite();
99 const DoubleTab& valeurs_diffu = champ_diffu.valeurs();
100 const Champ_base& champ_rho = get_champ_masse_volumique();
101 const DoubleTab& valeurs_rho = champ_rho.valeurs();
102
103 assert(sub_type(Champ_Elem_PolyMAC_CDO, champ_rho));
104 assert(sub_type(Champ_Fonc_P0_base, champ_diffu));
105 // assert(valeurs_rho.size_array()== mon_dom.les_elems().dimension_tot(0));
106 // Champ_Elem_PolyMAC_CDO : champ aux elems et aux faces
107 // Champ de masse volumique variable.
108 const IntTab& e_f = le_dom_poly_->elem_faces();
109 //Cerr << e_f << finl;
110 for (int elem = 0; elem < nb_elem; elem++)
111 {
112 const double diffu = valeurs_diffu(elem);
113 const double rho = valeurs_rho(elem);
114 double dt;
115 bool flag;
116 if (polymac_flica5)
117 {
118 int nb_rf = 0;
119 for (int i = 0; i < e_f.dimension(1); i++)
120 if (e_f(elem, i) != -1)
121 nb_rf++;
122 flag = (nb_rf == deux_dim); // a ameliorer, ca pourrait ne pas etre un hexa regulier...
123 }
124 else
125 flag = (e_f.dimension(1) == deux_dim || e_f(elem, deux_dim) == -1);
126 if (flag)
127 {
128 // Maille type VDF (deux_dim faces sur l'element)
129 // ToDo: coder dans le cas has_champ_masse_volumique()==false
130 double h = 0;
131 for (int f = 0; f < deux_dim; f++)
132 {
133 int face = e_f(elem, f);
134 const double d = le_dom_poly_->volumes(elem) / le_dom_poly_->surface(face);
135 h += 0.5 / (d * d); // On multiplie par 0.5 car face comptee 2 fois
136 //Cerr << elem << " " << face << " " << le_dom_poly_->surface(face) << finl;
137 }
138 // Voir Op_Diff_VDF_Elem_base::calculer_dt_stab():
139 dt = 0.5 * rho / ((diffu + DMINFLOAT) * h);
140 //Cerr << "VDF " << dt << finl;
141 }
142 else
143 {
144 dt = le_dom_poly_->carre_pas_maille(elem) * rho / (deux_dim * (diffu + DMINFLOAT));
145 //Cerr << "NC " << dt << finl;
146 }
147 if (dt < dt_stab)
148 dt_stab = dt;
149 }
150 }
151
152 dt_stab = Process::mp_min(dt_stab);
153 return dt_stab;
154}
155
157{
159 nu_.resize(0, equation().que_suis_je() == "Transport_K_Epsilon" ? 2 : diffusivite().valeurs().line_size());
160 le_dom_poly_->domaine().creer_tableau_elements(nu_);
161 le_dom_poly_->creer_tableau_faces(nu_fac_);
162 nu_a_jour_ = 0;
163}
164
166{
167 if (nu_a_jour_) return; // on a deja fait le travail
168
169 const Domaine_PolyMAC_CDO& domaine = le_dom_poly_.valeur();
170 const Conds_lim& cls = la_zcl_poly_->les_conditions_limites();
171 int i, j, f;
172
173 /* 1. nu_ */
174 //dimensionnement
175 const DoubleTab& diffu = diffusivite().valeurs();
176 if (equation().que_suis_je() != "Transport_K_Epsilon")
177 {
178 if (!diffu.get_md_vector())
179 {
180 // diffusvite uniforme
181 int n = nu_.dimension_tot(0), nb_comp = nu_.line_size();
182 // Tableaux vus comme uni-dimenionnels:
183 const DoubleVect& arr_diffu = diffu;
184 DoubleVect& arr_nu = nu_;
185 for (i = 0; i < n; i++)
186 for (j = 0; j < nb_comp; j++)
187 arr_nu[i * nb_comp + j] = arr_diffu[j];
188 }
189 else
190 {
191 assert(nu_.get_md_vector() == diffu.get_md_vector());
192 assert_espace_virtuel_vect(diffu);
193 nu_.inject_array(diffu);
194 }
195 }
196
197 /* ajout de la diffusivite turbulente si elle existe */
199 {
200 const DoubleTab& diffu_turb = diffusivite_turbulente().valeurs();
201 if (equation().que_suis_je() == "Transport_K_Epsilon")
202 {
203 bool nu_uniforme = sub_type(Champ_Uniforme, diffusivite());
204 double val_nu = diffu(0, 0);
205 for (i = 0; i < diffu_turb.dimension(0); i++)
206 for (j = 0; j < 2; j++)
207 {
208 if (!nu_uniforme)
209 val_nu = diffu(i, 0);
210 nu_(i, j) = val_nu + diffu_turb(i, j);
211 }
212 }
213 else
214 {
215 if (!diffu_turb.get_md_vector())
216 {
217 // diffusvite uniforme
218 int n = nu_.dimension_tot(0), nb_comp = nu_.line_size();
219 // Tableaux vus comme uni-dimenionnels:
220 const DoubleVect& arr_diffu_turb = diffu_turb;
221 DoubleVect& arr_nu = nu_;
222 for (i = 0; i < n; i++)
223 for (j = 0; j < nb_comp; j++)
224 arr_nu[i * nb_comp + j] += arr_diffu_turb[j];
225 }
226 else
227 {
228 assert(nu_.get_md_vector() == diffu_turb.get_md_vector());
229 assert_espace_virtuel_vect(diffu_turb);
230 nu_ += diffu_turb;
231 }
232 }
233 }
234
235 /* 2. nu_fac : prend en compte les lois de parois et le facteur utilisateur (nu_fac_mod) */
236 // utilise-t-on des lois de paroi ?
237 const RefObjU& modele_turbulence = equation().get_modele(TURBULENCE);
238 int loi_par = modele_turbulence && sub_type(Modele_turbulence_scal_base, modele_turbulence.valeur()) &&
239 ref_cast(Modele_turbulence_scal_base,modele_turbulence.valeur()).loi_paroi().use_equivalent_distance();
240
241 for (i = 0; i <= cls.size(); i++) //boucle sur les bords, puis sur les faces internes
242 {
243 int deb = i < cls.size() ? ref_cast(Front_VF, cls[i]->frontiere_dis()).num_premiere_face() : domaine.premiere_face_int(), num =
244 i < cls.size() ? ref_cast(Front_VF, cls[i]->frontiere_dis()).nb_faces() : domaine.nb_faces() - domaine.premiere_face_int();
245 for (f = deb; f < deb + num; f++) //nu par composante a chaque face
246 {
247 if (i < cls.size() && loi_par) //facteur multiplicatif du a une loi de paroi
248 nu_fac_(f) = domaine.dist_norm_bord(f) / ref_cast(Modele_turbulence_scal_base,modele_turbulence.valeur()).loi_paroi().equivalent_distance(i, f - deb);
249 else
250 nu_fac_(f) = equation().milieu().porosite_face(f); //par defaut : facteur du a la porosite
251 if (nu_fac_mod.size())
252 nu_fac_(f) *= nu_fac_mod(f); //prise en compte de nu_fac_mod
253 }
254 }
255 nu_fac_.echange_espace_virtuel();
256 nu_a_jour_ = 1;
257}
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
virtual DoubleTab & valeurs()=0
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
classe Champ_front_base Classe de base pour la hierarchie des champs aux frontieres.
virtual DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ.
classe Cond_lim_base Classe de base pour la hierarchie des classes qui representent les differentes c...
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
int_t nb_elem() const
Definition Domaine.h:131
int nb_cond_lim() const
Renvoie le nombre de conditions aux limites.
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
Classe Echange_externe_impose: Cette classe represente le cas particulier de la classe.
virtual double h_imp(int num) const
Renvoie la valeur du coefficient d'echange de chaleur impose sur la i-eme composante.
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 Milieu_base & milieu() const =0
virtual const RefObjU & get_modele(Type_modele type) const
class Front_VF
Definition Front_VF.h:36
classe Milieu_base Cette classe est la base de la hierarchie des milieux (physiques)
Definition Milieu_base.h:50
virtual const Champ_Don_base & conductivite() const
Renvoie la conductivite du milieu.
DoubleVect & porosite_face()
Definition Milieu_base.h:62
Classe Modele_turbulence_scal_base Cette classe represente un modele de turbulence pour une equation ...
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
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
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
class Op_Diff_PolyMAC_CDO_Gen_base
const Champ_base & diffusivite() const override
double calculer_dt_stab() const override
Calcul dt_stab.
void completer() override
Associe l'operateur au domaine_dis, le domaine_Cl_dis, et a l'inconnue de son equation.
const Champ_Fonc_base & diffusivite_turbulente() const
virtual const Champ_base & diffusivite_pour_pas_de_temps() const
Renvoie le champ_don correspondant a la vraie diffusivite du milieu qui sert pour le calcul du pas de...
virtual void completer()
Associe l'operateur au domaine_dis, le domaine_Cl_dis, et a l'inconnue de son equation.
static double mp_min(double)
Definition Process.cpp:386
static double mp_max(double)
Definition Process.cpp:376
Classe de base des flux de sortie.
Definition Sortie.h:52
virtual const Champ_base & get_champ_masse_volumique() const
Renvoie le champ de masse volumique.
virtual int has_champ_masse_volumique() const
Renvoie 1 si la masse volumique a ete associee, 0 sinon.
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45
virtual const MD_Vector & get_md_vector() const
Definition TRUSTVect.h:123
const Objet_U & valeur() const
Definition TRUST_Ref.h:134