TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
EOS_Tools_VEF.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 <Navier_Stokes_Fluide_Dilatable_base.h>
17#include <Source_Masse_Fluide_Dilatable_base.h>
18#include <Loi_Etat_Melange_GP_base.h>
19#include <Fluide_Dilatable_base.h>
20#include <Check_espace_virtuel.h>
21#include <Schema_Temps_base.h>
22#include <Porosites_champ.h>
23#include <EOS_Tools_VEF.h>
24#include <Domaine_VEF.h>
25#include <Champ_P1NC.h>
26#include <Domaine.h>
27#include <Debog.h>
28
29#include <kokkos++.h>
30#include <TRUSTArray_kokkos.tpp>
31
32Implemente_instanciable(EOS_Tools_VEF,"EOS_Tools_VEF",EOS_Tools_base);
33
35{
36 return os <<que_suis_je()<< finl;
37}
38
40{
41 return is;
42}
43
44/*! @brief Associates the domains to the ODE.
45 *
46 * @param (Domaine_dis_base& domaine) domain
47 * @param (Domaine_Cl_dis_base& domaine_cl) boundary condition domain
48 */
50{
51 le_dom = ref_cast(Domaine_VEF,dds);
52 le_dom_Cl = domaine_cl;
53 if (!un_.get_md_vector())
54 {
55 le_dom->creer_tableau_faces(un_, RESIZE_OPTIONS::NOCOPY_NOINIT);
56 mapToDevice(un_); // Copy on device this constant array
57 un_ = 1.;
58 }
59}
60
61/*! @brief Returns rho with the same discretization as the velocity: one value per face in VEF.
62 *
63 * @return (DoubleTab&) rho discretized per face
64 */
65const DoubleTab& EOS_Tools_VEF::rho_discvit() const
66{
67 return le_fluide_->masse_volumique().valeurs();
68}
69
70const DoubleTab& EOS_Tools_VEF::rho_face_n() const
71{
72 return le_fluide_->rho_n();
73}
74
75const DoubleTab& EOS_Tools_VEF::rho_face_np1() const
76{
77 return le_fluide_->rho_np1();
78}
79
80/*! @brief Computes the volumetric average of the given P1NC quantity.
81 *
82 * @return (DoubleTab&) rho discretized per face
83 */
84double EOS_Tools_VEF::moyenne_vol(const DoubleTab& tab) const
85{
86 assert(tab.line_size() == 1);
87 double x = Champ_P1NC::calculer_integrale_volumique(le_dom.valeur(), tab, FAUX_EN_PERIO);
88 // The simple approach would be to compute this directly, but it is incorrect because of FAUX_EN_PERIO
89 // which counts the interlaced volumes of periodic faces twice:
90 double y = Champ_P1NC::calculer_integrale_volumique(le_dom.valeur(), un_, FAUX_EN_PERIO);
91 return x / y;
92}
93
94/*! @brief Div(u) is computed on faces from Div(u) on elements
95 *
96 */
97void EOS_Tools_VEF::divu_discvit(const DoubleTab& DivVelocityElements, DoubleTab& DivVelocityFaces)
98{
99 ToDo_Kokkos("critical");
100 assert_espace_virtuel_vect(DivVelocityElements);
101 // Corrections to average div(u) on faces
102 const DoubleVect& volumes = le_dom->volumes();
103 const DoubleVect& volumes_entrelaces = le_dom->volumes_entrelaces();
104 const DoubleVect& volumes_entrelaces_Cl = ref_cast(Domaine_Cl_VEF,le_dom_Cl.valeur()).volumes_entrelaces_Cl();
105
106 IntTab& face_voisins = le_dom->face_voisins();
107 int premiere_fac_std=le_dom->premiere_face_std();
108
109 // Fill div(u) on faces
110 for (int face=0; face<premiere_fac_std; face++)
111 {
112 int nb_comp=0;
113 DivVelocityFaces(face)=0;
114 for (int i=0 ; i<2 ; i++)
115 {
116 int elem= face_voisins(face,i);
117 if (elem!=-1)
118 {
119 nb_comp++;
120 DivVelocityFaces(face) += DivVelocityElements(elem)*(volumes_entrelaces_Cl(face)/volumes(elem));
121 }
122 }
123 DivVelocityFaces(face) /= nb_comp;
124 }
125
126 int size = le_dom->nb_faces();
127 for (int face=premiere_fac_std; face<size; face++)
128 {
129 int nb_comp=0;
130 DivVelocityFaces(face)=0;
131 for (int i=0 ; i<2 ; i++)
132 {
133 int elem= face_voisins(face,i);
134 if (elem!=-1)
135 {
136 nb_comp++;
137 DivVelocityFaces(face) += DivVelocityElements(elem)*(volumes_entrelaces(face)/volumes(elem));
138 }
139 }
140 DivVelocityFaces(face) /= nb_comp;
141 }
142}
143
144/*! @brief Computes the right-hand side of the continuity equation for a VEF_P1B discretization: div(U) = W = dZ/dT + U.
145 *
146 * grad(Z) with Z=ln(rho)
147 *
148 * @return rho discretized per face
149 */
150void EOS_Tools_VEF::secmembre_divU_Z(DoubleTab& tab_W) const
151{
152 double dt = le_fluide().vitesse().equation().schema_temps().pas_de_temps();
153 const IntTab& face_sommets = le_dom->face_sommets();
154 int nb_elem_tot = le_dom->nb_elem_tot();
155 int nb_som_tot = le_dom->domaine().nb_som_tot();
156 int nb_faces_tot = le_dom->nb_faces_tot();
157 const Equation_base& eq = le_fluide().vitesse().equation();
158
159 const DoubleTab& tab_rhon = le_fluide().loi_etat()->rho_n();
160 const DoubleTab& tab_rhonp1 = le_fluide().loi_etat()->rho_np1();
161 DoubleTrav tab_rhonP1_, tab_rhonp1P1_;
162 const DoubleVect& porosite_face = le_fluide().porosite_face();
163 const DoubleTab& tab_rhonP1 = modif_par_porosite_si_flag(tab_rhon, tab_rhonP1_, 1, porosite_face);
164 const DoubleTab& tab_rhonp1P1 = modif_par_porosite_si_flag(tab_rhonp1, tab_rhonp1P1_, 1, porosite_face);
165 const DoubleVect& volumes_entrelaces = le_dom->volumes_entrelaces();
166 const Domaine_VEF& zp1b = ref_cast(Domaine_VEF, le_dom.valeur());
167
168 int nfe = le_dom->domaine().nb_faces_elem();
169 int nsf = le_dom->nb_som_face();
170 const Domaine& dom = le_dom->domaine();
171
172 // compute the sum of interlaced volumes around a vertex
173 DoubleTrav volume_int_som(nb_som_tot);
174 CIntTabView face_sommets_v = face_sommets.view_ro();
175 CDoubleArrView volumes_entrelaces_v = static_cast<const DoubleVect&>(volumes_entrelaces).view_ro();
176 CIntArrView renum_som_perio_v = dom.get_renum_som_perio().view_ro();
177 DoubleArrView volume_int_som_v = static_cast<DoubleVect&>(volume_int_som).view_rw();
178 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_faces_tot, KOKKOS_LAMBDA(
179 const int face)
180 {
181 for (int som = 0; som < nsf; som++)
182 {
183 int som_glob = renum_som_perio_v(face_sommets_v(face, som));
184 Kokkos::atomic_add(&volume_int_som_v(som_glob), volumes_entrelaces_v(face));
185 }
186 });
187 end_gpu_timer(__KERNEL_NAME__);
188
189 // discretization of rho on the vertices
190 DoubleTrav tab_rhon_som(nb_som_tot);
191 DoubleTrav tab_rhonp1_som(nb_som_tot);
192
193 CDoubleTabView tab_rhonP1_v = tab_rhonP1.view_ro();
194 CDoubleTabView tab_rhonp1P1_v = tab_rhonp1P1.view_ro();
195 DoubleArrView tab_rhon_som_v = static_cast<DoubleVect&>(tab_rhon_som).view_rw();
196 DoubleArrView tab_rhonp1_som_v = static_cast<DoubleVect&>(tab_rhonp1_som).view_rw();
197 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_faces_tot, KOKKOS_LAMBDA(
198 const int face)
199 {
200 for (int som = 0; som < nsf; som++)
201 {
202 int som_glob = renum_som_perio_v(face_sommets_v(face, som));
203 // double pond = 1./nsf; // version_originale
204 double pond = volumes_entrelaces_v(face) / volume_int_som_v(som_glob);
205 Kokkos::atomic_add(&tab_rhon_som_v(som_glob), tab_rhonP1_v(face, 0) * pond);
206 Kokkos::atomic_add(&tab_rhonp1_som_v(som_glob), tab_rhonp1P1_v(face, 0) * pond);
207 }
208 });
209 end_gpu_timer(__KERNEL_NAME__);
210
211// Corrections for testing the mean of the density derivative
212 // Sizing of tab_dZ
213 const Navier_Stokes_std& eqns = ref_cast(Navier_Stokes_std, eq);
214 const DoubleVect& pression = eqns.pression().valeurs();
215 Debog::verifier("EOS_Tools_VEF::secmembre_divU_Z pression=",pression);
216 Debog::verifier("EOS_Tools_VEF::secmembre_divU_Z tab_rhonP1=",tab_rhonP1);
217 Debog::verifier("EOS_Tools_VEF::secmembre_divU_Z tab_rhonp1P1=",tab_rhonp1P1);
218 Debog::verifier("EOS_Tools_VEF::secmembre_divU_Z dt=",dt);
219
220 int p_has_elem=zp1b.get_alphaE();
221 int p_has_som=zp1b.get_alphaS();
222 int p_has_arrete=zp1b.get_alphaA();
223 int nb_ar_tot = le_dom->domaine().nb_aretes_tot();
224
225 // ToDo_Kokkos, try to merge all theses kernels for efficiency:
226 int decal=0;
227 DoubleTrav tab_dZ = pression;
228 DoubleArrView tab_dZ_v = static_cast<DoubleVect&>(tab_dZ).view_rw();
229 if (p_has_elem)
230 {
231 CIntTabView elem_faces_v = le_dom->elem_faces().view_ro();
232 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_elem_tot, KOKKOS_LAMBDA(
233 const int elem)
234 {
235 double rn = 0;
236 double rnp1 = 0;
237 for (int face = 0; face < nfe; face++)
238 {
239 rn += tab_rhonP1_v(elem_faces_v(elem, face), 0);
240 rnp1 += tab_rhonp1P1_v(elem_faces_v(elem, face), 0);
241 }
242 tab_dZ_v(elem) = (rnp1 - rn) / (nfe * dt);
243 });
244 end_gpu_timer(__KERNEL_NAME__);
245 decal += nb_elem_tot;
246 }
247
248 if (p_has_som)
249 {
250 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_som_tot, KOKKOS_LAMBDA(
251 const int som)
252 {
253 tab_dZ_v(decal + som) = ((tab_rhonp1_som_v(som)) - (tab_rhon_som_v(som))) / dt;
254 });
255 end_gpu_timer(__KERNEL_NAME__);
256 decal += nb_som_tot;
257 }
258
259 if (p_has_arrete)
260 {
261 for (int ar = 0; ar < nb_ar_tot; ar++)
262 tab_dZ(decal + ar) = 0;
263 }
264 tab_dZ.echange_espace_virtuel();
265 Debog::verifier("EOS_Tools_VEF::secmembre_divU_Z tab_dZ=",tab_dZ);
266
267 // Adding special source terms of the mass equation:
268 const bool has_mass_flux = (sub_type(Navier_Stokes_Fluide_Dilatable_base, le_fluide().vitesse().equation())) ?
269 ref_cast(Navier_Stokes_Fluide_Dilatable_base, le_fluide().vitesse().equation()).has_source_masse() : false;
270
271 if (has_mass_flux)
272 {
273 const Source_Masse_Fluide_Dilatable_base& src_mass = ref_cast(Navier_Stokes_Fluide_Dilatable_base, le_fluide().vitesse().equation()).source_masse();
274 src_mass.ajouter_projection(le_fluide(),tab_dZ); // note: tab_dZ has the same size as the pressure array
275 }
276
277 CDoubleArrView dZ = static_cast<DoubleVect&>(tab_dZ).view_ro();
278 DoubleTabView W = tab_W.view_rw();
279 decal=0;
280 if (p_has_elem)
281 {
282 double coefdivelem=1;
283 CDoubleArrView volumes_v = le_dom->volumes().view_ro();
284 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_elem_tot, KOKKOS_LAMBDA(
285 const int elem)
286 {
287 W(elem, 0) = -coefdivelem * dZ(elem) * volumes_v(elem);
288 });
289 end_gpu_timer(__KERNEL_NAME__);
290 decal+=nb_elem_tot;
291 }
292 if (p_has_som)
293 {
294 double coefdivsom=1;
295 CDoubleArrView volumes_controle_v = zp1b.volume_aux_sommets().view_ro();
296 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), nb_som_tot, KOKKOS_LAMBDA(
297 const int som)
298 {
299 W(decal + som, 0) = -coefdivsom * dZ(decal + som) * volumes_controle_v(som);
300 });
301 end_gpu_timer(__KERNEL_NAME__);
302 decal+=nb_som_tot;
303 }
304 if (p_has_arrete)
305 {
306 for (int ar = 0; ar < nb_ar_tot; ar++)
307 {
308 // for now, tab_dZ has not been computed at edges
309 assert(tab_dZ(decal + ar) == 0);
310 tab_W(decal + ar) = 0.;
311 }
312 }
314 Debog::verifier("EOS_Tools_VEF::secmembre_divU_Z tab_W=",tab_W);
315}
DoubleTab & valeurs() override
Returns the array of field values at the current time.
static double calculer_integrale_volumique(const Domaine_VEF &, const DoubleVect &, Ok_Perio ok)
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
int_t get_renum_som_perio(int_t i) const
Definition Domaine.h:281
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
class Domaine_VEF
Definition Domaine_VEF.h:53
int get_alphaA() const
Definition Domaine_VEF.h:93
const DoubleVect & volume_aux_sommets() const
Definition Domaine_VEF.h:89
int get_alphaS() const
Definition Domaine_VEF.h:92
int get_alphaE() const
Definition Domaine_VEF.h:91
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
class EOS_Tools_VEF
DoubleVect un_
double moyenne_vol(const DoubleTab &) const override
Computes the volumetric average of the given P1NC quantity.
const Fluide_Dilatable_base & le_fluide() const
void associer_domaines(const Domaine_dis_base &, const Domaine_Cl_dis_base &) override
Associates the domains to the ODE.
void divu_discvit(const DoubleTab &, DoubleTab &) override
Div(u) is computed on faces from Div(u) on elements.
void secmembre_divU_Z(DoubleTab &) const override
Computes the right-hand side of the continuity equation for a VEF_P1B discretization: div(U) = W = dZ...
const DoubleTab & rho_face_np1() const override
const DoubleTab & rho_discvit() const override
Returns rho with the same discretization as the velocity: one value per face in VEF.
const DoubleTab & rho_face_n() const override
Abstract base class for EOS tools used with dilatable fluids.
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....
Schema_Temps_base & schema_temps()
Returns the time scheme associated with the equation.
const DoubleTab & rho_n() const
const Champ_Inc_base & vitesse() const
const DoubleTab & rho_np1() const
DoubleVect & porosite_face()
Definition Milieu_base.h:62
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
Base class carrying the terms of the momentum equation for a fluid without turbulence modelling under...
Navier_Stokes_std This class carries the terms of the momentum equation.
Champ_Inc_base & pression()
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
double pas_de_temps() const
Returns the current time step (delta_t).
Base class for output streams.
Definition Sortie.h:52
Special mass source term for the mass equation (used only during the projection/correction step).
virtual void ajouter_projection(const Fluide_Dilatable_base &fluide, DoubleVect &resu) const =0
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, ConstView< _TYPE_, _SHAPE_ > > view_ro() const
Definition TRUSTTab.h:261
std::enable_if_t< is_default_exec_space< EXEC_SPACE >, View< _TYPE_, _SHAPE_ > > view_rw()
Definition TRUSTTab.h:291
int line_size() const
Definition TRUSTVect.tpp:67
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")