TRUST 1.9.8
HPC thermohydraulic platform
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 Associe les domaines a l'EDO
45 *
46 * @param (Domaine_dis_base& domaine) domaine
47 * @param (Domaine_Cl_dis_base& domaine_cl) domaine cl
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 Renvoie rho avec la meme discretisation que la vitesse : une valeur par face en VEF
62 *
63 * @return (DoubleTab&) rho discretise par 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 Calcule la moyenne volumique de la grandeur P1NC donnee
81 *
82 * @return (DoubleTab&) rho discretise par 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 // La facon simple de faire serait celle-ci, mais c'est faux a cause de FAUX_EN_PERIO
89 // qui compte deux fois les volumes entrelaces des faces periodiques:
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 pour moyenner div(u) sur les 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 //remplissage de div(u) sur les 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 Calcule le second membre de l'equation de continuite pour une discretisation VEF_P1B: div(U) = W = dZ/dT + U.
145 *
146 * grad(Z) avec Z=ln(rho)
147 *
148 * @return rho discretise par 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 // calcul de la somme des volumes entrelacees autour d'un sommet
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 //discretisation de rho sur les sommets
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 pour test de la moyenne de la derivee de la masse volumique
212 // Dimensionnement de 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 // Ajout des termes sources speciaux de l'equation de masse:
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); // attention : tab_dZ a taille comme pression
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 //pour l'instant on n'a pas calcule tab_dZ aux aretes
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
Renvoie le tableau des valeurs du champ au temps courant.
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
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
class Domaine_VEF
Definition Domaine_VEF.h:54
int get_alphaA() const
Definition Domaine_VEF.h:94
const DoubleVect & volume_aux_sommets() const
Definition Domaine_VEF.h:90
int get_alphaS() const
Definition Domaine_VEF.h:93
int get_alphaE() const
Definition Domaine_VEF.h:92
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
classe EOS_Tools_VEF Cette classe et specifique a discretisation de type VEF.
DoubleVect un_
double moyenne_vol(const DoubleTab &) const override
Calcule la moyenne volumique de la grandeur P1NC donnee.
const Fluide_Dilatable_base & le_fluide() const
void associer_domaines(const Domaine_dis_base &, const Domaine_Cl_dis_base &) override
Associe les domaines a l'EDO.
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
Calcule le second membre de l'equation de continuite pour une discretisation VEF_P1B: div(U) = W = dZ...
const DoubleTab & rho_face_np1() const override
const DoubleTab & rho_discvit() const override
Renvoie rho avec la meme discretisation que la vitesse : une valeur par face en VEF.
const DoubleTab & rho_face_n() const override
classe Abstraite EOS_Tools_base
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....
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'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
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
classe Navier_Stokes_Fluide_Dilatable_base Cette classe basse porte les termes de l'equation de la dy...
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
Champ_Inc_base & pression()
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
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
Classe de base des flux de sortie.
Definition Sortie.h:52
: classe Source_Masse_Fluide_Dilatable_base Une source speciale pour l'equation de masse (utilisee se...
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")