TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Dift_VEF_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 <Modele_turbulence_hyd_base.h>
18#include <Navier_Stokes_std.h>
19#include <Op_Dift_VEF_base.h>
20#include <Domaine_Cl_VEF.h>
21
22
23Implemente_base(Op_Dift_VEF_base, "Op_Dift_VEF_base", Op_Diff_VEF_base);
24
26
28
30{
31 le_modele_turbulence = mod;
32}
33
35{
36 if (sub_type(Navier_Stokes_std, equation())) // process the hydraulics equation
37 {
38 if (le_modele_turbulence->utiliser_loi_paroi())
39 {
40 // BM: only take the reference if the array has been initialised, otherwise it blocks initialisation
41 const DoubleTab& tab = le_modele_turbulence->loi_paroi().Cisaillement_paroi();
42 if (tab.size_array() > 0) tau_tan_.ref(tab);
43 }
44 }
45}
46
47void Op_Dift_VEF_base::associer(const Domaine_dis_base& domaine_dis, const Domaine_Cl_dis_base& domaine_cl_dis, const Champ_Inc_base& ch_transporte)
48{
49 le_dom_vef = ref_cast(Domaine_VEF, domaine_dis);
50 la_zcl_vef = ref_cast(Domaine_Cl_VEF, domaine_cl_dis);
51 inconnue_ = ch_transporte;
52}
53
55{
57
58 const RefObjU& modele_turbulence = equation().get_modele(TURBULENCE);
59 if (modele_turbulence && sub_type(Modele_turbulence_hyd_base, modele_turbulence.valeur()))
60 {
61 const Modele_turbulence_hyd_base& mod_turb = ref_cast(Modele_turbulence_hyd_base, modele_turbulence.valeur());
62 const Champ_Fonc_base& viscosite_turbulente = mod_turb.viscosite_turbulente();
63 associer_diffusivite_turbulente(viscosite_turbulente);
65 }
66 else if (sub_type(Modele_turbulence_scal_base, modele_turbulence.valeur()))
67 {
68 const Modele_turbulence_scal_base& modele_turbulence_scalaire = ref_cast(Modele_turbulence_scal_base, modele_turbulence.valeur());
69 const Champ_Fonc_base& conductivite_turbulente = modele_turbulence_scalaire.conductivite_turbulente();
70 associer_diffusivite_turbulente(conductivite_turbulente);
71 }
72 else
73 {
74 Cerr << "Error in Op_Dift_VEF_base::completer() " << finl;
75 Cerr << que_suis_je() << " operator is presently associated to " << equation().que_suis_je() << finl;
76 Cerr << "instead of being associated to an equation dedicated to a turbulent flow." << finl;
78 }
79}
80
81void Op_Dift_VEF_base::calculer_borne_locale(DoubleVect& tab_borne_visco_turb, double dt_conv, double dt_diff_sur_dt_conv) const
82{
83 const Domaine_VEF& le_dom_VEF = domaine_vef();
84 int nb_elem = le_dom_VEF.nb_elem();
85 int flag = diffusivite().valeurs().dimension(0) > 1 ? 1 : 0;
86 const double dim = Objet_U::dimension;
87 CDoubleTabView diffu = diffusivite().valeurs().view_ro();
88 CDoubleArrView carre_pas_maille = le_dom_VEF.carre_pas_maille().view_ro();
89 DoubleArrView borne_visco_turb = tab_borne_visco_turb.view_rw();
90 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_elem, KOKKOS_LAMBDA(const int elem)
91 {
92 double h_inv = 1. / carre_pas_maille(elem);
93 // Not the cleanest way to retrieve diffu, but avoids code duplication across multiple classes:
94 double diffu_elem = (flag ? diffu(elem, 0) : diffu(0, 0));
95 double coef = 1. / (2 * (dt_conv + DMINFLOAT) * dim * h_inv * dt_diff_sur_dt_conv) - diffu_elem;
96 if (coef > 0 && coef < borne_visco_turb(elem))
97 borne_visco_turb(elem) = coef;
98 });
99 end_gpu_timer(__KERNEL_NAME__);
100}
101
102// The diffusivity is constant per element, so dt_diff must be computed per element: dt_stab=Min(dt_diff(K) = h(K)*h(K)/(2*dimension*diffu2_(K)))
103// where diffu2_ is the sum of the laminar and turbulent diffusivities.
104
105//GF: alpha_dt_stab=(alpha+alpha_t)*alpha_dt_stab/alpha AND alpha_dt_stab=(nu+diff_nu_turb)*valeurs_diffusivite_dt/nu
107{
108 remplir_nu(nu_); // Fill nu with the diffusivity at each element
109
110 //DoubleVect tab_diffu_turb(diffusivite_turbulente().valeurs());
111 DoubleTrav tab_diffu_turb;
112 tab_diffu_turb = diffusivite_turbulente().valeurs();
113 DoubleTrav tab_diffu;
114 tab_diffu = nu_; // XXX: Elie Saikali: Warning - not the same as DoubleTrav diffu(nu_) !!!!!!!!!
115
116 if (equation().que_suis_je().debute_par("Convection_Diffusion_Temp"))
117 {
118 double rhocp = mon_equation->domaine_dis().nb_elem() > 0 ? mon_equation->milieu().capacite_calorifique().valeurs()(0, 0) * mon_equation->milieu().masse_volumique().valeurs()(0, 0) : 1.0;
119 tab_diffu_turb /= rhocp;
120 tab_diffu /= rhocp;
121 }
122
123 const double deux_dim = 2. * Objet_U::dimension;
124 const Domaine_VEF& le_dom_VEF = domaine_vef();
125 const int le_dom_nb_elem = le_dom_VEF.domaine().nb_elem();
126 double dt_stab = 1.e30;
127 CDoubleTabView diffu = tab_diffu.view_ro();
128 CDoubleArrView diffu_turb = static_cast<const DoubleVect&>(tab_diffu_turb).view_ro();
129 CDoubleArrView carre_pas_maille = le_dom_VEF.carre_pas_maille().view_ro();
131 {
132 const DoubleTab& tab_rho_elem = get_champ_masse_volumique().valeurs();
133 assert(tab_rho_elem.size_array() == le_dom_VEF.nb_elem_tot());
134 CDoubleArrView rho_elem = static_cast<const DoubleVect&>(tab_rho_elem).view_ro();
135 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__),
136 Kokkos::RangePolicy<>(0, le_dom_nb_elem), KOKKOS_LAMBDA(
137 const int num_elem, double& dtstab)
138 {
139 double alpha = diffu(num_elem, 0) + diffu_turb(num_elem); // PQ : 06/03
140 alpha /= rho_elem(num_elem);
141 double coef = carre_pas_maille(num_elem) / (deux_dim * (alpha + DMINFLOAT));
142 if (coef < dtstab) dtstab = coef;
143 }, Kokkos::Min<double>(dt_stab));
144 }
145 else
146 {
147 const DoubleTab& tab_valeurs_diffusivite = diffusivite_pour_pas_de_temps().valeurs();
148 const int nb_comp = tab_valeurs_diffusivite.line_size(), cD = (tab_valeurs_diffusivite.dimension(0) == 1); // uniform or not?
149 CDoubleTabView valeurs_diffusivite = tab_valeurs_diffusivite.view_ro();
150 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__),
151 Kokkos::RangePolicy<>(0, le_dom_nb_elem), KOKKOS_LAMBDA(
152 const int num_elem, double& dtstab)
153 {
154 for (int nc = 0; nc < nb_comp; nc++)
155 {
156 double alpha = diffu(num_elem, nc) + diffu_turb(num_elem);
157 const double valeurs_diffusivite_dt = valeurs_diffusivite(!cD * num_elem, nc);
158 alpha *= valeurs_diffusivite_dt / (diffu(num_elem, nc) + DMINFLOAT);
159 double coef = carre_pas_maille(num_elem) / (deux_dim * (alpha + DMINFLOAT));
160 if (coef < dtstab) dtstab = coef;
161 }
162 }, Kokkos::Min<double>(dt_stab));
163 }
164 end_gpu_timer(__KERNEL_NAME__);
165 dt_stab = Process::mp_min(dt_stab);
166 return dt_stab;
167}
168
169// See Op_Dift_VEF_Face::calculer_dt_stab() for the dt_stab computation strategy
170void Op_Dift_VEF_base::calculer_pour_post(Champ_base& espace_stockage, const Nom& option, int comp) const
171{
172 if (Motcle(option) == "stabilite")
173 {
174 DoubleTab& es_valeurs = espace_stockage.valeurs();
175
176 if (le_dom_vef)
177 {
178 remplir_nu(nu_); // Fill nu with the diffusivity at each element
179
180 const Domaine_VEF& le_dom_VEF = domaine_vef();
181 const Domaine& le_dom = le_dom_VEF.domaine();
182 const DoubleVect& diffu_turb = diffusivite_turbulente().valeurs();
183 double alpha = -123., coef = -123.;
184 ToDo_Kokkos("critical");
185
186 int le_dom_nb_elem = le_dom.nb_elem();
188 {
189 const DoubleTab& rho_elem = get_champ_masse_volumique().valeurs();
190 assert(rho_elem.size_array() == le_dom_VEF.nb_elem_tot());
191 for (int num_elem = 0; num_elem < le_dom_nb_elem; num_elem++)
192 {
193 alpha = nu_[num_elem] + diffu_turb[num_elem]; // PQ : 06/03
194 alpha /= rho_elem[num_elem];
195 coef = le_dom_VEF.carre_pas_maille()(num_elem) / (2. * dimension * alpha);
196 es_valeurs(num_elem) = coef;
197 }
198 }
199 else
200 {
201 const Champ_base& champ_diffusivite = diffusivite_pour_pas_de_temps();
202 const DoubleTab& valeurs_diffusivite = champ_diffusivite.valeurs();
203 const int cD = (valeurs_diffusivite.dimension(0) == 1); // uniform or not?
204 for (int num_elem = 0; num_elem < le_dom_nb_elem; num_elem++)
205 {
206 const double valeurs_diffusivite_dt = valeurs_diffusivite(!cD * num_elem);
207 alpha = nu_[num_elem] + diffu_turb[num_elem]; // PQ : 06/03
208 alpha *= valeurs_diffusivite_dt / nu_[num_elem];
209 coef = le_dom_VEF.carre_pas_maille()(num_elem) / (2. * dimension * alpha);
210 es_valeurs(num_elem) = coef;
211 }
212 }
213
214 assert(est_egal(mp_min_vect(es_valeurs), calculer_dt_stab()));
215 }
216 }
217 else
218 Op_Diff_VEF_base::calculer_pour_post(espace_stockage, option, comp);
219}
220
221// The diffusivity is constant per element, so dt_diff must be computed per element: dt_stab=Min(dt_diff(K) = h(K)*h(K)/(2*dimension*diffu2_(K)))
222// where diffu2_ is the sum of the laminar and turbulent diffusivities.
224{
225 const Domaine_VEF& domaine_VEF = domaine_vef();
226 const IntTab& elem_faces = domaine_VEF.elem_faces();
227 const DoubleTab& face_normales = domaine_VEF.face_normales();
228 const DoubleVect& volumes = domaine_VEF.volumes(), &diffu_turb = diffusivite_turbulente().valeurs();
229 const int nb_faces_elem = domaine_VEF.domaine().nb_faces_elem(), le_dom_nb_elem = domaine_VEF.domaine().nb_elem();
230
231 const double diffu = diffusivite(0);
232 double dt_stab = 1.e30, coef, diffu2_;
233 ToDo_Kokkos("critical");
234
235 for (int num_elem = 0; num_elem < le_dom_nb_elem; num_elem++)
236 {
237 double surf_max = 1.e-30;
238 for (int i = 0; i < nb_faces_elem; i++)
239 {
240 const int num_face = elem_faces(num_elem, i);
241 double surf = face_normales(num_face, 0) * face_normales(num_face, 0);
242 for (int j = 1; j < dimension; j++)
243 surf += face_normales(num_face, j) * face_normales(num_face, j);
244 surf_max = (surf > surf_max) ? surf : surf_max;
245 }
246 double vol = volumes(num_elem);
247 vol *= vol / surf_max;
248 diffu2_ = diffu + diffu_turb[num_elem];
249 coef = vol / (2. * dimension * (diffu2_ + DMINFLOAT));
250 dt_stab = (coef < dt_stab) ? coef : dt_stab;
251 }
252
253 return Process::mp_min(dt_stab);
254}
DoubleTab & valeurs() override
Overrides Champ_base::valeurs() Returns the array of values.
class Champ_Fonc_base Base class of fields that are functions of a calculated quantity
Class Champ_Inc_base.
virtual DoubleTab & valeurs()=0
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
int_t nb_elem() const
Definition Domaine.h:131
int nb_faces_elem(int=0) const
Returns the number of faces of type i of the geometric elements that make up the domain.
Definition Domaine.h:484
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
class Domaine_VEF
Definition Domaine_VEF.h:53
const DoubleVect & carre_pas_maille() const
Definition Domaine_VEF.h:82
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
double volumes(int i) const
Definition Domaine_VF.h:113
int elem_faces(int i, int j) const
Returns the index of the i-th face of element num_elem; the face numbering convention is.
Definition Domaine_VF.h:542
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
int nb_elem_tot() const
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const RefObjU & get_modele(Type_modele type) const
Base class for the turbulence model hierarchy for Navier-Stokes equations.
const Champ_Fonc_base & viscosite_turbulente() const
Base class for scalar turbulence models coupled to a Navier-Stokes convection-diffusion equation.
const Champ_Fonc_base & conductivite_turbulente() const
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
A character string (Nom) in uppercase.
Definition Motcle.h:26
Navier_Stokes_std This class carries the terms of the momentum equation.
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
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
const Champ_Fonc_base & diffusivite_turbulente() const
void associer_diffusivite_turbulente(const Champ_Fonc_base &)
class Op_Diff_VEF_base
void calculer_pour_post(Champ_base &espace_stockage, const Nom &option, int comp) const override
virtual void remplir_nu(DoubleTab &) const
const Domaine_VEF & domaine_vef() const
void associer(const Domaine_dis_base &, const Domaine_Cl_dis_base &, const Champ_Inc_base &) override
void mettre_a_jour(double temps) override
DOES NOTHING - to override in derived classes.
void completer() override
Associates the operator with the domaine_dis, the domaine_Cl_dis, and the unknown of its equation.
const Champ_base & diffusivite() const override
void calculer_borne_locale(DoubleVect &, double, double) const override
double calculer_dt_stab() const override
Computes dt_stab.
double calculer_dt_stab_P1NCP1B() const
void associer_modele_turbulence(const Modele_turbulence_hyd_base &)
void calculer_pour_post(Champ_base &espace_stockage, const Nom &option, int comp) const override
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 void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
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_ size_array() const
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, ConstView< _TYPE_, _SHAPE_ > > view_ro() const
Definition TRUSTTab.h:261
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
int line_size() const
Definition TRUSTVect.tpp:67
const Objet_U & valeur() const
Definition TRUST_Ref.h:134