TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Loi_Etat_Multi_GP_QC.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 <Loi_Etat_Multi_GP_QC.h>
17#include <Champ_Uniforme.h>
18#include <Probleme_base.h>
19#include <Champ_Inc_base.h>
20#include <TRUSTTab.h>
21#include <Domaine_VF.h>
22#include <Debog.h>
23#include <Param.h>
24
25Implemente_instanciable_sans_constructeur(Loi_Etat_Multi_GP_QC,"Loi_Etat_Multi_Gaz_Parfait_QC",Loi_Etat_Multi_GP_base);
26// XD multi_gaz_parfait_QC loi_etat_gaz_parfait_base multi_gaz_parfait_QC INHERITS_BRACE Class for perfect gas
27// XD_CONT multi-species mixtures state law used with a quasi-compressible fluid.
28
30
32{
33 os <<que_suis_je()<< finl;
34 return os;
35}
36
38{
39 Param param(que_suis_je());
40 param.ajouter("Sc",&Sc_,Param::REQUIRED); // XD_ADD_P double
41 // XD_CONT Schmidt number of the gas Sc=nu/D (D: diffusion coefficient of the mixing).
42 param.ajouter( "Prandtl",&Pr_,Param::REQUIRED); // XD_ADD_P double
43 // XD_CONT Prandtl number of the gas Pr=mu*Cp/lambda
44 param.ajouter( "Cp",&Cp_); // XD_ADD_P double
45 // XD_CONT Specific heat at constant pressure of the gas Cp.
46 param.ajouter( "dtol_fraction",&dtol_fraction_); // XD_ADD_P double
47 // XD_CONT Delta tolerance on mass fractions for check testing (default value 1.e-6).
48 param.ajouter_flag( "correction_fraction",&correction_fraction_); // XD_ADD_P flag
49 // XD_CONT To force mass fractions between 0. and 1.
50 param.ajouter_flag( "ignore_check_fraction",&ignore_check_fraction_); // XD_ADD_P flag
51 // XD_CONT Not to check if mass fractions between 0. and 1.
52 param.lire_avec_accolades_depuis(is);
53 return is;
54}
55
56/*! @brief Associe les proprietes physiques d une espece a la loi d'etat
57 *
58 * @param (eq)
59 */
61{
62 liste_especes.add(eq.espece());
63}
64
65/*! @brief Calcule la masse molaire du melange (M) M depend de la mase molaire de chaque espece et de la composition du melange (Yi)
66 *
67 */
68void Loi_Etat_Multi_GP_QC::calculer_masse_molaire(DoubleTab& tab_masse_mol_mel) const
69{
70 const int size = tab_masse_mol_mel.size();
71 ArrOfDouble inv_M(size), numer_M(size);
72
73 for (int i=0; i<liste_Y.size(); i++)
74 {
75 double M_i=liste_especes(i)->masse_molaire();
76 const DoubleTab& Y_i=liste_Y(i)->valeurs();
77 double min_Y_i=local_min_vect(Y_i);
78 double max_Y_i=local_max_vect(Y_i);
79 if ((min_Y_i<0.-dtol_fraction_)||(max_Y_i>1.+dtol_fraction_))
80 {
81 Cerr << "Warning : (min_Y_i<-" << dtol_fraction_ << ")||(max_Y_i>1+" << dtol_fraction_ <<") for the " << i << "th mass fraction:" << finl;
82 Cerr << " min_Y_i = " << min_Y_i << finl;
83 Cerr << " max_Y_i = " << max_Y_i << finl;
85 }
86 for (int elem=0; elem<size; elem++)
87 {
88 numer_M[elem] += Y_i(elem,0);
89 inv_M[elem] += Y_i(elem,0)/M_i;
90 }
91 }
92
93 assert(liste_Y(0)->valeurs().size()==size);
94
95 for (int elem=0; elem<size; elem++)
96 if (inv_M[elem]>1.e-8)
97 tab_masse_mol_mel(elem,0) = numer_M[elem] / inv_M[elem];
98}
99
100/*! @brief Calcule le Cp du melange Le Cp depend du Cp de chaque espece et de la composition du melange (Yi)
101 *
102 */
103void Loi_Etat_Multi_GP_QC::calculer_tab_Cp(DoubleTab& tab_Cp) const
104{
105 // FIXME : Actuellement on suppose que Cp est pris constant pour chacune des especes
106 tab_Cp=0;
107 for (int i=0; i<liste_Y.size(); i++)
108 {
109 const DoubleTab& Y_i=liste_Y(i)->valeurs();
110 const double cp_i=liste_especes(i)->capacite_calorifique().valeurs()(0,0);
111 assert(cp_i>0);
112 for (int elem=0; elem<Y_i.size(); elem++) tab_Cp(elem,0) += Y_i(elem,0)*cp_i;
113 }
114}
115
116/*! @brief Corrections explicites pour les fractions massiques pour forcer la somme a 1 et sans valeurs negatives
117 *
118 */
120{
121 DoubleTab test( liste_Y(0)->valeurs()) ;
122 test=0;
123
124 for (int i=0; i<liste_Y.size(); i++)
125 {
126 DoubleTab& Y_i=liste_Y(i)->futur(futur);
127 double min_Y_i=local_min_vect(Y_i);
128 double max_Y_i=local_max_vect(Y_i);
129 Cerr << "Verification of the " << i << "th mass fraction:" << finl;
130 Cerr << " min_Y_i = " << min_Y_i << finl;
131 Cerr << " max_Y_i = " << max_Y_i << finl;
132 if ((min_Y_i<0.-dtol_fraction_)||(max_Y_i>1.+dtol_fraction_))
133 {
134 Cerr << " Warning : (min_Y_i<-" << dtol_fraction_ << ")||(max_Y_i>1+" << dtol_fraction_ <<")" << finl;
136 }
137 for (int elem=0; elem<Y_i.size(); elem++)
138 {
139 if (Y_i(elem,0)<0.)
140 {
141 Y_i(elem,0)=0.;
142 Cerr << " Y_i forced to " << Y_i(elem,0) << " on node " << elem << finl;
143 }
144 if (Y_i(elem,0)>1.)
145 {
146 Y_i(elem,0)=1.;
147 Cerr << " Y_i forced to " << Y_i(elem,0) << " on node " << elem << finl;
148 }
149 }
150 test+=Y_i;
151 }
152 double min_s=mp_min_vect(test);
153 double max_s=mp_max_vect(test);
154 Cerr << "Verification of the sum of the mass fractions:" << finl;
155 Cerr << " Sum(min_Y_i) = " << min_s << finl;
156 Cerr << " Sum(max_Y_i) = " << max_s << finl;
157 for (int i=0; i<liste_Y.size(); i++)
158 {
159 DoubleTab& Y_i=liste_Y(i)->futur(futur);
160 for (int elem=0; elem<Y_i.size(); elem++) Y_i(elem,0)/=(test(elem)+DMINFLOAT);
161 }
162 if ((!est_egal(min_s,1.,dtol_fraction_))||(!est_egal(max_s,1.,dtol_fraction_)))
163 {
164 Cerr << " Warning: the sum of the mass fractions is not equal to 1." <<finl;
166 }
167}
168
169/*! @brief Recalcule la masse volumique
170 *
171 */
173{
174 const DoubleTab& tab_ICh = le_fluide->inco_chaleur().valeurs();
175 DoubleTab& tab_rho = le_fluide->masse_volumique().valeurs();
176
178
180
181 double Pth = le_fluide->pression_th();
182 int n = tab_rho.size();
183 for (int som=0 ; som<n ; som++)
184 {
185 double r = 8.3143 / masse_mol_mel(som);
186 tab_rho_np1(som) = calculer_masse_volumique(Pth,tab_ICh(som,0),r);
187 tab_rho(som,0) = 0.5 * ( tab_rho_n(som) + tab_rho_np1(som) );
188 }
189 const Champ_base& rho_m=le_fluide->get_champ("rho_gaz");
190 ref_cast_non_const(DoubleTab,rho_m.valeurs())=tab_rho_np1;
191 tab_rho.echange_espace_virtuel();
192 tab_rho_np1.echange_espace_virtuel();
193 le_fluide->calculer_rho_face(tab_rho_np1);
194 Debog::verifier("Loi_Etat_Multi_GP_QC::calculer_masse_volumique, tab_rho_np1",tab_rho_np1);
195 Debog::verifier("Loi_Etat_Multi_GP_QC::calculer_masse_volumique, tab_rho",tab_rho);
196}
197
198double Loi_Etat_Multi_GP_QC::calculer_masse_volumique(double P, double T, double r) const
199{
201}
202
207
208/*! @brief Calcule la viscosite dynamique de reference (depend des Yi)
209 *
210 * With Wilke formulation: https://aip.scitation.org/doi/pdf/10.1063/1.1747673
211 * See also for mass fractions : https://doi.org/10.1016/j.ijheatmasstransfer.2020.120470
212 *
213 *
214 * Mu =
215 *
216 * N
217 * ______
218 * \ `
219 * \ Mu_i*Y_i
220 * \ ----------------
221 * \ N
222 * \ __
223 * / \ `
224 * / ) Phi_ij*Y_j
225 * / /_,
226 * / j = 1
227 * /_____,
228 * i = 1
229 *
230 *
231 * where Phi_ij =
232 *
233 * 2
234 * / 0.25 ______ \
235 * |/M_j\ / Mu_i |
236 * M_i*||---| * / ---- + 1|
237 * \\M_i/ \/ Mu_j /
238 * -------------------------------
239 * ___________
240 * / 8*M_i
241 * M_j* / ----- + 8
242 * \/ M_j
243 *
244 *
245 */
247{
248 const int size = liste_Y(0)->valeurs().size(), list_size = liste_Y.size();
249 DoubleTrav phi(size), mu(size);
250 mu = 0.;
251 phi = 0.;
252
253 for (int i = 0; i < list_size; i++)
254 {
255 phi = 0.;
256 const double M_i = liste_especes(i)->masse_molaire();
257 const double mu_i = liste_especes(i)->viscosite_dynamique().valeurs()(0, 0);
258
259 for (int j = 0; j < list_size; j++)
260 if (j != i) // sinon phi_ii = 1
261 {
262 const double M_j = liste_especes(j)->masse_molaire();
263 const double mu_j = liste_especes(j)->viscosite_dynamique().valeurs()(0, 0);
264
265 double a = 1. + sqrt(mu_i / mu_j) * pow(M_j / M_i, 0.25);
266 double b = sqrt(8. * (1. + (M_i / M_j)));
267 double phi_ij = ( M_i / M_j ) * a * a / b;
268
269 const DoubleVect& y_j = liste_Y(j)->valeurs();
270 // node is elem (VDF) or face (VEF)
271 for (int node = 0; node < y_j.size(); node++) phi(node) += y_j(node) * phi_ij;
272 }
273 // We add the mass fraction when i = j
274 const DoubleVect& y_i = liste_Y(i)->valeurs();
275 for (int node = 0; node < y_i.size(); node++) mu(node) += mu_i * y_i(node) / (y_i(node) + phi(node));
276 }
277
278 calculer_tab_mu(mu, size);
279}
280
281/*! @brief Calcule la viscosite dynamique sur Schmidt
282 *
283 */
285{
286 const Champ_Don_base& mu = le_fluide->viscosite_dynamique();
287 const DoubleTab& tab_mu = mu.valeurs();
288 Champ_Don_base& mu_sur_Sc = le_fluide->mu_sur_Schmidt();
289 DoubleTab& tab_mu_sur_Sc = mu_sur_Sc.valeurs();
290
291 if (!sub_type(Champ_Uniforme,mu_sur_Sc))
292 {
293 const int n = tab_mu_sur_Sc.size();
294 if (sub_type(Champ_Uniforme,mu))
295 for (int i=0 ; i<n ; i++) tab_mu_sur_Sc(i,0) = tab_mu(0,0) / Sc_;
296 else
297 for (int i=0 ; i<n ; i++) tab_mu_sur_Sc(i,0) = tab_mu(i,0)/Sc_;
298 }
299 else //mu_sur_Sc uniforme
300 tab_mu_sur_Sc(0,0) = tab_mu(0,0) / Sc_;
301
302 double temps_champ = mu.temps();
303 mu_sur_Sc.changer_temps(temps_champ);
304 tab_mu_sur_Sc.echange_espace_virtuel();
305}
classe Champ_Don_base classe de base des Champs donnes (non calcules)
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
virtual DoubleTab & valeurs()=0
classe Champ_Uniforme Represente un champ constant dans l'espace et dans le temps.
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
virtual double changer_temps(const double t)
Fixe le temps auquel se situe le champ.
double temps() const
Renvoie le temps du champ.
classe Convection_Diffusion_Espece_Multi_QC Cas particulier de Convection_Diffusion_Espece_Multi_base
static void verifier(const char *const msg, double)
Definition Debog.cpp:21
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
classe Loi_Etat_Multi_GP_QC Cette classe represente la loi d'etat pour un melange de gaz parfaits.
void calculer_masse_volumique() override
Recalcule la masse volumique.
void calculer_tab_Cp(DoubleTab &cp) const override
Calcule le Cp du melange Le Cp depend du Cp de chaque espece et de la composition du melange (Yi).
void rabot(int futur=0)
Corrections explicites pour les fractions massiques pour forcer la somme a 1 et sans valeurs negative...
void calculer_mu_sur_Sc() override
Calcule la viscosite dynamique sur Schmidt.
void associer_espece(const Convection_Diffusion_Espece_Multi_QC &eq)
Associe les proprietes physiques d une espece a la loi d'etat.
classe Loi_Etat_Multi_GP_base Cette classe represente la loi d'etat pour un melange de gaz parfaits.
void calculer_masse_volumique() override=0
Recalcule la masse volumique.
virtual void calculer_mu_wilke()=0
void calculer_tab_mu(const DoubleTab &mu, int size)
DoubleTab tab_rho_np1
DoubleTab tab_rho_n
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
@ REQUIRED
Definition Param.h:115
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ size() const
Definition TRUSTVect.tpp:45
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")