TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Terme_Source_Acceleration_VDF_Face.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 <Terme_Source_Acceleration_VDF_Face.h>
17#include <Navier_Stokes_std.h>
18#include <Champ_Fonc_P0_VDF.h>
19#include <Milieu_base.h>
20
21#include <Domaine_Cl_VDF.h>
22#include <Periodique.h>
23#include <Domaine_VDF.h>
24
25Implemente_instanciable(Terme_Source_Acceleration_VDF_Face,"Acceleration_VDF_Face",Terme_Source_Acceleration);
26
28{
29 return s << que_suis_je() ;
30}
31
32/*! @brief Appel a Terme_Source_Acceleration::lire_data
33 *
34 */
36{
37 lire_data(s);
38 return s;
39}
40
41/*! @brief Methode appelee par Source_base::completer() apres associer_domaines Remplit les ref.
42 *
43 * aux domaines et domaine_cl
44 *
45 */
47 const Domaine_Cl_dis_base& domaine_Cl_dis)
48{
49 if (je_suis_maitre())
50 Cerr << "Terme_Source_Acceleration_VDF_Face::associer_domaines" << finl;
51 le_dom_VDF_ = ref_cast(Domaine_VDF, domaine_dis);
52 le_dom_Cl_VDF_ = ref_cast(Domaine_Cl_VDF, domaine_Cl_dis);
53}
54
55/*! @brief Fonction outil pour Terme_Source_Acceleration_VDF_Face::ajouter Ajout des contributions d'une liste contigue de faces du terme source de translation:
56 *
57 * s_face = terme_source * rho
58 * resu += integrale (s_face) sur le volume de controle de la vitesse.
59 * On traite les cas suivants:
60 * rho = reference nulle (=> rho = 1.) sinon rho != nul
61 * faces de bord => sortie libre
62 * periodicite
63 * faces_internes
64 *
65 */
66static void TSAVDF_ajouter_liste_faces(const int premiere_face, const int derniere_face,
67 const DoubleVect& volumes_entrelaces,
68 const DoubleVect& volumes_elements,
69 const DoubleVect& porosite_surf,
70 const IntVect& orientation,
71 const IntTab& face_voisins,
72 const OBS_PTR(Champ_base) & ref_rho,
73 const DoubleTab& terme_source,
74 DoubleTab& s_face,
75 DoubleTab& resu)
76{
77 int num_face;
78 // Pointeur constant sur tableau constant.
79 // Pointeur nul si ref_rho_ est une reference nulle.
80 const DoubleTab * const rho_elem =
81 (bool(ref_rho)) ? &(ref_rho->valeurs()) : 0;
82
83 for (num_face=premiere_face; num_face<derniere_face; num_face++)
84 {
85 const double vol = volumes_entrelaces(num_face)*porosite_surf(num_face);
86 const int ncomp = orientation(num_face);
87 const double src = terme_source(num_face, ncomp);
88
89 double rho = 1.;
90
91 // Calcul d'un rho moyen sur le volume de controle de la vitesse
92 if (rho_elem)
93 {
94 const int elem0 = face_voisins(num_face,0);
95 const int elem1 = face_voisins(num_face,1);
96 double rho0 = 0, rho1 = 0, vol0 = 0, vol1 = 0;
97 if (elem0 >= 0)
98 {
99 rho0 = (*rho_elem)(elem0);
100 vol0 = volumes_elements(elem0);
101 }
102 if (elem1 >= 0)
103 {
104 rho1 = (*rho_elem)(elem1);
105 vol1 = volumes_elements(elem1);
106 }
107 rho = (rho0 * vol0 + rho1 * vol1) / (vol0 + vol1);
108 }
109
110 double a = src * rho;
111 s_face(num_face) = a;
112 // Integrale sur le volume de controle :
113 resu(num_face) += a * vol;
114 }
115}
116
117/*! @brief Ajoute le terme (la_source_ * rho * volume_entrelace) au champ resu.
118 *
119 * On suppose que resu est discretise comme la vitesse en VDF.
120 * Effet de bord:
121 * On met (la_source_ * rho) dans terme_source_post_
122 *
123 */
124void Terme_Source_Acceleration_VDF_Face::ajouter_blocs(matrices_t matrices, DoubleTab& secmem, const tabs_t& semi_impl) const
125{
126 const Domaine_VDF& domaine_VDF = le_dom_VDF_.valeur();
127 const Domaine_Cl_VDF& domaine_Cl_VDF = le_dom_Cl_VDF_.valeur();
128 const IntTab& face_voisins = domaine_VDF.face_voisins();
129 const IntVect& orientation = domaine_VDF.orientation();
130 const DoubleVect& porosite_surf = equation().milieu().porosite_face();
131 const DoubleVect& volumes_entrelaces = domaine_VDF.volumes_entrelaces();
132
133 DoubleTab& s_face = get_set_terme_source_post().valeurs();
134 s_face = 0.;
135
136 // Calcul de la_source_ en fonction des champs d'acceleration et de la
137 // vitesse du fluide.
138 const int dim = Objet_U::dimension;
139 const int nb_faces = secmem.dimension(0);
140 DoubleTab acceleration_aux_faces(nb_faces, dim);
141 calculer_la_source(acceleration_aux_faces);
142
143 // Boucle sur les conditions limites pour traiter les faces de bord
144
145 for (int n_bord=0; n_bord<domaine_VDF.nb_front_Cl(); n_bord++)
146 {
147 // pour chaque Condition Limite on regarde son type
148 // Si face de Dirichlet ou de Symetrie on ne fait rien
149 // Si face de Neumann on calcule la contribution au terme source
150 const Cond_lim& la_cl = domaine_Cl_VDF.les_conditions_limites(n_bord);
151 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
152 const int ndeb = le_bord.num_premiere_face();
153 const int nfin = ndeb + le_bord.nb_faces();
154 TSAVDF_ajouter_liste_faces(ndeb, nfin,
155 volumes_entrelaces,
156 le_dom_VDF_->volumes(),
157 porosite_surf,
158 orientation,
159 face_voisins,
160 ref_rho_,
161 acceleration_aux_faces,
162 s_face,
163 secmem);
164 }
165
166
167 // Boucle sur les faces internes
168 {
169 const int ndeb = domaine_VDF.premiere_face_int();
170 const int nfin = domaine_VDF.nb_faces();
171 TSAVDF_ajouter_liste_faces(ndeb, nfin,
172 volumes_entrelaces,
173 le_dom_VDF_->volumes(),
174 porosite_surf,
175 orientation,
176 face_voisins,
177 ref_rho_,
178 acceleration_aux_faces,
179 s_face,
180 secmem);
181 }
182 {
183 // Force la periodicite
184 for (int n_bord=0; n_bord<domaine_VDF.nb_front_Cl(); n_bord++)
185 {
186 const Cond_lim& la_cl = domaine_Cl_VDF.les_conditions_limites(n_bord);
187 if (sub_type(Periodique,la_cl.valeur()))
188 {
189 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
190 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
191 int nb_faces_bord=le_bord.nb_faces();
192 ArrOfInt fait(nb_faces_bord);
193 fait = 0;
194 for (int ind_face=0; ind_face<nb_faces_bord; ind_face++)
195 {
196 if (fait[ind_face] == 0)
197 {
198 int ind_face_associee = la_cl_perio.face_associee(ind_face);
199 fait[ind_face] = 1;
200 fait[ind_face_associee] = 1;
201 int face = le_bord.num_face(ind_face);
202 int face_associee = le_bord.num_face(ind_face_associee);
203 double val = 0.5*(secmem(face_associee)+secmem(face));
204 secmem(face)=secmem(face_associee) = val;
205 }// if fait
206 }// for face
207 }// sub_type Perio
208 }
209 }
210}
211
212/*! @brief Calcul des trois composantes du champ de vitesse fluide au centre de chaque face.
213 *
214 * Le resultat est stocke dans v_faces_stockage et on renvoie
215 * une reference au tableau. Pas d'espace virtuel dans le tableau.
216 * La composante normale a la face est deja connue: c'est la valeur discrete.
217 * Les autres composantes sont calculees en faisant la moyenne des vitesse
218 * des faces des elements voisins qui ont la bonne orientation, ponderee
219 * par le volume de l'element.
220 * Traitement des bords : on prend la vitesse de l'element voisin (a priori
221 * pas bon pour les conditions aux limites de vitesse imposee au bord,
222 * mais le vpoint est corrige ensuite pour imposer la vitesse).
223 *
224 */
226 DoubleTab& v_faces_stockage) const
227{
228 const Domaine_VDF& domaine_VDF = le_dom_VDF_.valeur();
229 const IntVect& orientation = domaine_VDF.orientation();
230 const IntTab& faces_voisins = domaine_VDF.face_voisins();
231 const DoubleVect& volumes = domaine_VDF.volumes(); // volumes des elements
232 const IntTab& elem_faces = domaine_VDF.elem_faces();
233 const DoubleTab& v_faces = get_eq_hydraulique().inconnue().valeurs();
234 const int dim = Objet_U::dimension;
235 const int nb_faces = v_faces.dimension(0);
236 v_faces_stockage.resize(nb_faces, dim);
237 int i_face;
238 ArrOfDouble composante_vitesse(3);
239 for (i_face = 0; i_face < nb_faces; i_face++)
240 {
241 const int orientation_face = orientation(i_face);
242 composante_vitesse=0;
243 int composante;
244
245 // Numeros des deux elements voisins de la face (-1 si face de bord)
246 int elem[2];
247 elem[0] = faces_voisins(i_face, 0);
248 elem[1] = faces_voisins(i_face, 1);
249
250 // Volumes de ces deux elements (0. si pas de voisin)
251 double volume_elem[2] = {0., 0.};
252 if (elem[0] >= 0)
253 volume_elem[0] = volumes(elem[0]);
254 if (elem[1] >= 0)
255 volume_elem[1] = volumes(elem[1]);
256
257 const double i_volume_total = 1. / (volume_elem[0] + volume_elem[1]);
258
259 for (composante = 0; composante < dim; composante++)
260 {
261 if (composante == orientation_face)
262 {
263 composante_vitesse[composante] = v_faces(i_face);
264 }
265 else
266 {
267 // Calcul de la moyenne des vitesses sur les faces voisines
268 // qui ont la bonne orientation:
269 composante_vitesse[composante] = 0.;
270 int i_elem;
271 for (i_elem = 0; i_elem < 2; i_elem++)
272 {
273 if (elem[i_elem] >= 0)
274 {
275 const int element = elem[i_elem];
276 const int face1 = elem_faces(element, composante);
277 const int face2 = elem_faces(element, composante + dim);
278 const double v1 = v_faces(face1);
279 const double v2 = v_faces(face2);
280 const double p = volume_elem[i_elem]; // Ponderation par le volume
281 composante_vitesse[composante] += (v1 + v2) * 0.5 * p;
282 }
283 }
284 composante_vitesse[composante] *= i_volume_total;
285 }
286 }
287 for (composante = 0; composante < dim; composante++)
288 {
289 v_faces_stockage(i_face, composante) = composante_vitesse[composante];
290 }
291 }
292 return v_faces_stockage;
293}
294
295/*! @brief Associe le champ de masse volumique=> Le terme source calcule sera alors homogene a d/dt(integrale(rho*v)).
296 *
297 * @param (champ_rho) un champ de type Champ_Fonc_P0_VDF qui sera utilise lors des appels a "ajouter()" pour evaluer la masse volumique.
298 */
299
301{
302 // Il faut que le champ soit discretise aux elements: possibilite
303 // d'autoriser d'autres types si besoin (Champ_Don, Champ_Inc, etc.)
304 // du moment que c'est des champs P0.
305 if (!sub_type(Champ_Fonc_P0_VDF, champ_rho))
306 {
307 Cerr << "Erreur dans Terme_Source_Acceleration_VDF_Face::associer_champ_rho" << finl;
308 Cerr << " Le champ de masse volumique doit etre de type Champ_Fonc_P0_VDF" << finl;
309 Cerr << " Type du champ associe : " << champ_rho.que_suis_je() << finl;
310 Cerr << " Nom du champ associe : " << champ_rho.le_nom() << finl;
311 assert(0);
312 exit();
313 }
314 ref_rho_ = champ_rho;
315}
316
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
classe Champ_Fonc_P0_VDF
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 Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
class Domaine_Cl_VDF
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_VDF
Definition Domaine_VDF.h:64
int orientation(int) const override
inline DoubleVect& Domaine_VDF::porosite_face() {
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
double volumes(int i) const
Definition Domaine_VF.h:113
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
int premiere_face_int() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:463
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
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
virtual const Milieu_base & milieu() 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
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
const Champ_Inc_base & inconnue() const override
Renvoie la vitesse (champ inconnue de l'equation) (version const).
static int dimension
Definition Objet_U.h:99
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
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 void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Classe de base des flux de sortie.
Definition Sortie.h:52
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
Terme source d'acceleration specialise pour la discretisation VDF.
void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl) const override
Ajoute le terme (la_source_ * rho * volume_entrelace) au champ resu.
void associer_domaines(const Domaine_dis_base &, const Domaine_Cl_dis_base &) override
Methode appelee par Source_base::completer() apres associer_domaines Remplit les ref.
const DoubleTab & calculer_vitesse_faces(DoubleTab &v_faces_stockage) const override
Calcul des trois composantes du champ de vitesse fluide au centre de chaque face.
void associer_champ_rho(const Champ_base &champ_rho) override
Associe le champ de masse volumique=> Le terme source calcule sera alors homogene a d/dt(integrale(rh...
virtual const Navier_Stokes_std & get_eq_hydraulique() const
Renvoie eq_hydraulique_ !
const DoubleTab & calculer_la_source(DoubleTab &src_faces) const
Calcul de la valeur du champ la_source aux faces en fonction de - calculer_vitesse_faces().
virtual Champ_Fonc_base & get_set_terme_source_post() const
virtual void lire_data(Entree &s)
Methode appelee par readOn des classes derivees Terme_Source_Acceleration_VDF_Face,...