TrioCFD 1.9.9_beta
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 /* we must be able to add/subtract equations between components */
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) /* ignore unknowns coming from other problems */
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++) /* other variables: components may be mixed */
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: set of columns on which at least one of the N component rows at e depends
87 for (n = 0, i = N * e; n < N; n++, i++)
88 for (auto &&x : idx) sten.append_line(i, x); // add this dependency to all rows
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 // Turbulent viscosity for correlations that need it
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 /* phase-change limiter: limit gamma to avoid alpha_k < 0 in any phase */
187 /* to do so, assemble the mass equation without phase change */
188 DoubleTrav sec_m(alpha); // residuals
189 std::map<std::string, Matrice_Morse> mat_m_stockees;
190 matrices_t mat_m; // derivatives
191 for (auto &&n_m : matrices)
192 if (n_m.first.find("/") == std::string::npos) /* ignore unknowns coming from other problems */
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()); // same stencils as those of the current equation
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()); //zero coefficients
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++) /* all operators */
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())) /* all sources except the interfacial flux */
206 eq_m.sources()(i)->ajouter_blocs(mat_m, sec_m, semi_impl);
207 std::vector<std::array<Matrice_Morse *, 2>> vec_m; //vector "source matrix, destination matrix"
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 and many derivatives...
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 // And for the span methods of the Saturation class
220 const int nbelem = domaine.nb_elem(), nb_max_sat = N * (N-1) /2; // arithmetic series!
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 // fill the arrays ...
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); // upper triangular matrix indexing!
236 // XXX XXX XXX
237 // Warning: this is dangerous! For now, we assume the pressure field has 1 component. However, the size of res is nb_max_sat*nbelem !!
238 // Also, the Span passed for the pressure field is nbelem, not nbelem_tot ....
239 assert(press.line_size() == 1);
240
241 // retrieve Tsat and 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 // fill in the rest
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 here otherwise memory leak ...
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 // interface exchange coefficients (explicit)
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 between phase k <-> phase l if 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); // upper triangular matrix indexing
288
289 if (correlation_G) /* phase change rate from a 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 /* thermal limit */
294 double Tk = temp(e, k), Tl = temp(e, l), Ts = Ts_tab(e,i_sat), dP_Ts = dPTs_tab(e,i_sat), // temperature on each side + Tsat + derivatives
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 /* phase enthalpies (in the direction corresponding to the chosen mode for G) */
298
299 /* Is G limited by evanescence on side k or l? */
300 int n_lim = G > 0 ? k : l, sgn = G > 0 ? 1 : -1; // outgoing phase
301 double Glim = sec_m(e, n_lim) / vol + p_ar(e, n_lim) / dt; //maximum acceptable phase change rate for this phase
302 if (std::fabs(G) < Glim) n_lim = -1; //G does not make the phase evanescent -> no limiting (n_lim = -2)
303 else G = (G > 0 ? 1 : -1) * Glim;//the phase would become evanescent due to G -> clamp to 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) /* derivatives of G at the thermal limit */
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())) //mass equation -> phase change
318 {
319 for (i = 0; i < 2; i++) secmem(e, i ? l : k) -= vol * (i ? -1 : 1) * G;
320 if (n_lim < 0) /* G by thermal limit */
321 {
322 if (Ma)
323 for (i = 0; i < 2; i++)
324 for (n = 0; n < N; n++) // derivatives w.r.t. 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++) // derivatives w.r.t. 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++) // derivatives w.r.t. 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 by 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())) // energy equation -> heat transfer
340 {
341 // thermal limit applies on one side: c (=0,1) / n_c (=k,l) / sign of outgoing flux from 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 /* derivatives (including those of G, except in the limit case) */
346 if (Ma)
347 for (i = 0; i < 2; i++)
348 for (n = 0; n < N; n++) // derivatives w.r.t. 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++) // derivatives w.r.t. 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++) // derivatives w.r.t. 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) /* derivatives of G in the evanescent case */
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())) //interfacial area equation; looks like the mass equation; not a conservation equation!
364 if (0.> mod2grp)
365 {
366 if (k==0) // k is the carrier phase
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 by thermal limit */
371 {
372 if (Ma) // derivatives w.r.t. 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) // derivatives w.r.t. 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) // derivatives w.r.t. 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) // derivatives w.r.t. 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 to add
396 }
397 else for (auto &s_d : vec_m) /* G by 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())) /* no saturation: energy exchanges only */
405 {
406 // outgoing flux from 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++) // only T derivatives
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}
Transport equation for the interfacial area.
virtual DoubleTab & get_elem_vector_field(DoubleTab &, bool passe=false) const
: class Champ_Inc_P0_base
Class Champ_Inc_base.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
virtual DoubleTab & valeurs()=0
virtual DoubleTab & passe(int i=1)
Definition Champ_Proto.h:50
class Champ_base This class is the base of the fields hierarchy.
Definition Champ_base.h:43
Base class for phase change correlations.
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
Specialisation of Convection_Diffusion_std for multiphase flows where the transported scalar is tempe...
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
Sources & sources()
Returns the source terms associated with the equation.
Champ_Inc_base & champ_conserve() const
virtual const Champ_Inc_base & inconnue() const =0
Probleme_base & probleme()
Returns the problem associated with the equation.
Schema_Temps_base & schema_temps()
Returns the time scheme associated with the equation.
const Champ_Don_base & viscosite_dynamique() const
Definition Fluide_base.h:58
const Champ_base & enthalpie() const
Base class for interfacial heat flux correlations of the form:
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)
Transforms v into a parallel array having the structure md.
Specialisation of Convection_Diffusion_std for multiphase flows where the transported scalar is the v...
const Operateur & operateur(int) const override
Returns the operator at the given index: returns terme_diffusif if i = 0,.
int nombre_d_operateurs() const override
Returns the number of operators in the equation: 2 for a diffusion equation.
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
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
Returns the heat capacity of the medium (const version).
virtual const Champ_Don_base & conductivite() const
Returns the conductivity of the medium (const version).
virtual const Champ_base & masse_volumique() const
Returns the mass density of the medium (const version).
DoubleTab & diametre_hydraulique_elem()
Definition Milieu_base.h:70
Composite medium representing a multiphase fluid and its properties:
bool has_saturation(int k, int l) const
Saturation_base & get_saturation(int k, int l) const
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
virtual int finit_par(const char *const n) const
Definition Nom.cpp:319
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
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
Operateur_Diff_base This class is the base of the hierarchy of operators representing.
virtual void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={ }) const
virtual Operateur_base & l_op_base()=0
Multiphase thermohydraulics problem of type "3*N equations":
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)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
Carries the terms of the momentum equation for multiphase flow without turbulence modelling.
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
Returns the current time step (delta_t).
Base class for output streams.
Definition Sortie.h:52
Interfacial flux source term (implemented in PolyMAC_HFV) of the form:
void dimensionner_blocs(matrices_t matrices, const tabs_t &semi_impl={}) const override
void completer() override
Updates internal references of the Source_base object.
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
Turbulent viscosity correlations describing the Reynolds stress tensor R_{ij} = - <u'_i u'_j>.
virtual void eddy_viscosity(DoubleTab &nu_t) const =0