TrioCFD 1.9.9_beta
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 Defines whether psi is convected with phi*u or with 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 // Fill faces_entrelaces_Cl_ which contains non-Dirichlet boundary faces
72 // and non-standard internal faces for which volumes_entrelaces_Cl is used.
73 // This temporary array was created to merge several
74 // Kokkos kernels into one
75 if (faces_entrelaces_Cl_.size_array()==0)
76 {
77 faces_entrelaces_Cl_.resize(domaine_VEF.premiere_face_std());
78 int ind_face=-1;
79 // Process boundary conditions.
80 // If a face carries a Dirichlet condition, it is not taken into account
81 // in the computation of dt_stab.
82 for (int n_bord = 0; n_bord < domaine_VEF.nb_front_Cl(); n_bord++)
83 {
84 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
85 if (!sub_type(Dirichlet, la_cl.valeur()) && !sub_type(Dirichlet_homogene, la_cl.valeur()))
86 {
87 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
88 int ndeb = le_bord.num_premiere_face();
89 int nfin = ndeb + le_bord.nb_faces();
90 for (int num_face = ndeb; num_face < nfin; num_face++)
91 faces_entrelaces_Cl_(++ind_face) = num_face;
92 }
93 }
94 // Non-standard internal faces:
95 int ndeb = domaine_VEF.premiere_face_int();
96 int nfin = domaine_VEF.premiere_face_std();
97 for (int num_face = ndeb; num_face < nfin; num_face++)
98 faces_entrelaces_Cl_(++ind_face) = num_face;
99 faces_entrelaces_Cl_.resize(ind_face+1);
100 }
101
102 double dt_stab = 1.e30;
103 CIntArrView faces_entrelaces_Cl = faces_entrelaces_Cl_.view_ro();
104 CDoubleArrView fluent = fluent_.view_ro();
105 CDoubleArrView volumes_entrelaces_Cl = domaine_Cl_VEF.volumes_entrelaces_Cl().view_ro();
106 start_gpu_timer(__KERNEL_NAME__);
107 Kokkos::parallel_reduce(__KERNEL_NAME__,
108 range_1D(0, faces_entrelaces_Cl_.size_array()),
109 KOKKOS_LAMBDA(const int ind_face, double& dtstab)
110 {
111 int num_face = faces_entrelaces_Cl(ind_face);
112 double dt_face = volumes_entrelaces_Cl(num_face)/(fluent(num_face)+DMINFLOAT);
113 if (dt_face < dtstab) dtstab = dt_face;
114 }, Kokkos::Min<double>(dt_stab));
115 end_gpu_timer(__KERNEL_NAME__);
116
117 // Process standard internal faces
118 int ndeb = domaine_VEF.premiere_face_std();
119 int nfin = domaine_VEF.nb_faces();
120
121 const DoubleVect& tab_volumes_entrelaces = domaine_VEF.volumes_entrelaces();
122 CDoubleArrView volumes_entrelaces = tab_volumes_entrelaces.view_ro();
123 // Necessary because Kokkos::parallel_reduce() overwrites dt_stab with the
124 // result of the reduction regardless of the initial value (in
125 // particular, the value from a previous reduction, as here).
126 double dt_stab_2 = dt_stab;
127 Kokkos::parallel_reduce(
128 start_gpu_timer(__KERNEL_NAME__),
129 range_1D(ndeb, nfin),
130 KOKKOS_LAMBDA(const int num_face, double& dtstab)
131 {
132 double dt_face = volumes_entrelaces(num_face) / (fluent(num_face) + DMINFLOAT);
133 if (dt_face < dtstab) dtstab = dt_face;
134 }, Kokkos::Min<double>(dt_stab_2));
135 end_gpu_timer(__KERNEL_NAME__);
136 if (dt_stab_2 < dt_stab) dt_stab = dt_stab_2;
137
138 // Min over all processors
139 dt_stab = Process::mp_min(dt_stab);
140 // trick to work around the const type of the method
141 Op_Conv_VEF_base& op = ref_cast_non_const(Op_Conv_VEF_base,*this);
142 op.fixer_dt_stab_conv(dt_stab);
143 if (vitesse().le_nom()=="rho_u" && equation().probleme().is_dilatable())
144 multiplier_par_rho_si_dilatable(fluent_,equation().milieu());
145
146 return dt_stab;
147}
148
149// cf Op_Conv_VEF_base::calculer_dt_stab() for the choice of dt_stab computation
150void Op_Conv_VEF_base::calculer_pour_post(Champ_base& espace_stockage,const Nom& option,int comp) const
151{
152 if (Motcle(option)=="stabilite")
153 {
154 DoubleTab& es_valeurs = espace_stockage.valeurs();
155 es_valeurs = 1.e30;
156
157 if ((bool(le_dom_vef)) && (bool(la_zcl_vef)))
158 {
159 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
160 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
161 const DoubleVect& volumes_entrelaces = domaine_VEF.volumes_entrelaces();
162 const DoubleVect& volumes_entrelaces_Cl = domaine_Cl_VEF.volumes_entrelaces_Cl();
163 double dt_face;
165 if (vitesse().le_nom()=="rho_u" && equation().probleme().is_dilatable())
166 diviser_par_rho_si_dilatable(fluent_,equation().milieu());
167
168 // Process boundary conditions.
169 // If a face carries a Dirichlet condition, it is not taken into account
170 // in the computation of dt_stab.
171 for (int n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
172 {
173 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
174 if ((sub_type(Dirichlet, la_cl.valeur())) || (sub_type(Dirichlet_homogene, la_cl.valeur())))
175 { /* Do nothing */}
176 else
177 {
178 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
179 int ndeb = le_bord.num_premiere_face();
180 int nfin = ndeb + le_bord.nb_faces();
181 for (int num_face=ndeb; num_face<nfin; num_face++)
182 {
183 dt_face = volumes_entrelaces_Cl(num_face)/(fluent_[num_face]+1.e-30);
184 es_valeurs(num_face) = dt_face;
185 }
186 }
187 }
188
189 // Process non-standard internal faces
190 int ndeb = domaine_VEF.premiere_face_int();
191 int nfin = domaine_VEF.premiere_face_std();
192
193 for (int num_face=ndeb; num_face<nfin; num_face++)
194 {
195 dt_face = volumes_entrelaces_Cl(num_face)/(fluent_[num_face]+1.e-30);
196 es_valeurs(num_face) = dt_face;
197 }
198
199 // Process standard internal faces
200 ndeb = nfin;
201 nfin = domaine_VEF.nb_faces();
202 for (int num_face=ndeb; num_face<nfin; num_face++)
203 {
204 dt_face = volumes_entrelaces(num_face)/(fluent_[num_face]+1.e-30);
205 es_valeurs(num_face) = dt_face;
206 }
207 if (vitesse().le_nom()=="rho_u" && equation().probleme().is_dilatable())
208 multiplier_par_rho_si_dilatable(fluent_,equation().milieu());
209 }
210 }
211 else
213}
214
216{
217 Motcle loc;
218 if (Motcle(option)=="stabilite")
219 loc = "face";
220 else
222 return loc;
223}
225{
226 const Domaine_Cl_VEF& zclvef = ref_cast(Domaine_Cl_VEF,domaine_cl_dis);
227 la_zcl_vef = zclvef;
228}
229
231 const Domaine_Cl_dis_base& domaine_cl_dis,
232 const Champ_Inc_base& )
233{
234 const Domaine_VEF& zvef = ref_cast(Domaine_VEF,domaine_dis);
235 const Domaine_Cl_VEF& zclvef = ref_cast(Domaine_Cl_VEF,domaine_cl_dis);
236
237 le_dom_vef = zvef;
238 la_zcl_vef = zclvef;
239 //******************************************************************************
240 // Initialization of tokens for alternation (kamoulox!)
241
242 //******************************************************************************
243 Cerr << "Initialization of the wheel for permutation of convection schemes" << finl;
244 roue= -1;
245 // roue2=-1;
246
247 le_dom_vef->creer_tableau_faces(fluent_);
248}
249
251{
252 return Op_VEF_Face::impr(os, *this );
253}
254
255DoubleTab& Op_Conv_VEF_base::calculer(const DoubleTab& transporte,
256 DoubleTab& resu) const
257{
258 resu = 0;
259 return ajouter(transporte,resu);
260}
262{
263 // Fill the fluent array by calling ajouter.
264 // This is expensive but at least it fixes (while waiting
265 // to optimize) the problem of a convection time step
266 // computed with velocities from the past.
267 DoubleTrav tmp(equation().inconnue().valeurs());
268 DoubleTab flux_bords_sauve(flux_bords_); // Save flux_bords, otherwise set to 0
269 ajouter(tmp,tmp);
270 flux_bords_=flux_bords_sauve;
271 // PL: This is really heavy, but what else? fluent depends on
272 // the scheme, so something like fluent=velocity*surface*porosity
273 // could be coded in this method
274}
275
276
277// Calculation of local time: Vect of size number of faces of the domain
278// This is the equivalent of "Op_Conv_VEF_base :: calculer_dt_stab ()"
279void Op_Conv_VEF_base::calculer_dt_local(DoubleTab& dt_face) const
280{
281 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
282 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
283 const DoubleVect& volumes_entrelaces = domaine_VEF.volumes_entrelaces();
284 const DoubleVect& volumes_entrelaces_Cl = domaine_Cl_VEF.volumes_entrelaces_Cl();
285
286 int nb_faces= domaine_VEF.nb_faces();
287 dt_face=(volumes_entrelaces);
289
290 for (int n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
291 {
292 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
293 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
294 int ndeb = le_bord.num_premiere_face();
295 int nfin = ndeb + le_bord.nb_faces();
296 for (int num_face=ndeb; num_face<nfin; num_face++)
297 {
298 if( sup_strict(fluent_[num_face], 1.e-30) )
299 dt_face(num_face)= volumes_entrelaces_Cl(num_face)/fluent_[num_face];
300 else
301 dt_face(num_face) = -1.;
302 }
303 }
304
305 //Non-standard internal faces
306 int ndeb = domaine_VEF.premiere_face_int();
307 int nfin = domaine_VEF.premiere_face_std();
308
309 for (int num_face=ndeb; num_face<nfin; num_face++)
310 {
311 if( sup_strict(fluent_[num_face], 1.e-30) )
312 dt_face(num_face)= volumes_entrelaces(num_face)/fluent_[num_face];
313 else
314 dt_face(num_face) = -1.;
315 }
316
317 //The standard internal faces
318 ndeb = nfin;
319 nfin = domaine_VEF.nb_faces();
320 for (int num_face=ndeb; num_face<nfin; num_face++)
321 {
322 if( sup_strict(fluent_[num_face], 1.e-30) )
323 dt_face(num_face)= volumes_entrelaces(num_face)/fluent_[num_face];
324 else
325 dt_face(num_face) = -1.;
326 }
327
328 double max_dt_local= dt_face.mp_max_abs_vect();
329 for(int i=0; i<nb_faces; i++)
330 {
331 if(! sup_strict(dt_face(i), 1.e-16))
332 dt_face(i) = max_dt_local;
333 }
334 dt_face.echange_espace_virtuel();
335
336 for (int n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
337 {
338 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
339 if (sub_type(Periodique,la_cl.valeur()))
340 {
341 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
342 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
343 int nb_faces_bord=le_bord.nb_faces();
344 for (int ind_face=0; ind_face<nb_faces_bord; ind_face++)
345 {
346 int ind_face_associee = la_cl_perio.face_associee(ind_face);
347 int face = le_bord.num_face(ind_face);
348 int face_associee = le_bord.num_face(ind_face_associee);
349 if (!est_egal(dt_face(face),dt_face(face_associee),1.e-8))
350 {
351 dt_face(face) = std::min(dt_face(face),dt_face(face_associee));
352 }
353 }
354 }
355 }
356 dt_face.echange_espace_virtuel();
357
358// dt_conv_locaux=dt_face;
359}
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
class Cond_lim Generic class used to represent any class
Definition Cond_lim.h:31
Classe Dirichlet_homogene This class is the base class of the hierarchy of homogeneous Dirichlet-type...
Dirichlet This class is the base class of the hierarchy of Dirichlet-type boundary conditions.
Definition Dirichlet.h:31
DoubleVect & volumes_entrelaces_Cl()
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
const Cond_lim & les_conditions_limites(int) const
Returns the i-th boundary condition.
class Domaine_VEF
Definition Domaine_VEF.h:53
int premiere_face_std() const
Definition Domaine_VEF.h:79
int nb_faces() const
Returns the total number of faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
int premiere_face_int() const
A face is internal if and only if it separates two elements.
Definition Domaine_VF.h:463
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
int nb_front_Cl() const
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 Champ_Inc_base & inconnue() const =0
const Nom & le_nom() const override
Returns the name of the field.
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
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
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 const Nom & le_nom() const
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Definition Objet_U.cpp:317
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
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
Defines whether psi is convected with phi*u or with 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
Computes 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
Print the face fluxes of a VEF operator (e.g. diffusion, convection).
Operateur_Conv_base This class is the base of the hierarchy of operators representing.
void fixer_dt_stab_conv(double dt)
DoubleTab flux_bords_
virtual void abortTimeStep()
virtual DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const
class Periodique This class represents a periodic boundary condition.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
static double mp_min(double)
Definition Process.cpp:391
Base class for output streams.
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")