TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Source_Flux_interfacial_base.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 <Source_Flux_interfacial_base.h>
17#include <Viscosite_turbulente_base.h>
18#include <Flux_interfacial_base.h>
19#include <Changement_phase_base.h>
20#include <Operateur_Diff_base.h>
21#include <Champ_Inc_P0_base.h>
22#include <Aire_interfaciale.h>
23#include <Milieu_composite.h>
24#include <Champ_Face_base.h>
25#include <Champ_Uniforme.h>
26#include <Pb_Multiphase.h>
27#include <Synonyme_info.h>
28#include <Matrix_tools.h>
29#include <EOS_to_TRUST.h>
30#include <Array_tools.h>
31#include <Domaine_VF.h>
32#include <Domaine.h>
33
34Implemente_base(Source_Flux_interfacial_base,"Source_Flux_interfacial_base", Sources_Multiphase_base);
35
37
39{
40 const Pb_Multiphase& pbm = ref_cast(Pb_Multiphase, equation().probleme());
41 if (!pbm.has_correlation("flux_interfacial"))
42 Process::exit(que_suis_je() + " : a flux_interfacial correlation must be defined in the global correlations { } block!");
43
44 const bool res_en_T = pbm.resolution_en_T();
45 if (!res_en_T) Process::exit("Source_Flux_interfacial_base::readOn NOT YET PORTED TO ENTHALPY EQUATION ! TODO FIXME !!");
46
47 for (int n = 0; n < pbm.nb_phases(); n++)
48 {
49 if ((( pbm.nom_phase(n).finit_par("group1"))) || (( pbm.nom_phase(n).finit_par("group2")))) mod2grp = 1.;
50 }
51
52 correlation_ = pbm.get_correlation("flux_interfacial");
53
54 dv_min = ref_cast(Flux_interfacial_base, correlation_.valeur()).dv_min();
55
56 return is;
57}
58
59void Source_Flux_interfacial_base::dimensionner_blocs(matrices_t matrices, const tabs_t& semi_impl) const
60{
61 const Champ_Inc_P0_base& ch = ref_cast(Champ_Inc_P0_base, equation().inconnue());
62 const Domaine_VF& domaine = ref_cast(Domaine_VF, equation().domaine_dis());
63 const DoubleTab& inco = ch.valeurs();
64
65 /* on doit pouvoir ajouter / soustraire les equations entre composantes */
66 int i, e, n, N = inco.line_size();
67 if (N == 1) return;
68 std::set<int> idx;
69 for (auto &&n_m : matrices)
70 if (n_m.first.find("/") == std::string::npos) /* pour ignorer les inconnues venant d'autres problemes */
71 {
72 Matrice_Morse& mat = *n_m.second, mat2;
73 const DoubleTab& dep = equation().probleme().get_champ(n_m.first).valeurs();
74 const int M = dep.line_size();
75 Stencil sten(0, 2);
76
77 if (n_m.first == "temperature" || n_m.first == "pression" || n_m.first == "alpha" || n_m.first == "interfacial_area" ) /* temperature/pression: dependance locale */
78 for (e = 0; e < domaine.nb_elem(); e++)
79 for (n = 0; n < N; n++)
80 for (int m = 0; m < M; m++) sten.append_line(N * e + n, M * e + m);
81 if (mat.nb_colonnes())
82 for (e = 0; e < domaine.nb_elem(); e++) /* autres variables: on peut melanger les composantes*/
83 {
84 for (idx.clear(), n = 0, i = N * e; n < N; n++, i++)
85 for (auto j = mat.get_tab1()(i) - 1; j < mat.get_tab1()(i + 1) - 1; j++)
86 idx.insert(mat.get_tab2()(j) - 1); //idx : ensemble des colonnes dont depend au moins une ligne des N composantes en e
87 for (n = 0, i = N * e; n < N; n++, i++)
88 for (auto &&x : idx) sten.append_line(i, x); //ajout de cette depedance a toutes les lignes
89 }
90 tableau_trier_retirer_doublons(sten);
92 mat.nb_colonnes() ? mat += mat2 : mat = mat2;
93 }
94}
95
97{
98 const Domaine_VF& domaine = ref_cast(Domaine_VF, equation().domaine_dis());
99 int N = equation().inconnue().valeurs().line_size();
100 if (!sub_type(Source_Flux_interfacial_base, equation().sources().dernier().valeur()))
101 Process::exit(que_suis_je() + " : Source_Flux_interfacial_base must be the last source term in the source term declaration list of the " + equation().que_suis_je() + " equation ! ");
102
103 if (sub_type(Energie_Multiphase, equation()))
104 {
105 qpi_.resize(0, N, N), domaine.domaine().creer_tableau_elements(qpi_);
106 dT_qpi_.resize(0, N, N, N), domaine.domaine().creer_tableau_elements(dT_qpi_);
107 da_qpi_.resize(0, N, N, N), domaine.domaine().creer_tableau_elements(da_qpi_);
108 dp_qpi_.resize(0, N, N), domaine.domaine().creer_tableau_elements(dp_qpi_);
109 }
110
111 if(ref_cast(Operateur_Diff_base, equation().probleme().equation(0).operateur(0).l_op_base()).is_turb()) is_turb_ = 1;
112}
113
115{
116 if (sub_type(Energie_Multiphase, equation())) return qpi_;
117 return ref_cast(Source_Flux_interfacial_base, ref_cast(Energie_Multiphase, ref_cast(Pb_Multiphase, equation().probleme()).equation_energie()).sources().dernier().valeur()).qpi();
118}
119
121{
122 if (sub_type(Energie_Multiphase, equation())) return dT_qpi_;
123 return ref_cast(Source_Flux_interfacial_base, ref_cast(Energie_Multiphase, ref_cast(Pb_Multiphase, equation().probleme()).equation_energie()).sources().dernier().valeur()).dT_qpi();
124}
125
127{
128 if (sub_type(Energie_Multiphase, equation())) return da_qpi_;
129 return ref_cast(Source_Flux_interfacial_base, ref_cast(Energie_Multiphase, ref_cast(Pb_Multiphase, equation().probleme()).equation_energie()).sources().dernier().valeur()).da_qpi();
130}
131
133{
134 if (sub_type(Energie_Multiphase, equation())) return dp_qpi_;
135 return ref_cast(Source_Flux_interfacial_base, ref_cast(Energie_Multiphase, ref_cast(Pb_Multiphase, equation().probleme()).equation_energie()).sources().dernier().valeur()).dp_qpi();
136}
137
139{
140 qpi_ = 0, dT_qpi_ = 0, da_qpi_ = 0, dp_qpi_ = 0;
141}
142
143void Source_Flux_interfacial_base::ajouter_blocs(matrices_t matrices, DoubleTab& secmem, const tabs_t& semi_impl) const
144{
145 const Pb_Multiphase& pbm = ref_cast(Pb_Multiphase, equation().probleme());
146 const Champ_Inc_P0_base& ch = ref_cast(Champ_Inc_P0_base, equation().inconnue());
147 // Matrice_Morse *mat = matrices.count(ch.le_nom().getString()) ? matrices.at(ch.le_nom().getString()) : nullptr;
148 const Milieu_composite& milc = ref_cast(Milieu_composite, equation().milieu());
149 const Domaine_VF& domaine = ref_cast(Domaine_VF, equation().domaine_dis());
150 const DoubleVect& pe = milc.porosite_elem(), &ve = domaine.volumes();
151 const tabs_t& der_h = ref_cast(Champ_Inc_base, milc.enthalpie()).derivees();
152 const Champ_base& ch_rho = milc.masse_volumique();
153 const Champ_Inc_base& ch_alpha = pbm.equation_masse().inconnue(), &ch_a_r = pbm.equation_masse().champ_conserve(),
154 &ch_temp = pbm.equation_energie().inconnue(), &ch_p = ref_cast(QDM_Multiphase, pbm.equation_qdm()).pression(),
155 *pch_rho = sub_type(Champ_Inc_base, ch_rho) ? &ref_cast(Champ_Inc_base, ch_rho) : nullptr;
156
157 const DoubleTab& inco = ch.valeurs(), &alpha = ch_alpha.valeurs(), &press = ch_p.valeurs(), &temp = ch_temp.valeurs(), &temp_p = ch_temp.passe(),
158 &h = milc.enthalpie().valeurs(), *dP_h = der_h.count("pression") ? &der_h.at("pression") : nullptr, *dT_h = der_h.count("temperature") ? &der_h.at("temperature") : nullptr,
159 &lambda = milc.conductivite().passe(), &mu = milc.viscosite_dynamique().passe(), &rho = milc.masse_volumique().passe(), &Cp = milc.capacite_calorifique().passe(),
160 &p_ar = ch_a_r.passe(), &a_r = ch_a_r.valeurs(), &qi = qpi(), &dTqi = dT_qpi(), &daqi = da_qpi(), &dpqi = dp_qpi(),
161 *d_bulles = (equation().probleme().has_champ("diametre_bulles")) ? &equation().probleme().get_champ("diametre_bulles").valeurs() : nullptr,
162 *k_turb = (equation().probleme().has_champ("k")) ? &equation().probleme().get_champ("k").passe() : nullptr;
163
164 Matrice_Morse *Mp = matrices.count("pression") ? matrices.at("pression") : nullptr,
165 *Mt = matrices.count("temperature") ? matrices.at("temperature") : nullptr,
166 *Ma = matrices.count("alpha") ? matrices.at("alpha") : nullptr,
167 *Mai = matrices.count("interfacial_area") ? matrices.at("interfacial_area") : nullptr;
168
169 int i, col, e, d, D = dimension, k, l, n, N = inco.line_size(), is_therm;
170 const int cL = (lambda.dimension_tot(0) == 1), cM = (mu.dimension_tot(0) == 1), cR = (rho.dimension_tot(0) == 1), cCp = (Cp.dimension_tot(0) == 1);
171
172 const Flux_interfacial_base& correlation_fi = ref_cast(Flux_interfacial_base, correlation_.valeur());
173 const Changement_phase_base *correlation_G = pbm.has_correlation("changement_phase") ? &ref_cast(Changement_phase_base, pbm.get_correlation("changement_phase")) : nullptr;
174 double dt = equation().schema_temps().pas_de_temps(), alpha_min = 1.e-6;
175
176 // Viscosite turbulente pour les correlations qui en ont besoin
177 DoubleTrav nut;
178 if (is_turb_)
179 {
180 nut.resize(0, N);
181 MD_Vector_tools::creer_tableau_distribue(equation().inconnue().valeurs().get_md_vector(), nut); //Necessary to compare size in eddy_viscosity()
182 const Viscosite_turbulente_base& corr_visc_turb = ref_cast(Viscosite_turbulente_base, *ref_cast(Operateur_Diff_base, equation().probleme().equation(0).operateur(0).l_op_base()).correlation_viscosite_turbulente());
183 corr_visc_turb.eddy_viscosity(nut);
184 }
185
186 /* limiteur de changement de phase : on limite gamma pour eviter d'avoir alpha_k < 0 dans une phase */
187 /* pour cela, on assemble l'equation de masse sans changement de phase */
188 DoubleTrav sec_m(alpha); //residus
189 std::map<std::string, Matrice_Morse> mat_m_stockees;
190 matrices_t mat_m; //derivees
191 for (auto &&n_m : matrices)
192 if (n_m.first.find("/") == std::string::npos) /* pour ignorer les inconnues venant d'autres problemes */
193 {
194 Matrice_Morse& dst = mat_m_stockees[n_m.first], &src = *n_m.second;
195 dst.get_set_tab1().ref_array(src.get_set_tab1()); // memes stencils que celui de l'equation courante
196 dst.get_set_tab2().ref_array(src.get_set_tab2());
197 dst.set_nb_columns(src.nb_colonnes());
198 dst.get_set_coeff().resize(src.get_set_coeff().size()); //coeffs nuls
199 mat_m[n_m.first] = &dst;
200 }
201 const Masse_Multiphase& eq_m = ref_cast(Masse_Multiphase, pbm.equation_masse());
202 for (i = 0; i < eq_m.nombre_d_operateurs(); i++) /* tous les operateurs */
203 eq_m.operateur(i).l_op_base().ajouter_blocs(mat_m, sec_m, semi_impl);
204 for (i = 0; i < eq_m.sources().size(); i++)
205 if (!sub_type(Source_Flux_interfacial_base, eq_m.sources()(i).valeur())) /* toutes les sources sauf le flux interfacial */
206 eq_m.sources()(i)->ajouter_blocs(mat_m, sec_m, semi_impl);
207 std::vector<std::array<Matrice_Morse *, 2>> vec_m; //vecteur "matrice source, matrice de destination"
208 for (auto &&n_m : matrices)
209 if (n_m.first.find("/") == std::string::npos && mat_m[n_m.first]->get_tab1().size_array() > 1) vec_m.push_back({{ mat_m[n_m.first], n_m.second }});
210
211 /* elements */
212 //coefficients et plein de derivees...
213 DoubleTrav dT_G(N), da_G(N), nv(N, N);
216 DoubleTab& hi = out.hi, &dT_hi = out.dT_hi, &da_hi = out.da_hi, &dP_hi = out.dp_hi;
217 hi.resize(N, N), dT_hi.resize(N, N, N), da_hi.resize(N, N, N), dP_hi.resize(N, N), in.v.resize(N, D);
218
219 // Et pour les methodes span de la classe Saturation
220 const int nbelem = domaine.nb_elem(), nb_max_sat = N * (N-1) /2; // oui !! suite arithmetique !!
221 DoubleTrav Ts_tab(nbelem,nb_max_sat), dPTs_tab(nbelem,nb_max_sat), Hvs_tab(nbelem,nb_max_sat), Hls_tab(nbelem,nb_max_sat), dPHvs_tab(nbelem,nb_max_sat), dPHls_tab(nbelem,nb_max_sat), Lvap_tab(nbelem,nb_max_sat), dP_Lvap_tab(nbelem,nb_max_sat), Sigma_tab(nbelem,nb_max_sat);
222
223 // fill velocity at elem tab
224 DoubleTab pvit_elem(0, N * D);
225 domaine.domaine().creer_tableau_elements(pvit_elem);
226 const Champ_Face_base& ch_vit = ref_cast(Champ_Face_base,ref_cast(Pb_Multiphase, equation().probleme()).equation_qdm().inconnue());
227 ch_vit.get_elem_vector_field(pvit_elem);
228
229 // remplir les tabs ...
230 for (k = 0; k < N; k++)
231 for (l = k + 1; l < N; l++)
232 if (milc.has_saturation(k, l))
233 {
234 Saturation_base& z_sat = milc.get_saturation(k, l);
235 const int ind_trav = (k*(N-1)-(k-1)*(k)/2) + (l-k-1); // Et oui ! matrice triang sup !
236 // XXX XXX XXX
237 // Attention c'est dangereux ! on suppose pour le moment que le champ de pression a 1 comp. Par contre la taille de res est nb_max_sat*nbelem !!
238 // Aussi, on passe le Span le nbelem pour le champ de pression et pas nbelem_tot ....
239 assert(press.line_size() == 1);
240
241 // recuperer Tsat et sigma ...
242 const DoubleTab& sig = z_sat.get_sigma_tab(), &tsat = z_sat.get_Tsat_tab();
243
244 // fill in the good case
245 for (int ii = 0; ii < nbelem; ii++)
246 {
247 Ts_tab(ii, ind_trav) = tsat(ii);
248 Sigma_tab(ii, ind_trav) = sig(ii);
249 }
250
251 // remplir les autres
252 MSatSpanD sats_all = { };
253 sats_all.insert( { SAT::T_SAT_DP, dPTs_tab.get_span() });
254 sats_all.insert( { SAT::HV_SAT, Hvs_tab.get_span() });
255 sats_all.insert( { SAT::HL_SAT, Hls_tab.get_span() });
256 sats_all.insert( { SAT::HV_SAT_DP, dPHvs_tab.get_span() });
257 sats_all.insert( { SAT::HL_SAT_DP, dPHls_tab.get_span() });
258 sats_all.insert( { SAT::LV_SAT, Lvap_tab.get_span() });
259 sats_all.insert( { SAT::LV_SAT_DP, dP_Lvap_tab.get_span() });
260
261 ConstDoubleTab_parts ppart(press);
262 z_sat.compute_all_flux_interfacial_pb_multiphase(ppart[0].get_span() /* elem reel */, sats_all, nb_max_sat, ind_trav);
263 }
264
265 for (e = 0; e < domaine.nb_elem(); e++)
266 {
267 double vol = pe(e) * ve(e), x, G = 0, dh = milc.diametre_hydraulique_elem()(e), dP_G = 0.; // E. Saikali : initialise dP_G ici sinon fuite memoire ...
268 for (in.v = 0, d = 0; d < D; d++)
269 for (n = 0; n < N; n++)
270 in.v(n, d) = pvit_elem(e, N * d + n);
271 for (nv = 0, d = 0; d < D; d++)
272 for (n = 0; n < N; n++)
273 for (k = 0 ; k<N ; k++) nv(n, k) += std::pow(pvit_elem(e, N * d + n) - ((n!=k) ? pvit_elem(e, N * d + k) : 0) , 2); // nv(n,n) = ||v(n)||, nv(n, k!=n) = ||v(n)-v(k)||
274 for (n = 0; n < N; n++)
275 for (k = 0 ; k<N ; k++) nv(n, k) = std::max(sqrt(nv(n, k)), dv_min);
276 //coeffs d'echange vers l'interface (explicites)
277 in.dh = dh, in.alpha = &alpha(e, 0), in.T = &temp(e, 0), in.T_passe = &temp_p(e, 0), in.p = press(e, 0), in.nv = &nv(0, 0), in.h = &h(e, 0), in.dT_h = dT_h ? &(*dT_h)(e, 0) : nullptr, in.dP_h = dP_h ? &(*dP_h)(e, 0) : nullptr;
278 in.lambda = &lambda(!cL * e, 0), in.mu = &mu(!cM * e, 0), in.rho = &rho(!cR * e, 0), in.Cp = &Cp(!cCp * e, 0), in.e = e, in.Lvap = &Lvap_tab(e, 0), in.dP_Lvap = &dP_Lvap_tab(e, 0), in.sigma = &Sigma_tab(e,0), in.Tsat = &Ts_tab(e,0), in.dP_Tsat = &dPTs_tab(e,0);
279 in.d_bulles = (d_bulles) ? &(*d_bulles)(e,0) : nullptr, in.k_turb = (k_turb) ? &(*k_turb)(e,0) : nullptr, in.nut = (is_turb_) ? &nut(e,0) : nullptr;
280 correlation_fi.coeffs(in, out);
281
282 for (k = 0; k < N; k++)
283 for (l = k + 1; l < N; l++)
284 if (milc.has_saturation(k, l)) //flux phase k <-> phase l si saturation
285 {
286 Saturation_base& sat = milc.get_saturation(k, l);
287 const int i_sat = (k*(N-1)-(k-1)*(k)/2) + (l-k-1); // Et oui ! matrice triang sup !
288
289 if (correlation_G) /* taux de changement de phase par une correlation */
290 G = correlation_G->calculer(k, l, dh, &alpha(e, 0), &temp(e, 0), press(e, 0), &nv(0), &lambda(!cL * e, 0), &mu(!cM * e, 0), &rho(!cM * e, 0), &Cp(!cCp * e, 0),
291 sat, dT_G, da_G, dP_G);
292
293 /* limite thermique */
294 double Tk = temp(e, k), Tl = temp(e, l), Ts = Ts_tab(e,i_sat), dP_Ts = dPTs_tab(e,i_sat), //temperature de chaque cote + Tsat + derivees
295 phi = hi(k, l) * (Tk - Ts) + hi(l, k) * (Tl - Ts) + qi(e, k, l) / vol, L = (phi < 0 ? h(e, l) : Hvs_tab(e,i_sat)) - (phi > 0 ? h(e, k) : Hls_tab(e,i_sat));
296 if ((is_therm = !correlation_G || std::fabs(G) > std::fabs(phi / L))) G = phi / L;
297 /* enthalpies des phases (dans le sens correspondant au mode choisi pour G) */
298
299 /* G est-il limite par l'evanescence cote k ou l ? */
300 int n_lim = G > 0 ? k : l, sgn = G > 0 ? 1 : -1; //phase sortante
301 double Glim = sec_m(e, n_lim) / vol + p_ar(e, n_lim) / dt; //changement de phase max acceptable par cette phase
302 if (std::fabs(G) < Glim) n_lim = -1; //G ne rend pas la phase evanescente -> pas de limitation (n_lim = -2)
303 else G = (G > 0 ? 1 : -1) * Glim;//la phase serait evanescente a cause de G -> on le bloque a G_lim (n_lim = k / l)
304
305 double hk = G > 0 ? h(e, k) : Hls_tab(e,i_sat), dTk_hk = G > 0 && dT_h ? (*dT_h)(e, k) : 0, dP_hk = G > 0 ? (dP_h ? (*dP_h)(e, k) : 0) : dPHls_tab(e,i_sat),
306 hl = G < 0 ? h(e, l) : Hvs_tab(e,i_sat), dTl_hl = G < 0 && dT_h ? (*dT_h)(e, l) : 0, dP_hl = G < 0 ? (dP_h ? (*dP_h)(e, l) : 0) : dPHvs_tab(e,i_sat);
307 if (n_lim < 0 && is_therm) /* derivees de G en limite thermique */
308 {
309 double dP_phi = dP_hi(k, l) * (Tk - Ts) + dP_hi(l, k) * (Tl - Ts) - (hi(k, l) + hi(l, k)) * dP_Ts + dpqi(e, k, l) / vol,
310 dTk_L = -dTk_hk, dTl_L = dTl_hl, dP_L = dP_hl - dP_hk;
311 dP_G = (dP_phi - G * dP_L) / L;
312 for (n = 0; n < N; n++) dT_G(n) = ((n == k) * (hi(k, l) - G * dTk_L) + (n == l) * (hi(l, k) - G * dTl_L) + dT_hi(k, l, n) * (Tk - Ts) + dT_hi(l, k, n) * (Tl - Ts) + dTqi(e, k, l, n)) / L;
313 for (n = 0; n < N; n++) da_G(n) = (da_hi(k, l, n) * (Tk - Ts) + da_hi(l, k, n) * (Tl - Ts) + daqi(e, k, l, n)) / L;
314 }
315
316
317 if (sub_type(Masse_Multiphase, equation())) //eq de masse -> changement de phase
318 {
319 for (i = 0; i < 2; i++) secmem(e, i ? l : k) -= vol * (i ? -1 : 1) * G;
320 if (n_lim < 0) /* G par limite thermique */
321 {
322 if (Ma)
323 for (i = 0; i < 2; i++)
324 for (n = 0; n < N; n++) //derivees en alpha
325 (*Ma)(N * e + (i ? l : k), N * e + n) += vol * (i ? -1 : 1) * da_G(n);
326 if (Mt)
327 for (i = 0; i < 2; i++)
328 for (n = 0; n < N; n++) //derivees en T
329 (*Mt)(N * e + (i ? l : k), N * e + n) += vol * (i ? -1 : 1) * dT_G(n);
330 if (Mp)
331 for (i = 0; i < 2; i++) //derivees en p
332 (*Mp)(N * e + (i ? l : k), e) += vol * (i ? -1 : 1) * dP_G;
333 }
334 else for (auto &s_d : vec_m) /* G par evanescence */
335 for (auto j = s_d[0]->get_tab1()(N * e + n_lim) - 1; j < s_d[0]->get_tab1()(N * e + n_lim + 1) - 1; j++)
336 for (col = s_d[0]->get_tab2()(j) - 1, x = -s_d[0]->get_coeff()(j), i = 0; i < 2; i++)
337 (*s_d[1])(N * e + (i ? l : k), col) += (i ? -1 : 1) * sgn * x;
338 }
339 else if (sub_type(Energie_Multiphase, equation())) //eq d'energie -> transfert de chaleur
340 {
341 //on suppose que la limite thermique s'applique d'un cote : c (=0,1) / n_c (=k,l) / signe du flux sortant de la phase k : s_c (=1,-1)
342 int c = (a_r(e, k) > a_r(e, l)), n_c = c ? l : k, n_d = c ? k : l, s_c = c ? -1 : 1;
343 double Tc = c ? Tl : Tk, hc = c ? hl : hk, dT_hc = c ? dTl_hl : dTk_hk, dP_hc = c ? dP_hl : dP_hk;
344 for (i = 0; i < 2; i++) secmem(e, i ? l : k)-= vol * (i ? -1 : 1) * (s_c * hi(n_c, n_d) * (Tc - Ts) + G * hc) - (i != c) * qi(e, k, l);
345 /* derivees (y compris celles en G, sauf dans le cas limite)*/
346 if (Ma)
347 for (i = 0; i < 2; i++)
348 for (n = 0; n < N; n++) //derivees en alpha
349 (*Ma)(N * e + (i ? l : k), N * e + n) += vol * (i ? -1 : 1) * (s_c * da_hi(n_c, n_d, n) * (Tc - Ts) + (n_lim < 0) * da_G(n) * hc) - (i != c) * daqi(e, k, l, n);
350 if (Mt)
351 for (i = 0; i < 2; i++)
352 for (n = 0; n < N; n++) //derivees en T
353 (*Mt)(N * e + (i ? l : k), N * e + n) += vol * (i ? -1 : 1) * (s_c * (dT_hi(n_c, n_d, n) * (Tc - Ts) + (n == n_c) * hi(n_c, n_d)) + (n_lim < 0) * dT_G(n) * hc + G * (n == n_c) * dT_hc) - (i != c) * dTqi(e, k, l, n);
354 if (Mp)
355 for (i = 0; i < 2; i++) //derivees en p
356 (*Mp)(N * e + (i ? l : k), e) += vol * (i ? -1 : 1) * (s_c * (dP_hi(n_c, n_d) * (Tc - Ts) - hi(n_c, n_d) * dP_Ts) + (n_lim < 0) * dP_G * hc + G * dP_hc) - (i != c) * dpqi(e, k, l);
357 if (n_lim >= 0)
358 for (auto &s_d : vec_m) /* derivees de G dans le cas evanescent */
359 for (auto j = s_d[0]->get_tab1()(N * e + n_lim) - 1; j < s_d[0]->get_tab1()(N * e + n_lim + 1) - 1; j++)
360 for (col = s_d[0]->get_tab2()(j) - 1, x = -s_d[0]->get_coeff()(j), i = 0; i < 2; i++)
361 (*s_d[1])(N * e + (i ? l : k), col) += (i ? -1 : 1) * hc * sgn * x;
362 }
363 else if (sub_type(Aire_interfaciale, equation())) //eq d'aire interfaciale ; looks like the mass equation ; not a conservation equation !
364 if (0.> mod2grp)
365 {
366 if (k==0) // k est la phase porteuse
367 if (alpha(e, l) > alpha_min) // if the phase l is present
368 {
369 secmem(e, l) += vol * 2./3. * inco(e, l) / (alpha(e, l) * (pch_rho ? (*pch_rho).valeurs()(e, l) : rho(e, l))) * G ;
370 if (n_lim < 0) /* G par limite thermique */
371 {
372 if (Ma) //derivees en alpha
373 {
374 (*Ma)(N * e + l , N * e + l) -= vol * 2./3. * inco(e, l) / (-alpha(e, l)*alpha(e, l) * (pch_rho ? (*pch_rho).valeurs()(e, l) : rho(e, l))) * G;
375 for (n = 0; n < N; n++) (*Ma)(N * e + l , N * e + n) -=
376 vol * 2./3. * inco(e, l) / (alpha(e, l) * (pch_rho ? (*pch_rho).valeurs()(e, l) : rho(e, l))) * da_G(n);
377 }
378 if (Mt) //derivees en T
379 {
380 if (pch_rho) (*Mt)(N * e + l , N * e + l) -=
381 vol * 2./3. * inco(e, l) / alpha(e, l)*-pch_rho->derivees().at("temperature")(e, l)/((*pch_rho).valeurs()(e, l)*(*pch_rho).valeurs()(e, l)) * G;
382 for (n = 0; n < N; n++) (*Mt)(N * e + l , N * e + n) -=
383 vol * 2./3. * inco(e, l) / (alpha(e, l) * (pch_rho ? (*pch_rho).valeurs()(e, l) : rho(e, l))) * dT_G(n);
384 }
385 if (Mp) //derivees en p
386 {
387 if (pch_rho) (*Mp)(N * e + l , e) -=
388 vol * 2./3. * inco(e, l) / alpha(e, l)*-pch_rho->derivees().at("pression")(e, l)/((*pch_rho).valeurs()(e, l)*(*pch_rho).valeurs()(e, l)) * G;
389 for (n = 0; n < N; n++) (*Mp)(N * e + l , N * e + n) -=
390 vol * 2./3. * inco(e, l) / (alpha(e, l) * (pch_rho ? (*pch_rho).valeurs()(e, l) : rho(e, l))) * dP_G;
391 }
392 if (Mai) //derivees en ai
393 {
394 (*Mai)(N * e + l , N * e + l) -= vol * 2./3. / (alpha(e, l)* (pch_rho ? (*pch_rho).valeurs()(e, l) : rho(e, l))) * G;
395 } // dAi_G a ajouter
396 }
397 else for (auto &s_d : vec_m) /* G par evanescence */
398 for (auto j = s_d[0]->get_tab1()(N * e + n_lim) - 1; j < s_d[0]->get_tab1()(N * e + n_lim + 1) - 1; j++)
399 for (col = s_d[0]->get_tab2()(j) - 1, x = -s_d[0]->get_coeff()(j), i = 0; i < 2; i++)
400 (*s_d[1])(N * e + l , col) -= 2./3. * inco(e, l) / (alpha(e, l) * (pch_rho ? (*pch_rho).valeurs()(e, l) : rho(e, l))) * sgn * x;
401 }
402 }
403 }
404 else if (sub_type(Energie_Multiphase, equation())) /* pas de saturation : echanges d'energie seulement */
405 {
406 //flux sortant de la phase k : hm * (Tk - Tl)
407 double hm = 1. / (1. / hi(k, l) + 1. / hi(l, k)), Tk = temp(e, k), Tl = temp(e, l);
408 for (i = 0; i < 2; i++) secmem(e, i ? l : k) -= vol * (i ? -1 : 1) * hm * (Tk - Tl);
409 if (Mt)
410 for (i = 0; i < 2; i++) //juste des derivees en T
411 {
412 (*Mt)(N * e + (i ? l : k), N * e + k) += vol * (i ? -1 : 1) * hm;
413 (*Mt)(N * e + (i ? l : k), N * e + l) += vol * (i ? 1 : -1) * hm;
414 }
415 }
416 }
417}
classe Aire_interfaciale Equation de transport de l'aire interfaciale
virtual DoubleTab & get_elem_vector_field(DoubleTab &, bool passe=false) const
: class Champ_Inc_P0_base
Classe Champ_Inc_base.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual DoubleTab & valeurs()=0
virtual DoubleTab & passe(int i=1)
Definition Champ_Proto.h:50
classe Champ_base Cette classe est la base de la hierarchie des champs.
Definition Champ_base.h:43
classe Changement_phase_base correlations de changement de phase
virtual double calculer(int k, int l, const double dh, const double *alpha, const double *T, const double p, const double *nv, const double *lambda, const double *mu, const double *rho, const double *Cp, const Saturation_base &sat, DoubleTab &dT_G, DoubleTab &da_G, double &dp_G) const =0
class Domaine_VF
Definition Domaine_VF.h:44
classe Energie_Multiphase Cas particulier de Convection_Diffusion_std pour un fluide quasi conpressib...
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
Sources & sources()
Renvoie les termes sources asssocies a l'equation.
Champ_Inc_base & champ_conserve() const
virtual const Champ_Inc_base & inconnue() 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.
const Champ_Don_base & viscosite_dynamique() const
Definition Fluide_base.h:60
const Champ_base & enthalpie() const
classe Flux_interfacial_base correlations de flux de chaleur interfacial de la forme
virtual void coeffs(const input_t &input, output_t &output) const =0
DoubleTab & get_sigma_tab()
static void creer_tableau_distribue(const MD_Vector &, Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
transforme v en un tableau parallele ayant la structure md.
classe Masse_Multiphase Cas particulier de Convection_Diffusion_std pour un fluide quasi conpressible
const Operateur & operateur(int) const override
Renvoie l'operateur specifie par son index: renvoie terme_diffusif si i = 0.
int nombre_d_operateurs() const override
Renvoie le nombre d'operateurs de l'equation: 2 pour une equation de diffusion.
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
auto & get_set_tab2()
const auto & get_tab2() const
const auto & get_tab1() const
void set_nb_columns(const int)
auto & get_set_coeff()
int nb_colonnes() const override
Return local number of columns (=size on the current proc).
auto & get_set_tab1()
static void allocate_morse_matrix(const int nb_lines, const int nb_columns, const Stencil &stencil, Matrice_Morse &matrix, const bool &attach_stencil_to_matrix=false)
DoubleVect & porosite_elem()
Definition Milieu_base.h:58
virtual const Champ_Don_base & capacite_calorifique() const
Renvoie la capacite calorifique du milieu.
virtual const Champ_Don_base & conductivite() const
Renvoie la conductivite du milieu.
virtual const Champ_base & masse_volumique() const
Renvoie la masse volumique du milieu.
DoubleTab & diametre_hydraulique_elem()
Definition Milieu_base.h:70
Classe Milieu_composite Cette classe represente un fluide reel ainsi que.
bool has_saturation(int k, int l) const
Saturation_base & get_saturation(int k, int l) const
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
virtual int finit_par(const char *const n) const
Definition Nom.cpp:324
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 Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
classe Operateur_Diff_base Cette classe est la base de la hierarchie des operateurs representant
virtual void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={ }) const
virtual Operateur_base & l_op_base()=0
classe Pb_Multiphase Cette classe represente un probleme de thermohydraulique multiphase de type "3*N...
virtual bool resolution_en_T() const
virtual Equation_base & equation_qdm()
virtual Equation_base & equation_energie()
const Nom & nom_phase(int i) const
int nb_phases() const
virtual Equation_base & equation_masse()
bool has_champ(const Motcle &nom, OBS_PTR(Champ_base) &ref_champ) const override
const Champ_base & get_champ(const Motcle &nom) const override
int has_correlation(std::string nom_correlation) const
const Correlation_base & get_correlation(std::string nom_correlation) const
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
classe QDM_Multiphase Cette classe porte les termes de l'equation de la dynamique
DoubleTab & get_Tsat_tab()
virtual void compute_all_flux_interfacial_pb_multiphase(const SpanD P, MSatSpanD, int ncomp=1, int ind=0) const
double pas_de_temps() const
Renvoie le pas de temps (delta_t) courant.
Classe de base des flux de sortie.
Definition Sortie.h:52
Classe Source_Flux_interfacial_base.
void dimensionner_blocs(matrices_t matrices, const tabs_t &semi_impl={}) const override
void completer() override
Met a jour les references internes a l'objet Source_base.
void mettre_a_jour(double temps) override
DOES NOTHING - to override in derived classes.
void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={}) const override
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
void append_line(_TYPE_)
Definition TRUSTTab.tpp:213
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
int line_size() const
Definition TRUSTVect.tpp:67
classe Viscosite_turbulente_base correlations de viscosite turbulente decrivant le tenseur de Reynold...
virtual void eddy_viscosity(DoubleTab &nu_t) const =0