TrioCFD 1.9.9_beta
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(); // not 0 because resuming is possible
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 Computes the molar mass of the mixture (M). M depends on the molar mass of each species and the mixture composition (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 Computes the Cp of the mixture. Cp depends on the Cp of each species and the mixture composition (Yi).
144 *
145 */
146void Loi_Etat_Multi_GP_WC::calculer_tab_Cp(DoubleTab& tab_Cp) const
147{
148 // FIXME : Currently Cp is assumed constant for each species
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 : check whether Yn.valeurs() is up to date
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 Recomputes the density.
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 : check whether the call is in the right place ...
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 Computes the reference dynamic viscosity (depends on mass fractions 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) // otherwise 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 : check whether Yn.valeurs() is up to date
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 Computes the dynamic viscosity divided by the Schmidt number = 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 : tab_mu_sur_Sc.line_size() = 1 :( :/ :(
305 // BUG : line_size should equal num_espece_ since D can vary between species
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 : D from species 1 is used here ...
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 Computes the kinematic viscosity divided by the Schmidt number = 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 : tab_nu_sur_Sc.line_size() = 1 :( :/ :(
348 // BUG : line_size should equal num_espece_ since D can vary between species
349
350 // TODO : FIXME : D from species 1 is used here ...
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}
class Champ_Don_base base class of Given Fields (not calculated)
void mettre_a_jour(double temps) override
Time update.
DoubleTab & valeurs() override
Overrides Champ_base::valeurs() Returns the array of values.
virtual DoubleTab & valeurs()=0
Champ_Uniforme Represents a field that is constant in space and time.
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
virtual double changer_temps(const double t)
Sets the time at which the field is defined.
double temps() const
Returns the time of the field.
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
Gives a name to the field.
Fluide_Weakly_Compressible class This class represents a weakly compressible fluid,...
const DoubleTab & pression_th_tab() const
const Champ_Don_base & fraction_massique_nonresolue() const
static constexpr double R_GAS
State law class for a mixture of ideal gases in the weakly compressible (WC) framework.
void calculer_masse_volumique() override
Recomputes the density.
const Champ_Don_base & cp_especes() const
void calculer_nu_sur_Sc() override
Computes the kinematic viscosity divided by the Schmidt number = D.
const Champ_Don_base & coeff_diffusion_especes() const
void calculer_tab_Cp(DoubleTab &cp) const override
Computes the Cp of the mixture. Cp depends on the Cp of each species and the mixture composition (Yi)...
const Champ_Don_base & visc_dynamique_especes() const
void calculer_mu_sur_Sc() override
Computes the dynamic viscosity divided by the Schmidt number = rho * D.
void initialiser_inco_ch() override
Initialises the heat equation unknown; sets rho arrays and updates density.
const Champ_Don_base & masse_molaire_especes() const
Base state law class for a mixture of ideal gases.
void calculer_masse_volumique() override=0
Recomputes the density (masse volumique).
virtual void calculer_mu_wilke()=0
void calculer_tab_mu(const DoubleTab &mu, int size)
void initialiser_inco_ch() override
Initialises the heat equation unknown; sets rho arrays and updates density.
DoubleTab tab_rho_np1
DoubleTab tab_rho_n
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
@ REQUIRED
Definition Param.h:115
class Probleme_base It is a Probleme_U that is not a coupling.
int postraiter(int force=1) override
If force=1, performs post-processing regardless of the post-processing frequencies.
void sauver() const override
Writes to file for restart (backup).
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
Base class for output streams.
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")