TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Conv_EF_Stab_PolyMAC_MPFA_Face.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 <Op_Conv_EF_Stab_PolyMAC_MPFA_Face.h>
17#include <Op_Grad_PolyMAC_MPFA_Face.h>
18#include <Champ_Face_PolyMAC_MPFA.h>
19#include <Masse_ajoutee_base.h>
20#include <Domaine_Cl_PolyMAC_family.h>
21#include <Schema_Temps_base.h>
22#include <Domaine_Poly_base.h>
23#include <Option_PolyMAC_family.h>
24#include <Pb_Multiphase.h>
25#include <Matrix_tools.h>
26#include <Array_tools.h>
27#include <TRUSTLists.h>
28#include <Dirichlet.h>
29#include <Param.h>
30#include <cmath>
31#include <Dirichlet_homogene.h>
32#include <Symetrie.h>
33
34Implemente_instanciable( Op_Conv_EF_Stab_PolyMAC_MPFA_Face, "Op_Conv_EF_Stab_PolyMAC_MPFA_Face", Op_Conv_EF_Stab_PolyMAC_HFV_Face ) ;
35Implemente_instanciable(Op_Conv_Amont_PolyMAC_MPFA_Face, "Op_Conv_Amont_PolyMAC_MPFA_Face", Op_Conv_EF_Stab_PolyMAC_MPFA_Face);
36Implemente_instanciable(Op_Conv_Centre_PolyMAC_MPFA_Face, "Op_Conv_Centre_PolyMAC_MPFA_Face", Op_Conv_EF_Stab_PolyMAC_MPFA_Face);
37
38// XD Op_Conv_EF_Stab_PolyMAC_MPFA_Face interprete Op_Conv_EF_Stab_PolyMAC_MPFA_Face BRACE Class
39// XD_CONT Op_Conv_EF_Stab_PolyMAC_MPFA_Face
43
45
47{
48 alpha_ = 1.0;
50}
52{
53 alpha_ = 0.0;
55}
56
58{
60 ref_cast(Champ_Face_PolyMAC_MPFA, vitesse_.valeur()).init_auxiliary_variables();
61}
62
63/*! @brief Computes the stability time step for the convection operator.
64 *
65 * This method calculates the maximum allowable time step based on the CFL stability condition
66 * for the convection operator. The computation considers incoming fluxes through
67 * each face of every element and determines the most restrictive time step constraint across the
68 * entire domain. For multiphase flows, elements with negligible phase presence are excluded from
69 * the time step calculation.
70 *
71 * @return The global minimum stability time step across all MPI processes
72 *
73 * @note Only incoming convective fluxes are considered in the stability analysis.
74 * @note For multiphase problems, elements with phase fraction below 1e-3 are ignored.
75 * @note In axisymmetric calculations, boundary faces with specific conditions may be excluded.
76 * @note The final time step is synchronized across all MPI processes using the minimum value.
77 * @note Flux contributions account for face porosity and surface area weighting.
78 */
80{
81 double dt = 1e10;
82 const Domaine_Poly_base& domaine = le_dom_poly_.valeur();
83 const DoubleVect& fs = domaine.face_surfaces(), &pf = equation().milieu().porosite_face(), &ve = domaine.volumes(),
84 &pe = equation().milieu().porosite_elem();
85 const DoubleTab& vit = vitesse_->valeurs(),
86 *alp = sub_type(Pb_Multiphase, equation().probleme()) ? &ref_cast(Pb_Multiphase, equation().probleme()).equation_masse().inconnue().passe() : nullptr;
87 const IntTab& e_f = domaine.elem_faces(), &f_e = domaine.face_voisins();
88 const IntTab *fcl = polymac_flica5 ? nullptr : &ref_cast(Champ_Face_PolyMAC_MPFA, equation().inconnue()).fcl();
89 const int N = vit.line_size();
90 DoubleTrav flux(N); //somme des flux pf * |f| * vf, volume minimal des mailles d'elements/faces affectes par ce flux
91
92 for (int e = 0; e < domaine.nb_elem(); e++)
93 {
94 const double vol = pe(e) * ve(e);
95 flux = 0.;
96
97 for (int i = 0; i < e_f.dimension(1); i++)
98 {
99 const int f = e_f(e, i);
100 if (f < 0) continue;
101 if (fcl && Option_PolyMAC_family::TRAITEMENT_AXI && (*fcl)(f, 0) == 2) continue;
102
103 for (int n = 0; n < N; n++)
104 flux(n) += pf(f) * fs(f) * std::max((e == f_e(f, 1) ? 1 : -1) * vit(f, n), 0.);
105 }
106
107 for (int n = 0; n < N; n++)
108 if ((!alp || (*alp)(e, n) > 1e-3) && std::abs(flux(n)) > 1e-12)
109 dt = std::min(dt, vol / flux(n));
110 }
111
112 return Process::mp_min(dt);
113}
114
115/*! @brief Dimensions the matrix blocks for the PolyMAC_MPFA Face convection operator with EF stabilization.
116 *
117 * This method constructs the sparsity pattern and allocates memory for the system matrix by analyzing
118 * face-element connectivity and establishing the stencil relationships between degrees of freedom.
119 * The resulting matrix structure accounts for face-face and element-element contributions based on
120 * the PolyMAC_MPFA Face discretization scheme.
121 *
122 * @param matrices Map containing the system matrices indexed by unknown field names
123 * @param semi_impl Map of semi-implicit terms indexed by unknown field names
124 *
125 * @note The method returns early if no diagonal block exists or if semi-implicit treatment is requested.
126 * @note For multiphase problems with added mass correlation, cross-coupling terms between phases are included.
127 * @note The stencil construction handles face equivalence relationships and boundary conditions appropriately.
128 * @note Duplicate entries in the stencil are automatically removed before matrix allocation.
129 */
130void Op_Conv_EF_Stab_PolyMAC_MPFA_Face::dimensionner_blocs(matrices_t matrices, const tabs_t& semi_impl) const
131{
132 const Domaine_Poly_base& domaine = le_dom_poly_.valeur();
133 const Champ_Face_PolyMAC_MPFA& ch = ref_cast(Champ_Face_PolyMAC_MPFA, equation().inconnue());
134
135 const std::string& nom_inco = ch.le_nom().getString();
136 if (!matrices.count(nom_inco) || semi_impl.count(nom_inco))
137 return; //pas de bloc diagonal ou semi-implicite -> rien a faire
138
139 const IntTab& f_e = domaine.face_voisins(), &e_f = domaine.elem_faces(), &fcl = ch.fcl(), &equiv = domaine.equiv();
140 const DoubleTab& nf = domaine.face_normales();
141 const DoubleVect& fs = domaine.face_surfaces();
142
143 const Pb_Multiphase *pbm = sub_type(Pb_Multiphase, equation().probleme()) ? &ref_cast(Pb_Multiphase, equation().probleme()) : nullptr;
144 const Masse_ajoutee_base *corr = pbm && pbm->has_correlation("masse_ajoutee") ? &ref_cast(Masse_ajoutee_base, pbm->get_correlation("masse_ajoutee")) : nullptr;
145 Matrice_Morse& mat = *matrices.at(nom_inco), mat2;
146
147 const int ne_tot = domaine.nb_elem_tot(), nf_tot = domaine.nb_faces_tot(), N = equation().inconnue().valeurs().line_size(), D = dimension;
148
149 Stencil stencil(0, 2);
150
151 // Parcourt des faces totales du domaine
152 for (int f = 0; f < domaine.nb_faces_tot(); f++)
153 if (f_e(f, 0) >= 0 && (f_e(f, 1) >= 0 || fcl(f, 0) == 3))
154 {
155 // Parcourt des deux elements adjacents a la face
156 for (int i = 0; i < 2; i++)
157 {
158 const int e = f_e(f, i);
159 if (e < 0) continue; // elem virtuel
160
161 for (int j = 0; j < 2; j++)
162 {
163 const int eb = f_e(f, j);
164 // Contribution des faces connectees a l'element
165 if (eb < 0) continue; // elem virtuel
166
167 for (int k = 0; k < e_f.dimension(1); k++)
168 {
169 const int fb = e_f(e, k);
170 if (fb < 0) continue;
171
172 if (fb < domaine.nb_faces() && fcl(fb, 0) < 2)
173 {
174 int fc = equiv(f, i, k);
175 if (fc >= 0) // face reel
176 {
177 // Cas d'equivalence : face -> face
178 for (int n = 0; n < N; n++)
179 for (int m = (corr ? 0 : n); m < (corr ? N : n + 1); m++)
180 stencil.append_line(N * fb + n, N * fc + m);
181 }
182 else if (f_e(f, 1) >= 0) // bord
183 {
184 // Pas d'equivalence : element -> face
185 for (int d = 0; d < D; d++)
186 if (std::fabs(nf(fb, d)) > 1e-6 * fs(fb))
187 for (int n = 0; n < N; n++)
188 for (int m = (corr ? 0 : n); m < (corr ? N : n + 1); m++)
189 stencil.append_line(N * fb + n, N * (nf_tot + D * eb + d) + m);
190 }
191 }
192 }
193
194 // Contribution element -element
195 for (int d = 0; d < D; d++)
196 for (int n = 0; n < N; n++)
197 for (int m = (corr ? 0 : n); m < (corr ? N : n + 1); m++)
198 stencil.append_line(N * (nf_tot + D * e + d) + n, N * (nf_tot + D * eb + d) + m);
199 }
200 }
201 }
202
203 // Suppression des doublons et allocation de la matrice
204 tableau_trier_retirer_doublons(stencil);
205 Matrix_tools::allocate_morse_matrix(N * (nf_tot + D * ne_tot), N * (nf_tot + D * ne_tot), stencil, mat2);
206 mat.nb_colonnes() ? mat += mat2 : mat = mat2;
207}
208
209/*! @brief Adds convection contributions to the system matrix and right-hand side vector.
210 *
211 * This method implements the convection operator with EF stabilization for PolyMAC_MPFA Face discretization.
212 * It computes face-based convection fluxes using upwind stabilization and assembles the corresponding
213 * matrix coefficients and source terms. The method handles both face-face and element-element contributions,
214 * accounting for face equivalence relationships and boundary conditions.
215 *
216 * @param matrices Map containing the system matrices indexed by unknown field names
217 * @param secmem Right-hand side vector to be updated with convection contributions
218 * @param semi_impl Map of semi-implicit field values indexed by field names
219 *
220 * @note The convection flux computation uses a blended upwind scheme with stabilization parameter alpha_.
221 * @note For multiphase flows, added mass correlations are included in the mass matrix contributions.
222 * @note The method distinguishes between compressible and incompressible flow formulations.
223 * @note Dirichlet boundary conditions are enforced through direct substitution in the source term.
224 * @note Face equivalence relationships are handled to maintain consistency across mesh interfaces.
225 * @note Performance statistics are automatically tracked during execution.
226 */
227void Op_Conv_EF_Stab_PolyMAC_MPFA_Face::ajouter_blocs(matrices_t matrices, DoubleTab& secmem, const tabs_t& semi_impl) const
228{
229 if (polymac_flica5)
230 {
231 const Domaine_Poly_base& domaine = le_dom_poly_.valeur();
232 const Champ_Face_PolyMAC_MPFA& ch = ref_cast(Champ_Face_PolyMAC_MPFA, le_champ_inco ? le_champ_inco.valeur() : equation().inconnue());
233 const Conds_lim& cls = la_zcl_poly_->les_conditions_limites();
234 const IntTab& f_e = domaine.face_voisins(), &e_f = domaine.elem_faces(), &fcl = ch.fcl(), &equiv = domaine.equiv();
235 const DoubleTab& vit = vitesse_->valeurs(), &nf = domaine.face_normales(), &vfd = domaine.volumes_entrelaces_dir();
236 const DoubleVect& fs = domaine.face_surfaces(), &pe = porosite_e, &pf = porosite_f, &ve = domaine.volumes();
237
238 /* a_r : produit alpha_rho si Pb_Multiphase -> par semi_implicite, ou en recuperant le champ_conserve de l'equation de masse */
239 const std::string& nom_inco = ch.le_nom().getString();
240 const DoubleTab& inco = semi_impl.count(nom_inco) ? semi_impl.at(nom_inco) : ch.valeurs();
241 Matrice_Morse *mat = matrices.count(nom_inco) && !semi_impl.count(nom_inco) ? matrices.at(nom_inco) : nullptr;
242
243 const int nf_tot = domaine.nb_faces_tot(), N = inco.line_size(), D = dimension;
244
245 DoubleTrav dfac(2, N, N), masse(N, N);
246 // Parcourt toutes les faces du domaine
247 for (int f = 0; f < domaine.nb_faces_tot(); f++)
248 {
249 if (f_e(f, 0) >= 0 && (f_e(f, 1) >= 0 || fcl(f, 0) == 1 || fcl(f, 0) == 3))
250 {
251 // Calcul des contributions des faces
252 dfac = 0.;
253 for (int i = 0; i < 2; i++)
254 {
255 // Masse : diagonale + correction
256 masse(0, 0) = std::fabs(vit[f]) > 1e-10 ? inco(f) / vit[f] : 1.0;
257
258 // Contribution a dfac
259 const int eb = f_e(f, i);
260 for (int n = 0; n < N; n++)
261 for (int m = 0; m < N; m++)
262 {
263 const double signe = (vit(f, m) * (i ? -1 : 1) >= 0) ? 1. : (vit(f, m) ? -1. : 0.);
264 dfac((fcl(f, 0) == 1) ? 0 : i, n, m) += fs(f) * inco[f] * pe(eb >= 0 ? eb : f_e(f, 0)) * (1. + signe * alpha_) / 2;
265 }
266 }
267
268 // Calcul des contributions a la matrice et au second membre
269 for (int i = 0; i < 2; i++)
270 {
271 const int e = f_e(f, i);
272 if (e < 0) continue; // elem virtuel
273
274 // partie "faces"
275 for (int k = 0; k < e_f.dimension(1); k++)
276 {
277 const int fb = e_f(e, k);
278 if (fb < 0) continue; // face in-existante (polyhedre)
279
280 if (fb < domaine.nb_faces() && fcl(fb, 0) < 2)
281 {
282 // Cas d'equivalence : face -> face
283 int fc = equiv(f, i, k);
284 if (fc >= 0 || f_e(f, 1) < 0)
285 {
286 for (int j = 0; j < 2; j++)
287 {
288 int eb = f_e(f, j);
289 const int fd = (j == i) ? fb : fc; // Face source
290 //multiplicateur pour passer de vf a ve
291 double mult = (fd < 0 || domaine.dot(&nf(fb, 0), &nf(fd, 0)) > 0) ? 1 : -1;
292 mult *= (fd >= 0) ? pf(fd) / pe(eb) : 1;
293
294 for (int n = 0; n < N; n++)
295 for (int m = 0; m < N; m++)
296 if (dfac(j, n, m))
297 {
298 const double fac = (i ? -1 : 1) * vfd(fb, e != f_e(fb, 0)) * dfac(j, n, m) / ve(e);
299
300 // Mise a jour du second membre
301 if (fd >= 0)
302 secmem(fb, n) -= fac * mult * vit[fd];
303 else
304 // CL de Dirichlet
305 for (int d = 0; d < D; d++)
306 secmem(fb, n) -= fac * nf(fb, d) / fs(fb) * ref_cast(Dirichlet, cls[fcl(f, 1)].valeur()).val_imp(fcl(f, 2), N * d + m) / masse(0, 0);
307
308 if (!incompressible_)
309 secmem(fb, n) += fac * vit[fb];
310
311 // Mise a jour de la matrice
312 if (mat && fac)
313 {
314 if (fd >= 0 && fcl(fd, 0) < 2)
315 (*mat)(N * fb + n, N * fd + m) += fac * mult;
316 if (!incompressible_)
317 (*mat)(N * fb + n, N * fb + m) -= fac;
318 }
319 }
320 }
321 }
322 // Cas sans equivalence :elements connectes
323 else
324 {
325 for (int j = 0; j < 2; j++)
326 {
327 const int eb = f_e(f, j);
328 for (int d = 0; d < D; d++)
329 if (std::fabs(nf(fb, d)) > 1e-6 * fs(fb))
330 for (int n = 0; n < N; n++)
331 for (int m = 0; m < N; m++)
332 if (dfac(j, n, m))
333 {
334 const double fac = (i ? -1 : 1) * vfd(fb, e != f_e(fb, 0)) * dfac(j, n, m) / ve(e) * nf(fb, d) / fs(fb);
335
336 // Mise a jour du second membre
337 secmem(fb, n) -= fac * vit[nf_tot + D * eb + d];
338 if (!incompressible_)
339 secmem(fb, n) += fac * vit[nf_tot + D * e + d];
340
341 // Mise a jour de la matrice
342 if (mat && fac)
343 {
344 (*mat)(N * fb + n, N * (nf_tot + D * eb + d) + m) += fac;
345 if (!incompressible_)
346 (*mat)(N * fb + n, N * (nf_tot + D * e + d) + m) -= fac;
347 }
348 }
349 }
350 }
351 }
352 }
353
354 // partie "elem"
355 for (int j = 0; j < 2; j++)
356 {
357 const int eb = f_e(f, j);
358 for (int d = 0; d < D; d++)
359 for (int n = 0; n < N; n++)
360 for (int m = 0; m < N; m++)
361 if (dfac(j, n, m))
362 {
363 const double fac = (i ? -1 : 1) * dfac(j, n, m);
364
365 // Mise a jour du second membre
366 secmem(nf_tot + D * e + d, n) -= fac * (eb >= 0 ? vit[nf_tot + D * eb + d] : ref_cast(Dirichlet, cls[fcl(f, 1)].valeur()).val_imp(fcl(f, 2), N * d + m));
367 if (!incompressible_)
368 secmem(nf_tot + D * e + d, n) += fac * vit[nf_tot + D * e + d]; //partie v div(alpha rho v)
369
370 if (mat && fac)
371 {
372 if (eb >= 0)
373 (*mat)(N * (nf_tot + D * e + d) + n, N * (nf_tot + D * eb + d) + m) += fac;
374 if (!incompressible_)
375 (*mat)(N * (nf_tot + D * e + d) + n, N * (nf_tot + D * e + d) + m) -= fac;
376 }
377 }
378 }
379 }
380 }
381 }
382 return;
383 }
384
385 const Domaine_Poly_base& domaine = le_dom_poly_.valeur();
386 const Champ_Face_PolyMAC_MPFA& ch = ref_cast(Champ_Face_PolyMAC_MPFA, equation().inconnue());
387 const Conds_lim& cls = la_zcl_poly_->les_conditions_limites();
388 const IntTab& f_e = domaine.face_voisins(), &e_f = domaine.elem_faces(), &fcl = ch.fcl(), &equiv = domaine.equiv();
389 const DoubleTab& vit = ch.passe(), &nf = domaine.face_normales(), &vfd = domaine.volumes_entrelaces_dir();
390 const DoubleVect& fs = domaine.face_surfaces(), &pe = porosite_e, &pf = porosite_f, &ve = domaine.volumes();
391
392 /* a_r : produit alpha_rho si Pb_Multiphase -> par semi_implicite, ou en recuperant le champ_conserve de l'equation de masse */
393 const std::string& nom_inco = ch.le_nom().getString();
394 const Pb_Multiphase *pbm = sub_type(Pb_Multiphase, equation().probleme()) ? &ref_cast(Pb_Multiphase, equation().probleme()) : nullptr;
395 const Masse_ajoutee_base *corr = pbm && pbm->has_correlation("masse_ajoutee") ? &ref_cast(Masse_ajoutee_base, pbm->get_correlation("masse_ajoutee")) : nullptr;
396 const DoubleTab& inco = semi_impl.count(nom_inco) ? semi_impl.at(nom_inco) : ch.valeurs(),
397 *a_r = !pbm ? nullptr : semi_impl.count("alpha_rho") ? &semi_impl.at("alpha_rho") : &pbm->equation_masse().champ_conserve().valeurs(),
398 *alp = pbm ? &pbm->equation_masse().inconnue().passe() : nullptr, &rho = equation().milieu().masse_volumique().passe();
399 Matrice_Morse *mat = matrices.count(nom_inco) && !semi_impl.count(nom_inco) ? matrices.at(nom_inco) : nullptr;
400
401 const int nf_tot = domaine.nb_faces_tot(), N = inco.line_size(), D = dimension;
402
403 DoubleTrav dfac(2, N, N), masse(N, N);
404 // Parcourt toutes les faces du domaine
405 for (int f = 0; f < domaine.nb_faces_tot(); f++)
406 {
407 if (f_e(f, 0) >= 0 && (f_e(f, 1) >= 0 || fcl(f, 0) == 1 || fcl(f, 0) == 3))
408 {
409 // Calcul des contributions des faces
410 dfac = 0.;
411 for (int i = 0; i < 2; i++)
412 {
413 const int e = f_e(f, (f_e(f, i) >= 0) ? i : 0);
414
415 // Masse : diagonale + correction
416 masse = 0.;
417 for (int n = 0; n < N; n++)
418 masse(n, n) = a_r ? (*a_r)(e, n) : 1;
419
420 if (corr)
421 corr->ajouter(&(*alp)(e, 0), &rho(e, 0), masse);
422
423 // Contribution a dfac
424 const int eb = f_e(f, i);
425 for (int n = 0; n < N; n++)
426 for (int m = 0; m < N; m++)
427 {
428 const double signe = (vit(f, m) * (i ? -1 : 1) >= 0) ? 1. : (vit(f, m) ? -1. : 0.);
429 dfac((fcl(f, 0) == 1) ? 0 : i, n, m) += fs(f) * vit(f, m) * pe(eb >= 0 ? eb : f_e(f, 0)) * masse(n, m) * (1. + signe * alpha_) / 2;
430 }
431 }
432
433 // Calcul des contributions a la matrice et au second membre
434 for (int i = 0; i < 2 ; i++)
435 {
436 const int e = f_e(f, i);
437 if (e < 0) continue; // elem virtuel
438
439 // partie "faces"
440 for (int k = 0; k < e_f.dimension(1); k++)
441 {
442 const int fb = e_f(e, k);
443 if (fb < 0) continue; // face in-existante (polyhedre)
444
445 if (fb < domaine.nb_faces() && fcl(fb, 0) < 2)
446 {
447 // Cas d'equivalence : face -> face
448 int fc = equiv(f, i, k);
449 if (fc >= 0 || f_e(f, 1) < 0)
450 {
451 for (int j = 0; j < 2; j++)
452 {
453 int eb = f_e(f, j);
454 const int fd = (j == i) ? fb : fc; // Face source
455 //multiplicateur pour passer de vf a ve
456 double mult = (fd < 0 || domaine.dot(&nf(fb, 0), &nf(fd, 0)) > 0) ? 1 : -1;
457 mult *= (fd >= 0) ? pf(fd) / pe(eb) : 1;
458
459 for (int n = 0; n < N; n++)
460 for (int m = 0; m < N; m++)
461 if (dfac(j, n, m))
462 {
463 const double fac = (i ? -1 : 1) * vfd(fb, e != f_e(fb, 0)) * dfac(j, n, m) / ve(e);
464
465 // Mise a jour du second membre
466 if (fd >= 0)
467 secmem(fb, n) -= fac * mult * inco(fd, m);
468 else
469 // CL de Dirichlet
470 for (int d = 0; d < D; d++)
471 secmem(fb, n) -= fac * nf(fb, d) / fs(fb) * ref_cast(Dirichlet, cls[fcl(f, 1)].valeur()).val_imp(fcl(f, 2), N * d + m);
472
473 if (!incompressible_)
474 secmem(fb, n) += fac * inco(fb, m);
475
476 // Mise a jour de la matrice
477 if (mat && fac)
478 {
479 if (fd >= 0 && fcl(fd, 0) < 2)
480 (*mat)(N * fb + n, N * fd + m) += fac * mult;
481 if (!incompressible_)
482 (*mat)(N * fb + n, N * fb + m) -= fac;
483 }
484 }
485 }
486 }
487 // Cas sans equivalence :elements connectes
488 else
489 {
490 for (int j = 0; j < 2; j++)
491 {
492 const int eb = f_e(f, j);
493 for (int d = 0; d < D; d++)
494 if (std::fabs(nf(fb, d)) > 1e-6 * fs(fb))
495 for (int n = 0; n < N; n++)
496 for (int m = 0; m < N; m++)
497 if (dfac(j, n, m))
498 {
499 const double fac = (i ? -1 : 1) * vfd(fb, e != f_e(fb, 0)) * dfac(j, n, m) / ve(e) * nf(fb, d) / fs(fb);
500
501 // Mise a jour du second membre
502 secmem(fb, n) -= fac * inco(nf_tot + D * eb + d, m);
503 if (!incompressible_)
504 secmem(fb, n) += fac * inco(nf_tot + D * e + d, m);
505
506 // Mise a jour de la matrice
507 if (mat && fac)
508 {
509 (*mat)(N * fb + n, N * (nf_tot + D * eb + d) + m) += fac;
510 if (!incompressible_)
511 (*mat)(N * fb + n, N * (nf_tot + D * e + d) + m) -= fac;
512 }
513 }
514 }
515 }
516 }
517 }
518
519 // partie "elem"
520 for (int j = 0; j < 2; j++)
521 {
522 const int eb = f_e(f, j);
523 for (int d = 0; d < D; d++)
524 for (int n = 0; n < N; n++)
525 for (int m = 0; m < N; m++)
526 if (dfac(j, n, m))
527 {
528 const double fac = (i ? -1 : 1) * dfac(j, n, m);
529
530 // Mise a jour du second membre
531 secmem(nf_tot + D * e + d, n) -= fac * (eb >= 0 ? inco(nf_tot + D * eb + d, m) : ref_cast(Dirichlet, cls[fcl(f, 1)].valeur()).val_imp(fcl(f, 2), N * d + m));
532 if (!incompressible_)
533 secmem(nf_tot + D * e + d, n) += fac * inco(nf_tot + D * e + d, m); //partie v div(alpha rho v)
534
535 if (mat && fac)
536 {
537 if (eb >= 0)
538 (*mat)(N * (nf_tot + D * e + d) + n, N * (nf_tot + D * eb + d) + m) += fac;
539 if (!incompressible_)
540 (*mat)(N * (nf_tot + D * e + d) + n, N * (nf_tot + D * e + d) + m) -= fac;
541 }
542 }
543 }
544 }
545 }
546 }
547}
: class Champ_Face_PolyMAC_MPFA
const IntTab & fcl() const
DoubleTab & passe(int i=1) override
Renvoie les valeurs du champs a l'instant t-i.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual DoubleTab & passe(int i=1)
Definition Champ_Proto.h:50
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
classe Dirichlet Cette classe est la classe de base de la hierarchie des conditions aux limites de ty...
Definition Dirichlet.h:31
class Domaine_Poly_base
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const Milieu_base & milieu() const =0
Champ_Inc_base & champ_conserve() const
virtual const Champ_Inc_base & inconnue() const =0
const Nom & le_nom() const override
Renvoie le nom du champ.
classe Masse_ajoutee_base masse ajoutee de la forme
virtual void ajouter(const double *alpha, const double *rho, DoubleTab &a_r) const =0
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
int nb_colonnes() const override
Return local number of columns (=size on the current proc).
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_base & masse_volumique() const
Renvoie la masse volumique du milieu.
DoubleVect & porosite_face()
Definition Milieu_base.h:62
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
const std::string & getString() const
Definition Nom.h:92
static int dimension
Definition Objet_U.h:99
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
void completer() override
Associe l'operateur au domaine_dis, le domaine_Cl_dis, et a l'inconnue de son equation.
double calculer_dt_stab() const override
Computes the stability time step for the convection operator.
void dimensionner_blocs(matrices_t matrices, const tabs_t &semi_impl={ }) const override
Dimensions the matrix blocks for the PolyMAC_MPFA Face convection operator with EF stabilization.
void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={ }) const override
Adds convection contributions to the system matrix and right-hand side vector.
virtual void completer()
Associe l'operateur au domaine_dis, le domaine_Cl_dis, et a l'inconnue de son equation.
classe Pb_Multiphase Cette classe represente un probleme de thermohydraulique multiphase de type "3*N...
virtual Equation_base & equation_masse()
int has_correlation(std::string nom_correlation) const
const Correlation_base & get_correlation(std::string nom_correlation) const
static double mp_min(double)
Definition Process.cpp:386
Classe de base des flux de sortie.
Definition Sortie.h:52
void append_line(_TYPE_)
Definition TRUSTTab.tpp:213
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
int line_size() const
Definition TRUSTVect.tpp:67