TrioCFD 1.9.8
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 definit si on calcule div(phi nu grad Psi) ou div(nu grap 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 // La diffusivite est constante dans le domaine donc
95 //
96 // dt_diff = h*h/diffusivite
97
98 double dt_stab = DMAXFLOAT;
99 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
101 {
102 // Methode "standard" de calcul du pas de temps
103 // Ce calcul est tres conservatif: si le max de la diffusivite
104 // n'est pas atteint a l'endroit ou le min de delta_h_carre est atteint,
105 // le pas de temps est sous-estime.
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 // Champ de masse volumique variable.
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() pour choix de calcul de dt_stab
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 // Champ de masse volumique variable.
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 // On dimensionne 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
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
Classe Champ_Inc_base.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual DoubleTab & valeurs()=0
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...
virtual void creer_tableau_elements(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
creation d'un tableau parallele de valeurs aux elements.
Definition Domaine.cpp:851
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
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.
class Domaine_VEF
Definition Domaine_VEF.h:54
double carre_pas_du_maillage() const
Definition Domaine_VEF.h:82
const DoubleVect & carre_pas_maille() const
Definition Domaine_VEF.h:83
int nb_faces_bord() const
renvoie le nombre de faces sur lesquelles sont appliquees les conditions limites :
Definition Domaine_VF.h:513
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
int nb_elem_tot() const
const Domaine & domaine() const
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 Champ_Inc_base & inconnue() const =0
const Nom & le_nom() const override
Renvoie le nom du champ.
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.
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par 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
Une chaine de caractere (Nom) en majuscules.
Definition Motcle.h:26
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
static int dimension
Definition Objet_U.h:99
friend class Sortie
Definition Objet_U.h:75
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_VEF_base
int phi_psi_diffuse(const Equation_base &eq) const
definit si on calcule div(phi nu grad Psi) ou div(nu grap 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
Calcul dt_stab.
int impr(Sortie &, const Operateur_base &) const
Impression des flux d'un operateur VEF aux faces (ie: diffusion, convection).
classe Operateur_Diff_base Cette classe est la base de la hierarchie des operateurs representant
virtual const Champ_base & diffusivite() const =0
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...
DoubleTab flux_bords_
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_ 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