TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Diff_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 <Op_Diff_VEF_base.h>
17#include <Champ_P1NC.h>
18#include <Champ_Q1NC.h>
19#include <Champ_Uniforme.h>
20#include <Milieu_base.h>
21#include <Probleme_base.h>
22#include <Schema_Temps_base.h>
23#include <Champ_Fonc_P0_base.h>
24#include <Discretisation_base.h>
25#include <Check_espace_virtuel.h>
26#include <Echange_externe_impose.h>
27
28Implemente_base(Op_Diff_VEF_base,"Op_Diff_VEF_base",Operateur_Diff_base);
29
31{
32 return s << que_suis_je() ;
33}
34
36{
37 return s ;
38}
39
40
41/*! @brief Determine whether to compute div(phi nu grad Psi) or div(nu grad Phi psi).
42 *
43 */
45{
46 if (eq.inconnue().le_nom()=="vitesse")
47 return 1;
48 return 0;
49}
50
52{
53 return Op_VEF_Face::impr(os, *this);
54}
55
57 const Domaine_Cl_dis_base& domaine_cl_dis,
58 const Champ_Inc_base& ch_transporte)
59{
60
61 const Domaine_VEF& zvef = ref_cast(Domaine_VEF,domaine_dis);
62 const Domaine_Cl_VEF& zclvef = ref_cast(Domaine_Cl_VEF,domaine_cl_dis);
63
64 if (sub_type(Champ_P1NC,ch_transporte))
65 {
66 const Champ_P1NC& inco = ref_cast(Champ_P1NC,ch_transporte);
67 OBS_PTR(Champ_P1NC) inconnue;
68 inconnue = inco;
69 }
70 if (sub_type(Champ_Q1NC,ch_transporte))
71 {
72 const Champ_Q1NC& inco = ref_cast(Champ_Q1NC,ch_transporte);
73 OBS_PTR(Champ_Q1NC) inconnue;
74 inconnue = inco;
75 }
76
77 le_dom_vef = zvef;
78 la_zcl_vef = zclvef;
79
80
81 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
82 int nb_dim = ch_transporte.valeurs().nb_dim();
83 int nb_comp = 1;
84
85 if(nb_dim==2)
86 nb_comp = ch_transporte.valeurs().dimension(1);
87
88 flux_bords_.resize(domaine_VEF.nb_faces_bord(), nb_comp);
89 flux_bords_ = 0.;
90}
92{
94 // The diffusivity is constant in the domain, hence
95 //
96 // dt_diff = h*h/diffusivity
97
98 double dt_stab = DMAXFLOAT;
99 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
101 {
102 // "Standard" method for time step computation.
103 // This computation is very conservative: if the diffusivity maximum
104 // is not reached at the location where the minimum of delta_h_squared is reached,
105 // the time step is underestimated.
106 const Champ_base& champ_diffusivite = diffusivite_pour_pas_de_temps();
107 const DoubleVect& valeurs_diffusivite = champ_diffusivite.valeurs();
108 double alpha_max = local_max_vect(valeurs_diffusivite);
109
110 // Detect if a heat flux is imposed on a boundary through Paroi_echange_externe_impose keyword
111 double h_imp_max = -1, h_imp_temp=-2, max_conductivity = 0;
112 const Domaine_Cl_VEF& le_dom_cl_vef = la_zcl_vef.valeur();
113 const Equation_base& mon_eqn = le_dom_cl_vef.equation();
114
115 for(int i=0; i<le_dom_cl_vef.nb_cond_lim(); i++)
116 {
117 // loop on boundaries
118 const Cond_lim_base& la_cl = le_dom_cl_vef.les_conditions_limites(i).valeur();
119 if (sub_type(Echange_externe_impose,la_cl))
120 {
121 const Echange_externe_impose& la_cl_int = ref_cast(Echange_externe_impose,la_cl);
122 const Champ_front_base& le_ch_front = ref_cast( Champ_front_base, la_cl_int.h_imp());
123 const DoubleVect& tab = le_ch_front.valeurs();
124 if(tab.size() > 0)
125 {
126 h_imp_temp = local_max_vect(tab); // get h_imp from datafile
127 h_imp_temp = std::fabs(h_imp_temp); // we should take the absolute value since it can be negative!
128 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 ?
129 }
130 }
131 } // End loop on boundaries
132
133 h_imp_max = Process::mp_max(h_imp_max);
134
135 if ((alpha_max == 0.)||(domaine_VEF.nb_elem()==0))
136 dt_stab = DMAXFLOAT;
137 else
138 {
139 const double min_delta_h_carre = domaine_VEF.carre_pas_du_maillage();
140 if (h_imp_max>0.0) //we have a BC with Paroi_echange_externe_impose
141 {
142 // get the thermal conductivity
143 const Milieu_base& mon_milieu = mon_eqn.milieu();
144 const DoubleVect& tab_lambda = mon_milieu.conductivite().valeurs();
145 max_conductivity = local_max_vect(tab_lambda);
146 // compute Biot number given by Bi = L*h/lambda.
147 double Bi = h_imp_max*sqrt(min_delta_h_carre)/max_conductivity;
148 // 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.
149 if (Bi>1.0)
150 alpha_max *= h_imp_max*sqrt(min_delta_h_carre)/max_conductivity;
151 }
152 dt_stab = min_delta_h_carre / (2. * dimension * alpha_max);
153 }
154 }
155 else
156 {
157 // Variable mass density field.
158 const double deux_dim = 2. * Objet_U::dimension;
159 const Champ_base& champ_diffu = diffusivite();
160 const Champ_base& champ_rho = get_champ_masse_volumique();
161 assert(sub_type(Champ_Fonc_P0_base, champ_rho));
162 assert(sub_type(Champ_Fonc_P0_base, champ_diffu));
163 const int nb_elem = domaine_VEF.nb_elem();
164 CDoubleArrView carre_pas_maille = domaine_VEF.carre_pas_maille().view_ro();
165 CDoubleArrView valeurs_diffu = static_cast<const DoubleVect&>(champ_diffu.valeurs()).view_ro();
166 CDoubleArrView valeurs_rho = static_cast<const DoubleVect&>(champ_rho.valeurs()).view_ro();
167 Kokkos::parallel_reduce(start_gpu_timer(__KERNEL_NAME__),
168 range_1D(0, nb_elem), KOKKOS_LAMBDA(
169 const int elem, double& dtstab)
170 {
171 const double h_carre = carre_pas_maille(elem);
172 const double diffu = valeurs_diffu(elem);
173 const double rho = valeurs_rho(elem);
174 const double dt = h_carre * rho / (deux_dim * (diffu+DMINFLOAT));
175 if (dt < dtstab) dtstab = dt;
176 }, Kokkos::Min<double>(dt_stab));
177 end_gpu_timer(__KERNEL_NAME__);
178 }
179 dt_stab = Process::mp_min(dt_stab);
180 return dt_stab;
181}
182
183// cf Op_Diff_VEF_base::calculer_dt_stab() for the choice of dt_stab computation
184void Op_Diff_VEF_base::calculer_pour_post(Champ_base& espace_stockage,const Nom& option,int comp) const
185{
186 if (Motcle(option)=="stabilite")
187 {
188 DoubleTab& es_valeurs = espace_stockage.valeurs();
189
190 if (le_dom_vef)
191 {
193 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
195 {
196
197 const Champ_base& champ_diffusivite = diffusivite_pour_pas_de_temps();
198 const DoubleVect& valeurs_diffusivite = champ_diffusivite.valeurs();
199 double alpha_max = local_max_vect(valeurs_diffusivite);
200
201 if ((alpha_max == 0.)||(domaine_VEF.nb_elem()==0))
202 es_valeurs = DMAXFLOAT;
203 else
204 {
205 const int nb_elem = domaine_VEF.nb_elem();
206 for (int elem = 0; elem < nb_elem; elem++)
207 {
208 es_valeurs(elem) = domaine_VEF.carre_pas_maille()(elem) / (2. * dimension * alpha_max);
209 }
210 }
211 }
212 else
213 {
214 const double deux_dim = 2. * Objet_U::dimension;
215 const Champ_base& champ_diffu = diffusivite();
216 const DoubleTab& valeurs_diffu = champ_diffu.valeurs();
217 const Champ_base& champ_rho = get_champ_masse_volumique();
218 const DoubleTab& valeurs_rho = champ_rho.valeurs();
219 assert(sub_type(Champ_Fonc_P0_base, champ_rho));
220 assert(sub_type(Champ_Fonc_P0_base, champ_diffu));
221 const int nb_elem = domaine_VEF.nb_elem();
222 assert(valeurs_rho.size_array()==domaine_VEF.nb_elem_tot());
223 // Variable mass density field.
224 for (int elem = 0; elem < nb_elem; elem++)
225 {
226 const double h_carre = domaine_VEF.carre_pas_maille()(elem);
227 const double diffu = valeurs_diffu(elem);
228 const double rho = valeurs_rho(elem);
229 const double dt = h_carre * rho / (deux_dim * diffu);
230 es_valeurs(elem) = dt;
231 }
232 }
233
234 assert(mp_min_vect(es_valeurs)==calculer_dt_stab());
235 }
236 }
237 else
239}
240
242{
243 Motcle loc;
244 if (Motcle(option)=="stabilite")
245 loc = "elem";
246 else
248 return loc;
249}
250
251void Op_Diff_VEF_base::remplir_nu(DoubleTab& tab_nu) const
252{
253 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
254 // Size/initialize nu
255 const DoubleTab& tab_diffu = diffusivite().valeurs();
256 if (!tab_nu.get_md_vector())
257 {
258 tab_nu.resize(0, tab_diffu.line_size());
259 domaine_VEF.domaine().creer_tableau_elements(tab_nu, RESIZE_OPTIONS::NOCOPY_NOINIT);
260 }
261 if (!tab_diffu.get_md_vector())
262 {
263 // diffusivite uniforme
264 const int n = tab_nu.dimension_tot(0);
265 const int nb_comp = tab_nu.line_size();
266 CDoubleArrView diffu = static_cast<const DoubleVect&>(tab_diffu).view_ro();
267 DoubleTabView nu = tab_nu.view_rw();
268 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__),
269 range_2D({0, 0}, {n, nb_comp}),
270 KOKKOS_LAMBDA(const int i, const int j)
271 {
272 nu(i, j) = diffu(j);
273 });
274 end_gpu_timer(__KERNEL_NAME__);
275 }
276 else
277 {
278 assert(tab_nu.get_md_vector() == tab_diffu.get_md_vector());
279 assert_espace_virtuel_vect(tab_diffu);
280 // Sync arrays on the device before copy:
281 mapToDevice(tab_diffu);
282 computeOnTheDevice(tab_nu);
283 tab_nu.inject_array(tab_diffu);
284 }
285}
DoubleTab & valeurs() override
Overrides Champ_base::valeurs() Returns the array of values.
Class Champ_Inc_base.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
virtual DoubleTab & valeurs()=0
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...
virtual void creer_tableau_elements(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
Creates a parallel array of values at elements.
Definition Domaine.cpp:850
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
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.
class Domaine_VEF
Definition Domaine_VEF.h:53
double carre_pas_du_maillage() const
Definition Domaine_VEF.h:81
const DoubleVect & carre_pas_maille() const
Definition Domaine_VEF.h:82
int nb_faces_bord() const
Returns the number of faces on which boundary conditions are applied:
Definition Domaine_VF.h:512
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
int nb_elem_tot() const
const Domaine & domaine() const
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 Champ_Inc_base & inconnue() const =0
const Nom & le_nom() const override
Returns the name of the field.
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).
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
virtual Motcle get_localisation_pour_post(const Nom &option) const
Definition MorEqn.cpp:43
virtual void calculer_pour_post(Champ_base &espace_stockage, const Nom &option, int comp) const
Definition MorEqn.cpp:35
A character string (Nom) in uppercase.
Definition Motcle.h:26
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
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
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
class Op_Diff_VEF_base
int phi_psi_diffuse(const Equation_base &eq) const
Determine whether to compute div(phi nu grad Psi) or div(nu grad Phi psi).
void calculer_pour_post(Champ_base &espace_stockage, const Nom &option, int comp) const override
Motcle get_localisation_pour_post(const Nom &option) const override
OBS_PTR(Domaine_VEF) le_dom_vef
int impr(Sortie &os) const override
DOES NOTHING - to override in derived classes.
void associer(const Domaine_dis_base &, const Domaine_Cl_dis_base &, const Champ_Inc_base &) override
virtual void remplir_nu(DoubleTab &) const
double calculer_dt_stab() const override
Computes dt_stab.
int impr(Sortie &, const Operateur_base &) const
Print the face fluxes of a VEF operator (e.g. diffusion, convection).
Operateur_Diff_base This class is the base of the hierarchy of operators representing.
virtual const Champ_base & diffusivite() const =0
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...
DoubleTab flux_bords_
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_ size_array() const
TRUSTArray & inject_array(const TRUSTArray &source, _SIZE_ nb_elements=-1, _SIZE_ first_element_dest=0, _SIZE_ first_element_source=0)
int nb_dim() const
Definition TRUSTTab.h:199
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, View< _TYPE_, _SHAPE_ > > view_rw()
Definition TRUSTTab.h:291
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45
int line_size() const
Definition TRUSTVect.tpp:67
virtual const MD_Vector & get_md_vector() const
Definition TRUSTVect.h:123