TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Loi_Etat_Multi_GP_WC.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 <Fluide_Weakly_Compressible.h>
17#include <Loi_Etat_Multi_GP_WC.h>
18#include <Champ_Uniforme.h>
19
20#include <Probleme_base.h>
21#include <Domaine_VF.h>
22#include <Param.h>
23#include <Debog.h>
24
25Implemente_instanciable_sans_constructeur(Loi_Etat_Multi_GP_WC,"Loi_Etat_Multi_Gaz_Parfait_WC",Loi_Etat_Multi_GP_base);
26// XD multi_gaz_parfait_WC loi_etat_gaz_parfait_base multi_gaz_parfait_WC INHERITS_BRACE Class for perfect gas
27// XD_CONT multi-species mixtures state law used with a weakly-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("Species_number",&num_espece_,Param::REQUIRED); // XD_ADD_P entier
41 // XD_CONT Number of species you are considering in your problem.
42 param.ajouter("Diffusion_coeff",&diffusion_coeff_,Param::REQUIRED); // XD_ADD_P field_base
43 // XD_CONT Diffusion coefficient of each species, defined with a Champ_uniforme of dimension equals to the
44 // XD_CONT species_number.
45 param.ajouter("Molar_mass",&molar_mass_,Param::REQUIRED); // XD_ADD_P field_base
46 // XD_CONT Molar mass of each species, defined with a Champ_uniforme of dimension equals to the species_number.
47 param.ajouter("Mu",&mu_,Param::REQUIRED); // XD_ADD_P field_base
48 // XD_CONT Dynamic viscosity of each species, defined with a Champ_uniforme of dimension equals to the species_number.
49 param.ajouter("Cp",&cp_,Param::REQUIRED);// XD_ADD_P field_base
50 // XD_CONT Specific heat at constant pressure of the gas Cp, defined with a Champ_uniforme of dimension equals to the
51 // XD_CONT species_number..
52 param.ajouter("Prandtl",&Pr_,Param::REQUIRED); // XD_ADD_P double
53 // XD_CONT Prandtl number of the gas Pr=mu*Cp/lambda.
54 param.lire_avec_accolades_depuis(is);
55
56 // XXX
57 if (diffusion_coeff_->valeurs().line_size() != num_espece_ ||
58 molar_mass_->valeurs().line_size() != num_espece_ ||
59 mu_->valeurs().line_size() != num_espece_ ||
60 cp_->valeurs().line_size() != num_espece_ )
61 {
62 Cerr << "Error while reading the EOS Multi_Gaz_Parfait_WC : This is not allowed !" << finl;
63 Cerr << "Verify that the dimension of the fields Diffusion_coeff, Molar_mass, Mu and Cp is = " << num_espece_ << finl;
65 }
66
67 return is;
68}
69
71{
72 /*
73 * XXX : In this problem we solve n-1 equations for n species
74 * The mass fraction of species n is [ 1 - (y1+y2+ ... +yn-1) ]
75 */
76
77 if (liste_Y.size() + 1 != num_espece_ )
78 {
79 Cerr << "Error in your data file : This is not allowed !" << finl;
80 Cerr << "You should define " << num_espece_-1 << " Species equations and not " << liste_Y.size() << finl;
82 }
83
84 Fluide_Weakly_Compressible& FWC = ref_cast(Fluide_Weakly_Compressible,le_fluide.valeur());
86 Yn.nommer("fraction_massique_nonresolue");
87 double t = le_fluide->masse_volumique().temps(); // pas 0 car reprise pt etre
88 update_Yn_values(Yn,t);
90}
91
92void Loi_Etat_Multi_GP_WC::update_Yn_values(Champ_Don_base& Yn, double temps)
93{
94 DoubleTab& tab_Yn = Yn.valeurs();
95 Yn.mettre_a_jour(temps);
96 tab_Yn = 1.0;// re-initialize as 1
97 const int size = liste_Y(0)->valeurs().size();
98 assert(tab_Yn.size() == size);
99 assert (liste_Y.size() + 1 == num_espece_);
100
101 for (int i=0; i<liste_Y.size(); i++)
102 for (int n=0; n<size; n++) tab_Yn(n,0) -= liste_Y(i)->valeurs()(n,0);
103
104 double min_Yn = local_min_vect(tab_Yn);
105 if (min_Yn < 0)
106 {
107 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
108 Cerr << "BIG PROBLEM : check your calculation because we are detecting negative mass fraction !" << finl;
109 Cerr << "The results are saved to help you !" << finl;
110 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
111 Fluide_Weakly_Compressible& FWC = ref_cast(Fluide_Weakly_Compressible,le_fluide.valeur());
112 Probleme_base& pb = FWC.get_problem();
113 pb.postraiter(1);
114 pb.sauver();
116 }
117}
118
119/*! @brief Calcule la masse molaire du melange (M) M depend de la mase molaire de chaque espece et de la composition du melange (Yi)
120 *
121 */
122void Loi_Etat_Multi_GP_WC::calculer_masse_molaire(DoubleTab& tab_masse_mol_mel) const
123{
124 assert (sub_type(Champ_Uniforme,masse_molaire_especes()));
125
126 const int size = tab_masse_mol_mel.size();
127 assert (liste_Y(0)->valeurs().size()==size);
128 ArrOfDouble inv_M(size);
129
130 const Fluide_Weakly_Compressible& FWC = ref_cast(Fluide_Weakly_Compressible,le_fluide.valeur());
131 const DoubleTab& Yn = FWC.fraction_massique_nonresolue().valeurs();
132
133 for (int i=0; i < num_espece_; i++)
134 {
135 const DoubleTab& Y_i = (i == num_espece_ -1) ? Yn : liste_Y(i)->valeurs();
136 const double M_i = masse_molaire_especes().valeurs()(0,i);
137 for (int elem=0; elem<size; elem++) inv_M[elem] += Y_i(elem,0)/M_i;
138 }
139
140 for (int elem=0; elem<size; elem++) tab_masse_mol_mel(elem,0) = 1.0 / inv_M[elem];
141}
142
143/*! @brief Calcule le Cp du melange Le Cp depend du Cp de chaque espece et de la composition du melange (Yi)
144 *
145 */
146void Loi_Etat_Multi_GP_WC::calculer_tab_Cp(DoubleTab& tab_Cp) const
147{
148 // FIXME : Actuellement on suppose que Cp est pris constant pour chacune des especes
149 assert (sub_type(Champ_Uniforme,cp_especes()));
150
151 tab_Cp = 0;
152 const int size =liste_Y(0)->valeurs().size();
153
154 const Fluide_Weakly_Compressible& FWC = ref_cast(Fluide_Weakly_Compressible,le_fluide.valeur());
155 const DoubleTab& Yn = FWC.fraction_massique_nonresolue().valeurs();
156
157 for (int i=0; i<num_espece_; i++)
158 {
159 // TODO : FIXME : a voir si Yn.valeurs() est a jour
160 const DoubleTab& Y_i = (i == num_espece_ -1) ? Yn : liste_Y(i)->valeurs();
161 const double cp_i = cp_especes().valeurs()(0,i);
162 for (int elem=0; elem<size; elem++) tab_Cp(elem,0) += Y_i(elem,0)*cp_i;
163 }
164}
165
166/*! @brief Recalcule la masse volumique
167 *
168 */
170{
171 const DoubleTab& tab_ICh = le_fluide->inco_chaleur().valeurs();
172 DoubleTab& tab_rho = le_fluide->masse_volumique().valeurs();
173
174 Fluide_Weakly_Compressible& FWC = ref_cast(Fluide_Weakly_Compressible,le_fluide.valeur());
176 double temps = le_fluide->masse_volumique().temps();
177 update_Yn_values(Yn,temps); // XXX : a voir si l'appel est dans le bon endroit ...
179
180 assert (tab_rho.line_size() == 1);
181 const int n = tab_rho.size();
182 const DoubleTab& pres = FWC.pression_th_tab();
183
184 for (int som=0 ; som<n ; som++)
185 {
186 double r = R_GAS / masse_mol_mel(som);
187 tab_rho_np1(som) = calculer_masse_volumique(pres(som,0),tab_ICh(som,0),r);
188 tab_rho(som,0) = 0.5 * ( tab_rho_n(som) + tab_rho_np1(som) );
189 }
190
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_WC::calculer_masse_volumique, tab_rho_np1",tab_rho_np1);
195 Debog::verifier("Loi_Etat_Multi_GP_WC::calculer_masse_volumique, tab_rho",tab_rho);
196}
197
198double Loi_Etat_Multi_GP_WC::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 assert (liste_Y.size() + 1 == num_espece_);
249 const int size = liste_Y(0)->valeurs().size();
250 DoubleTrav phi(size), mu(size);
251 mu = 0.;
252 phi = 0.;
253
254 Fluide_Weakly_Compressible& FWC = ref_cast(Fluide_Weakly_Compressible,le_fluide.valeur());
255 DoubleTab& Yn = FWC.fraction_massique_nonresolue().valeurs();
256
257 for (int i=0; i < num_espece_ ; i++)
258 {
259 phi = 0.;
260 const double M_i = masse_molaire_especes().valeurs()(0,i);
261 const double mu_i = visc_dynamique_especes().valeurs()(0,i);
262
263 for (int j=0; j < num_espece_ ; j++)
264 if (j != i) // sinon phi_ii = 1
265 {
266 const double M_j = masse_molaire_especes().valeurs()(0,j);
267 const double mu_j = visc_dynamique_especes().valeurs()(0,j);
268
269 double a = 1. + sqrt( mu_i / mu_j ) * pow( M_j / M_i , 0.25);
270 double b = sqrt( 8. * ( 1. + ( M_i / M_j )));
271 double phi_ij = ( M_i / M_j ) * a * a / b;
272 // TODO : FIXME : a voir si Yn.valeurs() est a jour
273 const DoubleTab& y_j = (j == num_espece_ -1) ? Yn : liste_Y(j)->valeurs();
274 // node is elem (VDF) or face (VEF)
275 for (int node=0; node<y_j.size(); node++) phi(node) += y_j(node,0) * phi_ij;
276 }
277 // We add the mass fraction when i = j
278 const DoubleTab& y_i = (i == num_espece_ -1) ? Yn : liste_Y(i)->valeurs();
279 for (int node=0; node<y_i.size(); node++) mu(node) += mu_i * y_i(node,0) / ( y_i(node,0) + phi(node) );
280 }
281
282 calculer_tab_mu(mu, size);
283}
284
285/*! @brief Calcule la viscosite dynamique sur Schmidt = rho * D
286 *
287 */
289{
290 /*
291 * ====================================================================
292 * Schmidt number : Sc = nu / D = mu / ( rho * D )
293 * => rho * D = mu/Sc
294 * species equation : div ( rho * D * grad Y1) = div ( mu/Sc * grad Y1)
295 * ====================================================================
296 */
297
298 Champ_Don_base& mu_sur_Sc = le_fluide->mu_sur_Schmidt();
299 DoubleTab& tab_mu_sur_Sc = mu_sur_Sc.valeurs();
300 const Champ_base& rho = le_fluide->masse_volumique();
301 const DoubleTab& tab_rho = rho.valeurs();
302 const int n = tab_mu_sur_Sc.size();
303
304 // TODO : FIXME : On a tab_mu_sur_Sc.line_size() = 1 :( :/ :(
305 // BUG : il faut avoir line_size = num_espece_ car on peut avoir D qui varie entre espece
306
307 if (!sub_type(Champ_Uniforme,mu_sur_Sc))
308 {
309 if (sub_type(Champ_Uniforme,rho))
310 {
311 Cerr << "We should not have a density field of type Champ_Uniforme !" << finl;
313 }
314 else
315 for (int i=0 ; i<n ; i++)
316 {
317 // TODO : FIXME : j'ai pris D de l'espece 1 ...
318 tab_mu_sur_Sc(i,0) = tab_rho(i,0) * coeff_diffusion_especes().valeurs()(0,0);
319 }
320 }
321 else
322 {
323 Cerr << "We should not have a mu_sur_Sc of type Champ_Uniforme !" << finl;
325 }
326
327 mu_sur_Sc.changer_temps(rho.temps());
328 tab_mu_sur_Sc.echange_espace_virtuel();
329}
330
331/*! @brief Calcule la viscosite dynamique sur Schmidt = D
332 *
333 */
335{
336 /*
337 * ====================================================================
338 * Schmidt number : Sc = nu / D
339 * => D = nu/Sc
340 * ====================================================================
341 */
342
343 Champ_Don_base& nu_sur_Sc = le_fluide->nu_sur_Schmidt();
344 DoubleTab& tab_nu_sur_Sc = nu_sur_Sc.valeurs();
345 const int n = tab_nu_sur_Sc.size();
346
347 // TODO : FIXME : On a tab_nu_sur_Sc.line_size() = 1 :( :/ :(
348 // BUG : il faut avoir line_size = num_espece_ car on peut avoir D qui varie entre espece
349
350 // TODO : FIXME : j'ai pris D de l'espece 1 ...
351 for (int i=0 ; i<n ; i++) tab_nu_sur_Sc(i,0) = coeff_diffusion_especes().valeurs()(0,0);
352
353 double temps_champ = le_fluide->masse_volumique().temps();
354 nu_sur_Sc.changer_temps(temps_champ);
355 tab_nu_sur_Sc.echange_espace_virtuel();
356}
classe Champ_Don_base classe de base des Champs donnes (non calcules)
void mettre_a_jour(double temps) override
Mise a jour en temps.
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.
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
void nommer(const Nom &) override
Donne un nom au champ.
classe Fluide_Weakly_Compressible Cette classe represente un d'un fluide faiblement compressible
const DoubleTab & pression_th_tab() const
const Champ_Don_base & fraction_massique_nonresolue() const
static constexpr double R_GAS
classe Loi_Etat_Multi_GP_WC Cette classe represente la loi d'etat pour un melange de gaz parfaits.
void calculer_masse_volumique() override
Recalcule la masse volumique.
const Champ_Don_base & cp_especes() const
void calculer_nu_sur_Sc() override
Calcule la viscosite dynamique sur Schmidt = D.
const Champ_Don_base & coeff_diffusion_especes() const
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).
const Champ_Don_base & visc_dynamique_especes() const
void calculer_mu_sur_Sc() override
Calcule la viscosite dynamique sur Schmidt = rho * D.
void initialiser_inco_ch() override
Initialise l'inconnue de l'equation de chaleur : ne fai rien.
const Champ_Don_base & masse_molaire_especes() const
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)
void initialiser_inco_ch() override
Initialise l'inconnue de l'equation de chaleur : ne fai rien.
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
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
int postraiter(int force=1) override
Si force=1, effectue le postraitement sans tenir compte des frequences de postraitement.
void sauver() const override
Ecriture sur fichier en vue d'une reprise (sauvegarde).
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
int line_size() const
Definition TRUSTVect.tpp:67
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")