TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Conv_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_Conv_VEF_base.h>
17
18#include <Milieu_base.h>
19#include <Schema_Temps_base.h>
20#include <Probleme_base.h>
21#include <TRUSTTrav.h>
22#include <Discretisation_base.h>
23
24#include <Modifier_pour_fluide_dilatable.h>
25#include <Dirichlet_homogene.h>
26#include <Periodique.h>
27
28Implemente_base(Op_Conv_VEF_base,"Op_Conv_VEF_base",Operateur_Conv_base);
29
31{
32 return s << que_suis_je() ;
33}
34
36{
37 return s ;
38}
39
40
41/*! @brief definit si l'on convecte psi avec phi*u ou avec u
42 *
43 */
45{
46 if (eq.inconnue().le_nom()=="vitesse")
47 return 0;
48 return 1;
49}
50
51
53{
54 vitesse_ = ref_cast(Champ_Inc_base,vit);
55}
56
57
62
64{
65 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
66 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
68 if (vitesse().le_nom()=="rho_u" && equation().probleme().is_dilatable())
69 diviser_par_rho_si_dilatable(fluent_,equation().milieu());
70
71 // Remplissage de faces_entrelaces_Cl_ qui contient les faces
72 // de bord non Dirichlet et les faces internes non std pour
73 // lequelles on utilise le volumes_entrelaces_Cl
74 // Ce tableau temporaire a ete cree pour fusionner plusieurs
75 // kernels Kokkos en un seul
76 if (faces_entrelaces_Cl_.size_array()==0)
77 {
78 faces_entrelaces_Cl_.resize(domaine_VEF.premiere_face_std());
79 int ind_face=-1;
80 // On traite les conditions aux limites
81 // Si une face porte une condition de Dirichlet on n'en tient pas compte
82 // dans le calcul de dt_stab
83 for (int n_bord = 0; n_bord < domaine_VEF.nb_front_Cl(); n_bord++)
84 {
85 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
86 if (!sub_type(Dirichlet, la_cl.valeur()) && !sub_type(Dirichlet_homogene, la_cl.valeur()))
87 {
88 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
89 int ndeb = le_bord.num_premiere_face();
90 int nfin = ndeb + le_bord.nb_faces();
91 for (int num_face = ndeb; num_face < nfin; num_face++)
92 faces_entrelaces_Cl_(++ind_face) = num_face;
93 }
94 }
95 // Faces internes non std:
96 int ndeb = domaine_VEF.premiere_face_int();
97 int nfin = domaine_VEF.premiere_face_std();
98 for (int num_face = ndeb; num_face < nfin; num_face++)
99 faces_entrelaces_Cl_(++ind_face) = num_face;
100 faces_entrelaces_Cl_.resize(ind_face+1);
101 }
102
103 double dt_stab = 1.e30;
104 CIntArrView faces_entrelaces_Cl = faces_entrelaces_Cl_.view_ro();
105 CDoubleArrView fluent = fluent_.view_ro();
106 CDoubleArrView volumes_entrelaces_Cl = domaine_Cl_VEF.volumes_entrelaces_Cl().view_ro();
107 start_gpu_timer(__KERNEL_NAME__);
108 Kokkos::parallel_reduce(__KERNEL_NAME__,
109 range_1D(0, faces_entrelaces_Cl_.size_array()),
110 KOKKOS_LAMBDA(const int ind_face, double& dtstab)
111 {
112 int num_face = faces_entrelaces_Cl(ind_face);
113 double dt_face = volumes_entrelaces_Cl(num_face)/(fluent(num_face)+DMINFLOAT);
114 if (dt_face < dtstab) dtstab = dt_face;
115 }, Kokkos::Min<double>(dt_stab));
116 end_gpu_timer(__KERNEL_NAME__);
117
118 // On traite les faces internes standard
119 int ndeb = domaine_VEF.premiere_face_std();
120 int nfin = domaine_VEF.nb_faces();
121
122 const DoubleVect& tab_volumes_entrelaces = domaine_VEF.volumes_entrelaces();
123 CDoubleArrView volumes_entrelaces = tab_volumes_entrelaces.view_ro();
124 // Necessaire car Kokkos::parallel_reduce() reecrit dt_stab avec le
125 // resultat de la reduction quelle que soit la valeur de depart (en
126 // particulier, celle d'une reduction precedente, comme ici).
127 double dt_stab_2 = dt_stab;
128 Kokkos::parallel_reduce(
129 start_gpu_timer(__KERNEL_NAME__),
130 range_1D(ndeb, nfin),
131 KOKKOS_LAMBDA(const int num_face, double& dtstab)
132 {
133 double dt_face = volumes_entrelaces(num_face) / (fluent(num_face) + DMINFLOAT);
134 if (dt_face < dtstab) dtstab = dt_face;
135 }, Kokkos::Min<double>(dt_stab_2));
136 end_gpu_timer(__KERNEL_NAME__);
137 if (dt_stab_2 < dt_stab) dt_stab = dt_stab_2;
138
139 // Min sur l'ensemble des processeurs
140 dt_stab = Process::mp_min(dt_stab);
141 // astuce pour contourner le type const de la methode
142 Op_Conv_VEF_base& op = ref_cast_non_const(Op_Conv_VEF_base,*this);
143 op.fixer_dt_stab_conv(dt_stab);
144 if (vitesse().le_nom()=="rho_u" && equation().probleme().is_dilatable())
145 multiplier_par_rho_si_dilatable(fluent_,equation().milieu());
146
147 return dt_stab;
148}
149
150// cf Op_Conv_VEF_base::calculer_dt_stab() pour choix de calcul de dt_stab
151void Op_Conv_VEF_base::calculer_pour_post(Champ_base& espace_stockage,const Nom& option,int comp) const
152{
153 if (Motcle(option)=="stabilite")
154 {
155 DoubleTab& es_valeurs = espace_stockage.valeurs();
156 es_valeurs = 1.e30;
157
158 if ((bool(le_dom_vef)) && (bool(la_zcl_vef)))
159 {
160 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
161 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
162 const DoubleVect& volumes_entrelaces = domaine_VEF.volumes_entrelaces();
163 const DoubleVect& volumes_entrelaces_Cl = domaine_Cl_VEF.volumes_entrelaces_Cl();
164 double dt_face;
166 if (vitesse().le_nom()=="rho_u" && equation().probleme().is_dilatable())
167 diviser_par_rho_si_dilatable(fluent_,equation().milieu());
168
169 // On traite les conditions aux limites
170 // Si une face porte une condition de Dirichlet on n'en tient pas compte
171 // dans le calcul de dt_stab
172 for (int n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
173 {
174 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
175 if ((sub_type(Dirichlet, la_cl.valeur())) || (sub_type(Dirichlet_homogene, la_cl.valeur())))
176 { /* Do nothing */}
177 else
178 {
179 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
180 int ndeb = le_bord.num_premiere_face();
181 int nfin = ndeb + le_bord.nb_faces();
182 for (int num_face=ndeb; num_face<nfin; num_face++)
183 {
184 dt_face = volumes_entrelaces_Cl(num_face)/(fluent_[num_face]+1.e-30);
185 es_valeurs(num_face) = dt_face;
186 }
187 }
188 }
189
190 // On traite les faces internes non standard
191 int ndeb = domaine_VEF.premiere_face_int();
192 int nfin = domaine_VEF.premiere_face_std();
193
194 for (int num_face=ndeb; num_face<nfin; num_face++)
195 {
196 dt_face = volumes_entrelaces_Cl(num_face)/(fluent_[num_face]+1.e-30);
197 es_valeurs(num_face) = dt_face;
198 }
199
200 // On traite les faces internes standard
201 ndeb = nfin;
202 nfin = domaine_VEF.nb_faces();
203 for (int num_face=ndeb; num_face<nfin; num_face++)
204 {
205 dt_face = volumes_entrelaces(num_face)/(fluent_[num_face]+1.e-30);
206 es_valeurs(num_face) = dt_face;
207 }
208 if (vitesse().le_nom()=="rho_u" && equation().probleme().is_dilatable())
209 multiplier_par_rho_si_dilatable(fluent_,equation().milieu());
210 }
211 }
212 else
214}
215
217{
218 Motcle loc;
219 if (Motcle(option)=="stabilite")
220 loc = "face";
221 else
223 return loc;
224}
226{
227 const Domaine_Cl_VEF& zclvef = ref_cast(Domaine_Cl_VEF,domaine_cl_dis);
228 la_zcl_vef = zclvef;
229}
230
232 const Domaine_Cl_dis_base& domaine_cl_dis,
233 const Champ_Inc_base& )
234{
235 const Domaine_VEF& zvef = ref_cast(Domaine_VEF,domaine_dis);
236 const Domaine_Cl_VEF& zclvef = ref_cast(Domaine_Cl_VEF,domaine_cl_dis);
237
238 le_dom_vef = zvef;
239 la_zcl_vef = zclvef;
240 //******************************************************************************
241 // Initialisation des jetons pour l'alternance (kamoulox !)
242
243 //******************************************************************************
244 Cerr << "Initialisation de la roue pour la permutation des schemas de convection" << finl;
245 roue= -1;
246 // roue2=-1;
247
248 le_dom_vef->creer_tableau_faces(fluent_);
249}
250
252{
253 return Op_VEF_Face::impr(os, *this );
254}
255
256DoubleTab& Op_Conv_VEF_base::calculer(const DoubleTab& transporte,
257 DoubleTab& resu) const
258{
259 resu = 0;
260 return ajouter(transporte,resu);
261}
263{
264 // Remplissage du tableau fluent par appel a ajouter
265 // C'est cher mais au moins cela corrige (en attendant
266 // d'optimiser) le probleme d'un pas de temps de convection
267 // calcule avec des vitesses du passe
268 DoubleTrav tmp(equation().inconnue().valeurs());
269 DoubleTab flux_bords_sauve(flux_bords_); // On sauve les flux_bords car sinon mis a 0
270 ajouter(tmp,tmp);
271 flux_bords_=flux_bords_sauve;
272 // PL: C'est vraiment lourd, mais comment faire? fluent est dependant
273 // du schema et donc on peut coder quelque chose comme fluent=vitesse*surface*porosite
274 // dans cette presente methode
275}
276
277
278// Calculation of local time: Vect of size number of faces of the domain
279// This is the equivalent of "Op_Conv_VEF_base :: calculer_dt_stab ()"
280void Op_Conv_VEF_base::calculer_dt_local(DoubleTab& dt_face) const
281{
282 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
283 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
284 const DoubleVect& volumes_entrelaces = domaine_VEF.volumes_entrelaces();
285 const DoubleVect& volumes_entrelaces_Cl = domaine_Cl_VEF.volumes_entrelaces_Cl();
286
287 int nb_faces= domaine_VEF.nb_faces();
288 dt_face=(volumes_entrelaces);
290
291 for (int n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
292 {
293 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
294 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
295 int ndeb = le_bord.num_premiere_face();
296 int nfin = ndeb + le_bord.nb_faces();
297 for (int num_face=ndeb; num_face<nfin; num_face++)
298 {
299 if( sup_strict(fluent_[num_face], 1.e-30) )
300 dt_face(num_face)= volumes_entrelaces_Cl(num_face)/fluent_[num_face];
301 else
302 dt_face(num_face) = -1.;
303 }
304 }
305
306 //Non-standard internal faces
307 int ndeb = domaine_VEF.premiere_face_int();
308 int nfin = domaine_VEF.premiere_face_std();
309
310 for (int num_face=ndeb; num_face<nfin; num_face++)
311 {
312 if( sup_strict(fluent_[num_face], 1.e-30) )
313 dt_face(num_face)= volumes_entrelaces(num_face)/fluent_[num_face];
314 else
315 dt_face(num_face) = -1.;
316 }
317
318 //The standard internal faces
319 ndeb = nfin;
320 nfin = domaine_VEF.nb_faces();
321 for (int num_face=ndeb; num_face<nfin; num_face++)
322 {
323 if( sup_strict(fluent_[num_face], 1.e-30) )
324 dt_face(num_face)= volumes_entrelaces(num_face)/fluent_[num_face];
325 else
326 dt_face(num_face) = -1.;
327 }
328
329 double max_dt_local= dt_face.mp_max_abs_vect();
330 for(int i=0; i<nb_faces; i++)
331 {
332 if(! sup_strict(dt_face(i), 1.e-16))
333 dt_face(i) = max_dt_local;
334 }
335 dt_face.echange_espace_virtuel();
336
337 for (int n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
338 {
339 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
340 if (sub_type(Periodique,la_cl.valeur()))
341 {
342 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
343 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
344 int nb_faces_bord=le_bord.nb_faces();
345 for (int ind_face=0; ind_face<nb_faces_bord; ind_face++)
346 {
347 int ind_face_associee = la_cl_perio.face_associee(ind_face);
348 int face = le_bord.num_face(ind_face);
349 int face_associee = le_bord.num_face(ind_face_associee);
350 if (!est_egal(dt_face(face),dt_face(face_associee),1.e-8))
351 {
352 dt_face(face) = std::min(dt_face(face),dt_face(face_associee));
353 }
354 }
355 }
356 }
357 dt_face.echange_espace_virtuel();
358
359// dt_conv_locaux=dt_face;
360}
Classe Champ_Inc_base.
virtual DoubleTab & valeurs()=0
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
Classe Dirichlet_homogene Cette classe est la classe de base de la hierarchie des conditions aux limi...
classe Dirichlet Cette classe est la classe de base de la hierarchie des conditions aux limites de ty...
Definition Dirichlet.h:31
DoubleVect & volumes_entrelaces_Cl()
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les 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
int premiere_face_std() const
Definition Domaine_VEF.h:80
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int premiere_face_int() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:463
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
int nb_front_Cl() const
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 Champ_Inc_base & inconnue() const =0
const Nom & le_nom() const override
Renvoie le nom du champ.
class Front_VF
Definition Front_VF.h:36
int nb_faces() const
Definition Front_VF.h:53
int num_premiere_face() const
Definition Front_VF.h:63
int num_face(const int) const
Definition Front_VF.h:68
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
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 const Nom & le_nom() const
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Objet_U.cpp:319
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
class Op_Conv_VEF_base
int impr(Sortie &os) const override
DOES NOTHING - to override in derived classes.
int phi_u_transportant(const Equation_base &eq) const
definit si l'on convecte psi avec phi*u ou avec u
void associer(const Domaine_dis_base &, const Domaine_Cl_dis_base &, const Champ_Inc_base &) override
DoubleTab & calculer(const DoubleTab &, DoubleTab &) const override
void calculer_pour_post(Champ_base &espace_stockage, const Nom &option, int comp) const override
const Champ_Inc_base & vitesse() const
virtual void remplir_fluent() const
void abortTimeStep() override
void associer_vitesse(const Champ_base &) override
double calculer_dt_stab() const override
Calcul dt_stab.
void associer_domaine_cl_dis(const Domaine_Cl_dis_base &) override
ArrOfInt faces_entrelaces_Cl_
void calculer_dt_local(DoubleTab &) const override
Motcle get_localisation_pour_post(const Nom &option) const override
int impr(Sortie &, const Operateur_base &) const
Impression des flux d'un operateur VEF aux faces (ie: diffusion, convection).
classe Operateur_Conv_base Cette classe est la base de la hierarchie des operateurs representant
void fixer_dt_stab_conv(double dt)
DoubleTab flux_bords_
virtual void abortTimeStep()
virtual DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
static double mp_min(double)
Definition Process.cpp:386
Classe de base des flux de sortie.
Definition Sortie.h:52
_TYPE_ mp_max_abs_vect(Mp_vect_options opt=VECT_REAL_ITEMS) const
Definition TRUSTVect.h:160
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")