TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Masse_Multiphase.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 <EcritureLectureSpecial.h>
17#include <Pb_Multiphase_HEM.h>
18#include <Masse_Multiphase.h>
19#include <Champ_Uniforme.h>
20#include <Matrice_Morse.h>
21#include <Discret_Thyd.h>
22#include <Fluide_base.h>
23#include <Domaine_VF.h>
24#include <TRUSTTrav.h>
25#include <Domaine.h>
26#include <EChaine.h>
27#include <Param.h>
28
29Implemente_instanciable(Masse_Multiphase, "Masse_Multiphase", Convection_Diffusion_std);
30// XD Masse_Multiphase eqn_base Masse_Multiphase INHERITS_BRACE Mass consevation equation for a multi-phase problem
31// XD_CONT where the unknown is the alpha (void fraction)
32
34
36{
37 assert(l_inco_ch_);
38 assert(le_fluide_);
39 terme_convectif.associer_eqn(*this), evanescence_.associer_eqn(*this);
40
42
43 terme_convectif.set_fichier("Debit");
44 terme_convectif.set_description((Nom)"Mass flow rate=Integral(-alpha*rho*u*ndS) [kg/s] if SI units used");
45
46 champs_compris_.ajoute_champ(l_inco_ch_);
47
48 // Special treatment for Pb_Multiphase_HEM
49 // We enforce the presence of a source term related to the interfacial flux automatically.
50 if (sub_type(Pb_Multiphase_HEM, probleme()))
51 {
52 bool check_source_FICC = false;
53
54 for (int ii = 0; ii < sources().size(); ii++)
55 if (sources()(ii)->que_suis_je().debute_par("Flux_interfacial"))
56 check_source_FICC = true;
57
58 if (!check_source_FICC)
59 {
60 EChaine source_FI("{ flux_interfacial }");
61 lire_sources(source_FI);
62 }
63 }
64
65 return is;
66}
67
69{
71 param.ajouter_non_std("convection",(this));
72 param.ajouter_non_std("evanescence|vanishing",(this));
73 param.ajouter_condition("is_read_convection","The convection operator must be read, select negligeable type if you want to neglect it.");
74}
75
77{
78 if (mot=="evanescence") is >> evanescence_;
80 return 1;
81}
82
84{
85 if (i)
86 {
87 Cerr << "Masse_Multiphase : wrong operator number " << i << finl;
89 }
90 return terme_convectif;
91}
92
94{
95 if (i)
96 {
97 Cerr << "Masse_Multiphase : wrong operator number " << i << finl;
99 }
100 return terme_convectif;
101}
102
108
110{
112 if (evanescence_) ok &= evanescence_->has_interface_blocs();
113 return ok;
114}
115
116/* evanescence is processed last */
117void Masse_Multiphase::dimensionner_blocs(matrices_t matrices, const tabs_t& semi_impl) const
118{
119 Equation_base::dimensionner_blocs(matrices, semi_impl);
120 if (evanescence_) evanescence_->dimensionner_blocs(matrices, semi_impl);
121}
122
123void Masse_Multiphase::assembler_blocs_avec_inertie(matrices_t matrices, DoubleTab& secmem, const tabs_t& semi_impl)
124{
125 Equation_base::assembler_blocs_avec_inertie(matrices, secmem, semi_impl);
126 if (evanescence_) evanescence_->ajouter_blocs(matrices, secmem, semi_impl);
127}
128
129/*! @brief Associates a physical medium to the equation; the medium is cast to Fluide_base.
130 *
131 * @param un_milieu Physical medium to associate.
132 * @throws not all physical properties of the fluid are specified
133 */
135{
136 const Fluide_base& un_fluide = ref_cast(Fluide_base,un_milieu);
137 associer_fluide(un_fluide);
138}
139
140/*! @brief Associates the unknown of the equation to the state law.
141 *
142 */
144{
146 terme_convectif->check_multiphase_compatibility();
147
148 const Domaine_dis_base& zdis = domaine_dis();
149 if (discretisation().is_vdf())
150 {
151 // initialize the grad operator if VDF
152 Op_Grad_.associer_eqn(*this);
153 Op_Grad_.typer();
154 Op_Grad_.l_op_base().associer_eqn(*this);
155 const Domaine_Cl_dis_base& zcl = domaine_Cl_dis();
156 const Champ_Inc_base& inco = inconnue();
157 Op_Grad_->associer(zdis, zcl, inco);
158 }
159
160 verifier_somme_alpha();
161}
162
163void Masse_Multiphase::verifier_somme_alpha()
164{
165 const DoubleTab& vals = l_inco_ch_->valeurs();
166 const int ne = vals.dimension(0), nl = vals.line_size();
167 DoubleVect vals_somme(ne);
168 vals_somme = 0.;
169
170 for (int i = 0; i < ne; i++)
171 for (int j = 0; j < nl; j++)
172 vals_somme(i) += vals(i, j);
173
174 const double min_a = mp_min_vect(vals_somme), max_a = mp_max_vect(vals_somme);
175
176 if (min_a < 1. - 1.e-12 || max_a > 1. + 1.e-12)
177 {
178 Cerr << "WHAT ?? The sum of the void fraction (per cell) is not 1 !!!! You should do something !" << finl;
180 }
181}
182
183/*! @brief Discretizes the equation.
184 *
185 */
187{
188 int nb_valeurs_temp = schema_temps().nb_valeurs_temporelles();
189 double temps = schema_temps().temps_courant();
190 const Discret_Thyd& dis=ref_cast(Discret_Thyd, discretisation());
191 Cerr << "Volume fraction discretization" << finl;
192 // Use temperature directive since the discretization is identical
193 const Pb_Multiphase& pb = ref_cast(Pb_Multiphase, probleme());
194 dis.discretiser_champ("temperature",domaine_dis(),"alpha","sans_dimension", pb.nb_phases(),nb_valeurs_temp,temps,l_inco_ch_);
195 l_inco_ch_->fixer_nature_du_champ(pb.nb_phases() == 1 ? scalaire : pb.nb_phases() == dimension ? vectoriel : multi_scalaire); //pfft
196 for (int i = 0; i < pb.nb_phases(); i++)
197 l_inco_ch_->fixer_nom_compo(i, Nom("alpha_") + pb.nom_phase(i));
198 champs_compris_.ajoute_champ(l_inco_ch_);
200
201 Cerr << "Masse_Multiphase::discretiser() ok" << finl;
202}
203
204/*! @brief Returns the physical medium associated with the equation.
205 *
206 * (a Fluide_base upcasted to Milieu_base)
207 * (const version)
208 *
209 * @return The Fluide_base upcasted to Milieu_base.
210 */
212{
213 return fluide();
214}
215
216
217/*! @brief Returns the physical medium associated with the equation.
218 *
219 * (a Fluide_base upcasted to Milieu_base)
220 *
221 * @return The Fluide_base upcasted to Milieu_base.
222 */
224{
225 return fluide();
226}
227
228
229/*! @brief Returns the incompressible fluid associated with the equation (const version).
230 *
231 * @return The incompressible fluid associated with the equation.
232 * @throws If no fluid is associated with the equation.
233 */
235{
236 if (!le_fluide_)
237 {
238 Cerr << "You forgot to associate the fluid to the problem named " << probleme().le_nom() << finl;
240 }
241 return le_fluide_.valeur();
242}
243
244
245/*! @brief Returns the incompressible fluid associated with the equation.
246 *
247 * @return The incompressible fluid associated with the equation.
248 * @throws If no fluid is associated with the equation.
249 */
251{
252 assert(le_fluide_);
253 return le_fluide_.valeur();
254}
255
256/*! @brief Returns the name of the application domain of the equation.
257 *
258 * Here "Fraction_volumique".
259 *
260 * @return The name of the application domain.
261 */
263{
264 static Motcle domaine ="Fraction_volumique";
265 return domaine;
266}
267
268/*! @brief Associates a fluid of type Fluide_base with the equation.
269 *
270 * @param un_fluide The fluid medium to associate with the equation.
271 */
273{
274 assert(sub_type(Fluide_base,un_fluide));
275 le_fluide_ = ref_cast(Fluide_base,un_fluide);
276}
277
278void Masse_Multiphase::calculer_alpha_rho(const Objet_U& obj, DoubleTab& val, DoubleTab& bval, tabs_t& deriv)
279{
280 const Equation_base& eqn = ref_cast(Equation_base, obj);
281 const Champ_base& ch_rho = eqn.milieu().masse_volumique();
282 const Champ_Inc_base& ch_alpha = eqn.inconnue(),
283 *pch_rho = sub_type(Champ_Inc_base, ch_rho) ? &ref_cast(Champ_Inc_base, ch_rho) : nullptr;
284
285 const DoubleTab& alpha = ch_alpha.valeurs(),
286 &rho = ch_rho.valeurs();
287
288 const int nl = val.dimension_tot(0),
289 N = val.line_size(),
290 cR = sub_type(Champ_Uniforme, ch_rho);
291
292 /* field values */
293 for (int i = 0; i < nl; i++)
294 for (int n = 0; n < N; n++)
295 val(i, n) = alpha(i, n) * rho(!cR * i, n);
296
297 /* boundary values */
298 /* valeur_aux_bords can only be used if ch_rho has a domaine_dis_base */
299 ch_rho.a_un_domaine_dis_base() ? bval = ch_rho.valeur_aux_bords() :
300 ch_rho.valeur_aux(ref_cast(Domaine_VF, eqn.domaine_dis()).xv_bord(), bval);
301
302 tab_multiply_any_shape(bval, ch_alpha.valeur_aux_bords(), VECT_ALL_ITEMS);
303
304 /* derivatives */
305 DoubleTab& d_a = deriv["alpha"]; // derivative w.r.t. alpha: rho
306 d_a.resize(nl, N);
307
308 for (int i = 0; i < nl; i++)
309 for (int n = 0; n < N; n++)
310 d_a(i, n) = rho(!cR * i, n);
311
312 if (pch_rho)
313 for (auto &&d_c : pch_rho->derivees()) // derivatives w.r.t. the dependencies of rho
314 {
315 DoubleTab& der = deriv[d_c.first];
316 der.resize(nl, N);
317
318 for (int i = 0; i < nl; i++)
319 for (int n = 0; n < N; n++)
320 der(i, n) = d_c.second(i, n) * alpha(i, n);
321 }
322}
323
324void Masse_Multiphase::calculer_alpha_rho_conv(const Objet_U& obj, DoubleTab& val, DoubleTab& bval, tabs_t& deriv)
325{
326 const Equation_base& eqn = ref_cast(Equation_base, obj);
327 const Pb_Multiphase& pbm = ref_cast(Pb_Multiphase, eqn.probleme());
328 const Champ_base& ch_rho = eqn.milieu().masse_volumique();
329 const Champ_Inc_base& ch_alpha = eqn.inconnue(), *pch_rho = sub_type(Champ_Inc_base, ch_rho) ? &ref_cast(Champ_Inc_base, ch_rho) : nullptr;
330 const DoubleTab& alpha = ch_alpha.valeurs(), &rho = ch_rho.valeurs();
331 const int nl = val.dimension_tot(0),
332 N = val.line_size(),
333 cR = sub_type(Champ_Uniforme, ch_rho);
334
335 /* field values */
336 for (int i = 0; i < nl; i++)
337 for (int n = 0; n < N; n++)
338 val(i, n) = (alpha(i, n) - pbm.alpha_inf_phase(n)) * rho(!cR * i, n);
339
340 /* boundary values */
341 /* valeur_aux_bords can only be used if ch_rho has a domaine_dis_base */
342 ch_rho.a_un_domaine_dis_base() ? bval = ch_rho.valeur_aux_bords() :
343 ch_rho.valeur_aux(ref_cast(Domaine_VF, eqn.domaine_dis()).xv_bord(), bval);
344
345 // tab_multiply_any_shape(bval, ch_alpha.valeur_aux_bords(), VECT_ALL_ITEMS);
346 DoubleTrav calpha;
347 calpha = ch_alpha.valeur_aux_bords();
348
349 const int n2 = calpha.dimension_tot(0);
350 for (int i = 0; i < n2; i++)
351 for (int n = 0; n < N; n++)
352 calpha(i, n) = calpha(i, n) - pbm.alpha_inf_phase(n);
353
354 tab_multiply_any_shape(bval, calpha, VECT_ALL_ITEMS);
355
356 /* derivatives */
357 DoubleTab& d_a = deriv["alpha"]; // derivative w.r.t. alpha: rho
358 d_a.resize(nl, N);
359
360 for (int i = 0; i < nl; i++)
361 for (int n = 0; n < N; n++)
362 d_a(i, n) = rho(!cR * i, n);
363
364 if (pch_rho)
365 for (auto &&d_c : pch_rho->derivees()) // derivatives w.r.t. the dependencies of rho
366 {
367 DoubleTab& der = deriv[d_c.first];
368 der.resize(nl, N);
369
370 for (int i = 0; i < nl; i++)
371 for (int n = 0; n < N; n++)
372 der(i, n) = d_c.second(i, n) * alpha(i, n);
373 }
374}
375
377{
378 if (champ_convecte_)
379 return; // already done
380
381 const int Nt = inconnue().nb_valeurs_temporelles(),
382 Nl = inconnue().valeurs().size_reelle_ok() ? inconnue().valeurs().dimension(0) : -1,
383 Nc = inconnue().valeurs().line_size();
384
385 // champ_convecte_: same type / support as the unknown
386 discretisation().creer_champ(champ_convecte_, domaine_dis(), inconnue().que_suis_je(), "N/A", "N/A", Nc, Nl, Nt, schema_temps().temps_courant());
387
388 champ_convecte_->associer_eqn(*this);
389 auto nom_fonc = get_fonc_champ_convecte();
390 champ_convecte_->nommer(nom_fonc.first);
391 champ_convecte_->init_champ_calcule(*this, nom_fonc.second);
392}
Class Champ_Inc_base.
virtual int nb_valeurs_temporelles() const
Returns the number of temporal values currently kept.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
DoubleTab valeur_aux_bords() const override
Returns the field value at the boundary faces.
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 int a_un_domaine_dis_base() const
Definition Champ_base.h:69
virtual DoubleTab valeur_aux_bords() const
Returns the field value at the boundary faces.
virtual DoubleTab & valeur_aux(const DoubleTab &positions, DoubleTab &valeurs) const
Causes an error! Must be overridden by derived classes.
Convection_Diffusion_std This class is the base for equations modelling the transport.
int lire_motcle_non_standard(const Motcle &, Entree &) override
Reads non-simple-type parameters of an Objet_U from an input stream.
class Discret_Thyd This class is the base class representing a discretization
static void creer_champ(OWN_PTR(Champ_Inc_base)&ch, const Domaine_dis_base &z, const Nom &type, const Nom &nom, const Nom &unite, int nb_comp, int nb_ddl, int nb_pas_dt, double temps, const Nom &directive=NOM_VIDE, const Nom &nom_discretisation=NOM_VIDE)
Static method that creates an OWN_PTR(Champ_Inc_base) of the specified type.
void discretiser_champ(const Motcle &directive, const Domaine_dis_base &z, const Nom &nom, const Nom &unite, int nb_comp, int nb_pas_dt, double temps, OWN_PTR(Champ_Inc_base)&champ, const Nom &sous_type=NOM_VIDE) const
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
class Domaine_VF
Definition Domaine_VF.h:44
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
class Equation_base The role of an equation is the calculation of one or more fields....
virtual void set_param(Param &titi) const override
virtual const Milieu_base & milieu() const =0
virtual void dimensionner_matrice_sans_mem(Matrice_Morse &mat_morse)
Sources & sources()
Returns the source terms associated with the equation.
virtual void assembler_blocs_avec_inertie(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={})
const Discretisation_base & discretisation() const
Returns the discretization associated with the equation.
virtual const Champ_Inc_base & inconnue() const =0
virtual void dimensionner_blocs(matrices_t matrices, const tabs_t &semi_impl={}) const
virtual void completer()
Completes the construction (initialization) of objects associated with the equation.
virtual Domaine_Cl_dis_base & domaine_Cl_dis()
Returns the discretized boundary condition domain associated with the equation.
Probleme_base & probleme()
Returns the problem associated with the equation.
Schema_Temps_base & schema_temps()
Returns the time scheme associated with the equation.
virtual void discretiser()
Discretizes the equation.
virtual Entree & lire_sources(Entree &)
Reading of source terms in an input stream.
virtual int has_interface_blocs() const
Champs_compris champs_compris_
Domaine_dis_base & domaine_dis()
Returns the discretized domain associated with the equation.
Base class for an incompressible fluid and its properties:
Definition Fluide_base.h:36
Specialisation of Convection_Diffusion_std for multiphase flows where the transported scalar is the v...
int lire_motcle_non_standard(const Motcle &, Entree &) override
Reads non-simple-type parameters of an Objet_U from an input stream.
static void calculer_alpha_rho(const Objet_U &obj, DoubleTab &val, DoubleTab &bval, tabs_t &deriv)
const Operateur & operateur(int) const override
Returns the operator at the given index: returns terme_diffusif if i = 0,.
void discretiser() override
Discretizes the equation.
const Motcle & domaine_application() const override
Returns the name of the application domain of the equation.
Operateur_Evanescence evanescence_
static void calculer_alpha_rho_conv(const Objet_U &obj, DoubleTab &val, DoubleTab &bval, tabs_t &deriv)
const Champ_Inc_base & inconnue() const override
Returns the unknown field representing the unknown (alpha) (const version).
const Milieu_base & milieu() const override
Returns the physical medium associated with the equation.
void associer_milieu_base(const Milieu_base &) override
Associates a physical medium to the equation; the medium is cast to Fluide_base.
int has_interface_blocs() const override
void dimensionner_matrice_sans_mem(Matrice_Morse &matrice) override
void associer_fluide(const Fluide_base &)
Associates a fluid of type Fluide_base with the equation.
void init_champ_convecte() const override
void assembler_blocs_avec_inertie(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={}) override
void completer() override
Associates the unknown of the equation to the state law.
const Fluide_base & fluide() const
Returns the incompressible fluid associated with the equation (const version).
void dimensionner_blocs(matrices_t matrices, const tabs_t &semi_impl={}) const override
Operateur_Grad Op_Grad_
std::pair< std::string, fonc_calc_t > get_fonc_champ_convecte() const
void set_param(Param &param) const override
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
Milieu_base This class is the base of the (physical) medium hierarchy.
Definition Milieu_base.h:50
virtual const Champ_base & masse_volumique() const
Returns the mass density of the medium (const version).
A character string (Nom) in uppercase.
Definition Motcle.h:26
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
friend class Entree
Definition Objet_U.h:71
static int dimension
Definition Objet_U.h:94
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
Objet_U()
Default constructor: assigns a unique identifier to the object (object_id_) and registers the object ...
Definition Objet_U.cpp:54
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
class Operateur Generic class of the operator hierarchy.
Definition Operateur.h:39
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_condition(const char *condition, const char *message, const char *name=0)
Declare a post-read logical condition that must hold on the parameter values.
Definition Param.cpp:496
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
Multiphase thermohydraulics problem of type "3*N equations":
double alpha_inf_phase(int i) const
const Nom & nom_phase(int i) const
int nb_phases() const
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Definition Probleme_U.h:109
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
double temps_courant() const
Returns the current time.
virtual int nb_valeurs_temporelles() const =0
Base class for output streams.
Definition Sortie.h:52
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
int line_size() const
Definition TRUSTVect.tpp:67
_SIZE_ size_reelle_ok() const
Definition TRUSTVect.tpp:38