TrioCFD 1.9.9_beta
TrioCFD documentation
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 // "Standard" method for computing the time step
43 // This computation is very conservative: if the max of the diffusivity
44 // is not reached at the location where the min of delta_h_carre is reached,
45 // the time step is underestimated.
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: field at elements and faces
107 // Variable density field.
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); // to improve: this could not be a regular hexahedron...
123 }
124 else
125 flag = (e_f.dimension(1) == deux_dim || e_f(elem, deux_dim) == -1);
126 if (flag)
127 {
128 // VDF-type cell (deux_dim faces per element)
129 // ToDo: implement for the case 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); // multiply by 0.5 since each face is counted twice
136 //Cerr << elem << " " << face << " " << le_dom_poly_->surface(face) << finl;
137 }
138 // See 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; // already done
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 //sizing
175 const DoubleTab& diffu = diffusivite().valeurs();
176 if (equation().que_suis_je() != "Transport_K_Epsilon")
177 {
178 if (!diffu.get_md_vector())
179 {
180 // uniform diffusivity
181 int n = nu_.dimension_tot(0), nb_comp = nu_.line_size();
182 // Arrays viewed as one-dimensional:
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 /* add turbulent diffusivity if it exists */
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 // uniform diffusivity
218 int n = nu_.dimension_tot(0), nb_comp = nu_.line_size();
219 // Arrays viewed as one-dimensional:
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: accounts for wall laws and the user factor (nu_fac_mod) */
236 // are wall laws used?
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++) //loop over boundaries, then over internal faces
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 per component at each face
246 {
247 if (i < cls.size() && loi_par) //multiplicative factor due to a wall law
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); //default: factor due to porosity
251 if (nu_fac_mod.size())
252 nu_fac_(f) *= nu_fac_mod(f); //account for nu_fac_mod
253 }
254 }
255 nu_fac_.echange_espace_virtuel();
256 nu_a_jour_ = 1;
257}
DoubleTab & valeurs() override
Overrides Champ_base::valeurs() Returns the array of values.
virtual DoubleTab & valeurs()=0
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_front_base Base class for the hierarchy of boundary fields.
virtual DoubleTab & valeurs() override
Returns the array of field values.
class Cond_lim_base Base class for the hierarchy of classes that represent the different boundary con...
class Conds_lim This class represents a vector of boundary conditions.
Definition Conds_lim.h:32
int_t nb_elem() const
Definition Domaine.h:131
int nb_cond_lim() const
Returns the number of boundary conditions.
const Cond_lim & les_conditions_limites(int) const
Returns the i-th boundary condition.
Classe Echange_externe_impose: This class represents the special case of the class.
virtual double h_imp(int num) const
Returns the value of the imposed heat exchange coefficient on the i-th component.
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 Milieu_base & milieu() const =0
virtual const RefObjU & get_modele(Type_modele type) const
class Front_VF
Definition Front_VF.h:36
Milieu_base This class is the base of the (physical) medium hierarchy.
Definition Milieu_base.h:50
virtual const Champ_Don_base & conductivite() const
Returns the conductivity of the medium (const version).
DoubleVect & porosite_face()
Definition Milieu_base.h:62
Base class for scalar turbulence models coupled to a Navier-Stokes convection-diffusion equation.
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
static int dimension
Definition Objet_U.h:94
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
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
class Op_Diff_PolyMAC_CDO_Gen_base
const Champ_base & diffusivite() const override
double calculer_dt_stab() const override
Computes dt_stab.
void completer() override
Associates the operator with the domaine_dis, the domaine_Cl_dis, and the unknown of its equation.
const Champ_Fonc_base & diffusivite_turbulente() const
virtual const Champ_base & diffusivite_pour_pas_de_temps() const
Returns the field corresponding to the true diffusivity of the medium used for the time step computat...
virtual void completer()
Associates the operator with the domaine_dis, the domaine_Cl_dis, and the unknown of its equation.
static double mp_min(double)
Definition Process.cpp:391
static double mp_max(double)
Definition Process.cpp:379
Base class for output streams.
Definition Sortie.h:52
virtual const Champ_base & get_champ_masse_volumique() const
Returns the density field.
virtual int has_champ_masse_volumique() const
Returns 1 if the density field has been associated, 0 otherwise.
_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