TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Perte_Charge_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 <Perte_Charge_VEF.h>
17#include <Schema_Temps_base.h>
18#include <Domaine_VEF.h>
19#include <Fluide_Incompressible.h>
20#include <Probleme_base.h>
21#include <Domaine.h>
22#include <Champ_Uniforme.h>
23#include <Sous_Domaine.h>
24#include <Sous_domaine_VF.h>
25#include <Sous_domaine_dis_base.h>
26#include <Champ_P1NC.h>
27#include <Check_espace_virtuel.h>
28#include <Champ_Don_Fonc_xyz.h>
29#include <Champ_Don_Fonc_txyz.h>
30#include <Param.h>
31
32Implemente_base_sans_constructeur(Perte_Charge_VEF,"Perte_Charge_VEF",Source_base);
33
34Perte_Charge_VEF::Perte_Charge_VEF():implicite_(1) { }
35
37{
38 return s << que_suis_je() << finl;
39}
40
42{
43 Param param(que_suis_je());
44 Cerr << que_suis_je() << "::readOn " << finl;
45 lambda.setNbVar(4+dimension);
46 set_param(param);
47 param.lire_avec_accolades_depuis(is);
48 Cerr << "Interpretation de la fonction " << lambda.getString() << " ... ";
49 lambda.parseString();
50 Cerr << " Ok" << finl;
51 if (diam_hydr->nb_comp()!=1)
52 {
53 Cerr << "Il faut definir le champ diam_hydr a une composante" << finl;
54 exit();
55 }
56 return is;
57}
58
60{
61 param.ajouter_non_std("lambda",(this),Param::REQUIRED);
62 param.ajouter("diam_hydr",&diam_hydr,Param::REQUIRED);
63 param.ajouter_non_std("sous_domaine|sous_zone",(this));
64 param.ajouter("implicite",&implicite_);
65}
66
68{
69 if (mot=="lambda")
70 {
71 Nom tmp;
72 is >> tmp;
73 lambda.setString(tmp);
74 lambda.addVar("Re");
75 lambda.addVar("t");
76 lambda.addVar("x");
77 if (dimension>1)
78 lambda.addVar("y");
79 if (dimension>2)
80 lambda.addVar("z");
81 return 1;
82 }
83 else if (mot=="sous_domaine")
84 {
85 is >> nom_sous_domaine;
86 sous_domaine=true;
87 return 1;
88 }
89 else // non compris
90 {
91 Cerr << "Mot cle \"" << mot << "\" non compris lors de la lecture d'un "
92 << que_suis_je() << finl;
93 exit();
94 }
95 return -1;
96}
97
98////////////////////////////////////////////////////////////////
99// //
100// Fonction principale : ajouter //
101// //
102////////////////////////////////////////////////////////////////
103
104namespace
105{
106double valeur_a_la_face(const Champ_Don_base& le_ch, const IntTab& f_e, int f)
107{
108 assert(le_ch.valeurs().line_size() == 1);
109 double s = 0.0, val = 0.0;
110 for (int i = 0, e; i < 2; i++)
111 if ((e = f_e(f, i)) > -1)
112 {
113 val += le_ch.valeurs()(e, 0);
114 s += 1.0;
115 }
116 val /= s;
117 return val;
118}
119}
120
121DoubleTab& Perte_Charge_VEF::ajouter(DoubleTab& resu) const
122{
123 const Domaine_VEF& zvef=le_dom_VEF.valeur();
124 const Champ_Don_base& nu=le_fluide->viscosite_cinematique(); // viscosite cinematique
125 const DoubleTab& xv=zvef.xv() ; // centres de gravite des faces
126 const DoubleTab& vit=la_vitesse->valeurs();
127 // Sinon segfault a l'initialisation de ssz quand il n'y a pas de sous-domaine !
128 const Sous_domaine_VF& ssz = sous_domaine ? le_sous_domaine_dis.valeur() : Sous_domaine_VF();
129 const IntTab& f_e = zvef.face_voisins();
130
131 // Parametres pour perte_charge()
132 DoubleVect u(dimension);
133 DoubleVect pos(dimension);
134 DoubleVect v_valeur(dimension);
135 // Optimisations pour les cas ou nu ou diam_hydr sont constants
136 const bool nu_constant = sub_type(Champ_Uniforme, nu), dh_constant = sub_type(Champ_Uniforme, diam_hydr.valeur()),
137 nu_xyz = sub_type(Champ_Don_Fonc_xyz, nu) || sub_type(Champ_Don_Fonc_txyz, nu),
138 dh_xyz = sub_type(Champ_Don_Fonc_xyz, diam_hydr.valeur()) || sub_type(Champ_Don_Fonc_txyz, diam_hydr.valeur());
139
140 // Le temps actuel
141 double t=equation().schema_temps().temps_courant();
142
143 // Nombre de faces a traiter.
144 int max_faces = sous_domaine ? ssz.les_faces().size() : zvef.nb_faces();
145
146 for (int face=0; face<max_faces; face++)
147 {
148 // indice de la face dans le domaine_VEF
149 int la_face = sous_domaine ? ssz.les_faces()[face] : face;
150
151 if (la_face<zvef.nb_faces())
152 {
153 // Recup la vitesse a la face, et en calcule le module
154 double norme_u=0;
155 for (int dim=0; dim<dimension; dim++)
156 {
157 u[dim]=vit(la_face,dim);
158 norme_u+=u[dim]*u[dim];
159 }
160 norme_u=sqrt(norme_u) ;
161
162 // Calcul de la position
163 for (int i=0; i<dimension; i++)
164 pos[i]=xv(la_face,i);
165
166 const double nu_valeur = nu_constant ? nu.valeurs()(0,0) : (nu_xyz ? nu.valeur_a_compo(pos,0) : ::valeur_a_la_face(nu, f_e, la_face));
167 const double dh_valeur = dh_constant ? diam_hydr->valeurs()(0,0) : (dh_xyz ? diam_hydr->valeur_a_compo(pos,0) : ::valeur_a_la_face(diam_hydr, f_e, la_face));
168
169 // Calcul du reynolds
170 double reynolds=norme_u*dh_valeur/nu_valeur;
171 // Lambda est souvent indetermine pour Re->0
172 if (reynolds < 1.e-10)
173 reynolds=1e-10;
174
175 // Calcul du volume d'integration
176 double volume=sous_domaine?
177 ssz.volumes_entrelaces(face) :
178 zvef.volumes_entrelaces(la_face);
179 volume*=equation().milieu().porosite_face(la_face);
180
181 // Calcul du resultat final (ouf)
182 double coeff_ortho,coeff_long,u_l;
183 coeffs_perte_charge(u,pos,t,norme_u,dh_valeur,nu_valeur,reynolds,coeff_ortho,coeff_long,u_l,v_valeur);
184 for (int dim=0; dim<dimension; dim++)
185 {
186 // La perte de charge vaut -coeff_long*u_l*v_valeur[dim] -coeff_ortho(u[dim] -u_v*v_valeur[dim])
187 // soit -coeff_ortho* u[dim] - (coeff_long-coeff_ortho)* u_l*v_valeur[dim]
188 resu(la_face,dim)-=(coeff_ortho* u[dim] + (coeff_long-coeff_ortho)* u_l*v_valeur[dim])*volume;
189 }
190 }
191 }
192 return resu;
193}
194
195/*! @brief copie de ajouter sauf la derniere ligne
196 *
197 */
198void Perte_Charge_VEF::contribuer_a_avec(const DoubleTab& inco, Matrice_Morse& matrice) const
199{
200 if (implicite_==0) return; // La perte de charge n'est pas implicitee, on quitte
201
202 // Raccourcis
203 const Champ_Don_base& nu=le_fluide->viscosite_cinematique(); // viscosite cinematique
204 const DoubleTab& xv=le_dom_VEF->xv() ; // centres de gravite des faces
205 const DoubleTab& vit=la_vitesse->valeurs();
206 // Sinon segfault a l'initialisation de ssz quand il n'y a pas de sous-domaine !
207 const Sous_domaine_VF& ssz=sous_domaine?le_sous_domaine_dis.valeur():Sous_domaine_VF();
208 const Domaine_VEF& zvef=le_dom_VEF.valeur();
209 const IntTab& f_e = zvef.face_voisins();
210
211 // Parametres pour perte_charge()
212 DoubleVect u(dimension);
213 double norme_u;
214 double reynolds;
215 DoubleVect pos(dimension);
216 DoubleVect v_valeur(dimension);
217 // Optimisations pour les cas ou nu ou diam_hydr sont constants
218 const bool nu_constant = sub_type(Champ_Uniforme, nu), dh_constant = sub_type(Champ_Uniforme, diam_hydr.valeur()),
219 nu_xyz = sub_type(Champ_Don_Fonc_xyz, nu) || sub_type(Champ_Don_Fonc_txyz, nu),
220 dh_xyz = sub_type(Champ_Don_Fonc_xyz, diam_hydr.valeur()) || sub_type(Champ_Don_Fonc_txyz, diam_hydr.valeur());
221
222 // Le temps actuel
223 double t=equation().schema_temps().temps_courant();
224
225 // Nombre de faces a traiter.
226 int max_faces=sous_domaine?
227 ssz.les_faces().size() :
228
229 zvef.nb_faces();
230
231 // To ensure that nu_valeur will not be zero
232 // and not have a division by zero for the calculation of Reynolds
233 assert_espace_virtuel_vect(nu.valeurs());
234
235 for (int face=0; face<max_faces; face++)
236 {
237
238 // indice de la face dans le domaine_VEF
239 int la_face=sous_domaine?
240 ssz.les_faces()[face] :
241 face;
242
243 // Fixed bug by GF: si la face est une face virtuelle on passe, car nu mal calcule et coef(no,no) invalide
244 if (la_face>=zvef.nb_faces())
245 continue;
246
247 // Recup la vitesse a la face, et en calcule le module
248 norme_u=0;
249 for (int dim=0; dim<dimension; dim++)
250 {
251 u[dim]=vit(la_face,dim);
252 norme_u+=u[dim]*u[dim];
253 }
254 norme_u=sqrt(norme_u) ;
255
256 // Calcul de la position
257 for (int i=0; i<dimension; i++)
258 pos[i]=xv(la_face,i);
259
260 const double nu_valeur = nu_constant ? nu.valeurs()(0,0) : (nu_xyz ? nu.valeur_a_compo(pos,0) : ::valeur_a_la_face(nu, f_e, la_face));
261 const double dh_valeur = dh_constant ? diam_hydr->valeurs()(0,0) : (dh_xyz ? diam_hydr->valeur_a_compo(pos,0) : ::valeur_a_la_face(diam_hydr, f_e, la_face));
262
263 // Calcul du reynolds
264 reynolds=norme_u*dh_valeur/nu_valeur;
265 // Lambda est souvent indetermine pour Re->0
266 if (reynolds < 1.e-10)
267 reynolds=1e-10;
268
269 // Calcul du volume d'integration
270 double volume=sous_domaine?
271 ssz.volumes_entrelaces(face) :
272 zvef.volumes_entrelaces(la_face);
273 volume*=equation().milieu().porosite_face(la_face);
274
275 // Calcul du resultat final (ouf)
276 double coeff_ortho,coeff_long,u_l;
277 coeffs_perte_charge(u,pos,t,norme_u,dh_valeur,nu_valeur,reynolds,coeff_ortho,coeff_long,u_l,v_valeur);
278 for (int dim=0; dim<dimension; dim++)
279 {
280 int n0=la_face*dimension+dim;
281 // matrice.coef(n0,n0) += (coeff_ortho + (coeff_long-coeff_ortho)* v_valeur[dim]*v_valeur[dim]); // Fixed bug
282 matrice.coef(n0,n0) += (coeff_ortho + (coeff_long-coeff_ortho)* v_valeur[dim]*v_valeur[dim])*volume;
283 // La perte de charge vaut -coeff_long*u_l*v_valeur[dim] -coeff_ortho(u[dim] -u_v*v_valeur[dim])
284 // soit -coeff_ortho* u[dim] - (coeff_long-coeff_orho)* u_l*v_valeur[dim]
285 // resu(la_face,dim)-=(coeff_ortho* u[dim] + (coeff_long-coeff_orho)* u_l*v_valeur[dim]);
286 }
287 }
288}
289
290DoubleTab& Perte_Charge_VEF::calculer(DoubleTab& resu) const
291{
292 resu=0;
293 return ajouter(resu);
294}
295
296
298{
300
301 if (sous_domaine)
302 {
303 sous_domaine=false;
304 const Sous_Domaine& le_sous_domaine=equation().probleme().domaine().ss_domaine(nom_sous_domaine);
305 const Domaine_dis_base& le_domaine_dis=le_dom_VEF.valeur();
306 for (int ssz=0; ssz<le_domaine_dis.nombre_de_sous_domaines_dis(); ssz++)
307 {
308 if (le_domaine_dis.sous_domaine_dis(ssz).sous_domaine().est_egal_a(le_sous_domaine))
309 {
310 sous_domaine=true;
311 le_sous_domaine_dis=ref_cast(Sous_domaine_VF,le_domaine_dis.sous_domaine_dis(ssz));
312 }
313 }
314
315 if(!sous_domaine)
316 {
317 Cerr << "On ne trouve pas le sous_domaine discretise associe a " << nom_sous_domaine << finl;
318 exit();
319 }
320 }
321}
322
323////////////////////////////////////////////////////////////////
324// //
325// Fonctions virtuelles pures de Source_base //
326// //
327////////////////////////////////////////////////////////////////
328
329
331{
332 la_vitesse = ref_cast(Champ_P1NC,equation().inconnue());
333 le_fluide = ref_cast(Fluide_base,equation().milieu());
334}
335
337 const Domaine_Cl_dis_base& domaine_Cl_dis)
338{
339 le_dom_VEF = ref_cast(Domaine_VEF, domaine_dis);
340 le_dom_Cl_VEF = ref_cast(Domaine_Cl_VEF, domaine_Cl_dis);
341}
class Champ_Don_Fonc_txyz Cette classe represente un champ de donnees fonction
class Champ_Don_Fonc_xyz Cette classe represente un champ de donnees fonction
classe Champ_Don_base classe de base des Champs donnes (non calcules)
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
classe Champ_Uniforme Represente un champ constant dans l'espace et dans le temps.
virtual double valeur_a_compo(const DoubleVect &position, int ncomp) const
Calcule la valeur ponctuelle de la composante "compo" du champ au point de coordonnees pos.
const Sous_Domaine_t & ss_domaine(int i) const
Definition Domaine.h:290
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 nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
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 nombre_de_sous_domaines_dis() const
const Sous_domaine_dis_base & sous_domaine_dis(int i) 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
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
Schema_Temps_base & schema_temps()
Renvoie le schema en temps associe a l'equation.
classe Fluide_base Cette classe represente un d'un fluide incompressible ainsi que
Definition Fluide_base.h:38
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
double coef(int i, int j) 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
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 Entree
Definition Objet_U.h:76
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 int est_egal_a(const Objet_U &) const
Renvoie 1 si l'objet x et *this sont une seule et meme instance (meme adresse en memoire).
Definition Objet_U.cpp:301
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ REQUIRED
Definition Param.h:115
void ajouter_non_std(const char *keyword, const Objet_U *value, Param::Nature nat=Param::OPTIONAL)
Register a keyword handled by Objet_U::lire_motcle_non_standard.
Definition Param.cpp:489
Factorise les fonctionnalites de plusieurs pertes de charge en VEF, vitesse aux faces.
int lire_motcle_non_standard(const Motcle &, Entree &) override
Lecture des parametres de type non simple d'un objet_U a partir d'un flot d'entree.
DoubleTab & calculer(DoubleTab &) const override
virtual void set_param(Param &param) const override
void contribuer_a_avec(const DoubleTab &, Matrice_Morse &) const override
copie de ajouter sauf la derniere ligne
void associer_pb(const Probleme_base &) override
associe le_fluide et la_vitesse
DoubleTab & ajouter(DoubleTab &) const override
Appelle perte_charge pour chaque face ou cela est necessaire.
Nom nom_sous_domaine
Nom du sous-domaine, initialise dans readOn().
virtual void coeffs_perte_charge(const DoubleVect &u, const DoubleVect &pos, double t, double norme_u, double dh, double nu, double reynolds, double &coeff_ortho, double &coeff_long, double &u_l, DoubleVect &v_valeur) const =0
Appele pour chaque face par ajouter().
void associer_domaines(const Domaine_dis_base &, const Domaine_Cl_dis_base &) override
associe le_dom_VEF et le_dom_Cl_VEF
void completer() override
Met a jour les references internes a l'objet Source_base.
bool sous_domaine
Le terme est-il limite a un sous-domaine ?
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
const Domaine & domaine() const
Renvoie le domaine associe au probleme.
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
double temps_courant() const
Renvoie le temps courant.
Classe de base des flux de sortie.
Definition Sortie.h:52
classe Source_base Un objet Source_base est un terme apparaissant au second membre d'une
Definition Source_base.h:42
virtual void completer()
Met a jour les references internes a l'objet Source_base.
Cette classe abstraite contient les informations geometrique de sous-domaine communes aux methodes de...
const IntTab & les_faces() const
double volumes_entrelaces(int) const
Renvoie le volume entrelace restreint au sous-domaine. face est l'indice dans le tableau les_faces_.
const Sous_Domaine & sous_domaine() const
_SIZE_ size() const
Definition TRUSTVect.tpp:45
int line_size() const
Definition TRUSTVect.tpp:67