TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Conv_EF_Stab_PolyMAC_HFV_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_HFV_Face.h>
17#include <Champ_Face_PolyMAC_HFV.h>
18#include <Dirichlet_homogene.h>
19#include <Masse_ajoutee_base.h>
20#include <Schema_Temps_base.h>
21#include <Domaine_Cl_PolyMAC_family.h>
22#include <Domaine_Poly_base.h>
23#include <Pb_Multiphase.h>
24#include <Matrix_tools.h>
25#include <Array_tools.h>
26#include <TRUSTLists.h>
27#include <Dirichlet.h>
28#include <Param.h>
29#include <cmath>
30
31Implemente_instanciable( Op_Conv_EF_Stab_PolyMAC_HFV_Face, "Op_Conv_EF_Stab_PolyMAC_HFV_Face", Op_Conv_EF_Stab_PolyMAC_CDO_Face );
32Implemente_instanciable( Op_Conv_Amont_PolyMAC_HFV_Face, "Op_Conv_Amont_PolyMAC_HFV_Face", Op_Conv_EF_Stab_PolyMAC_HFV_Face );
33Implemente_instanciable( Op_Conv_Centre_PolyMAC_HFV_Face, "Op_Conv_Centre_PolyMAC_HFV_Face", Op_Conv_EF_Stab_PolyMAC_HFV_Face );
34
35// XD Op_Conv_EF_Stab_PolyMAC_HFV_Face interprete Op_Conv_EF_Stab_PolyMAC_HFV_Face BRACE Class
36// XD_CONT Op_Conv_EF_Stab_PolyMAC_HFV_Face
37
41
43
45{
46 alpha_ = 1.0;
48}
49
51{
52 alpha_ = 0.0;
54}
55
57{
58 double dt = 1e10;
59 const Domaine_Poly_base& domaine = le_dom_poly_.valeur();
60 const DoubleVect& fs = domaine.face_surfaces(), &pf = equation().milieu().porosite_face(), &ve = domaine.volumes(), &pe = equation().milieu().porosite_elem();
61 const DoubleTab& vit = vitesse_->valeurs(),
62 *alp = sub_type(Pb_Multiphase, equation().probleme()) ? &ref_cast(Pb_Multiphase, equation().probleme()).equation_masse().inconnue().passe() : nullptr;
63 const IntTab& e_f = domaine.elem_faces(), &f_e = domaine.face_voisins();
64 const int N = vit.line_size();
65 DoubleTrav flux(N); //somme des flux pf * |f| * vf, volume minimal des mailles d'elements/faces affectes par ce flux
66
67 for (int e = 0; e < domaine.nb_elem(); e++)
68 {
69 // Calcul du volume effectif de l'element
70 const double vol = pe(e) * ve(e);
71 flux = 0.;
72
73 // Parcourt des faces associees a l'element
74 for (int i = 0; i < e_f.dimension(1); i++)
75 {
76 int f = e_f(e, i);
77 if (f < 0) continue; // face in-existante
78
79 for (int n = 0; n < N; n++)
80 {
81 // Ajout du flux entrant pour la composante n : Seuls les flux entrants comptent
82 double flux_f = pf(f) * fs(f) * std::max((e == f_e(f, 1) ? 1 : -1) * vit(f, n), 0.);
83 flux(n) += flux_f;
84 }
85 }
86
87 // Calcul du pas de temps pour chaque composante n
88 for (int n = 0; n < N; n++)
89 if ((!alp || (*alp)(e, n) > 1e-3) && std::abs(flux(n)) > 1e-12)
90 dt = std::min(dt, vol / flux(n));
91 }
92
93 return Process::mp_min(dt);
94}
95
96void Op_Conv_EF_Stab_PolyMAC_HFV_Face::dimensionner_blocs(matrices_t matrices, const tabs_t& semi_impl) const
97{
98 const Domaine_Poly_base& domaine = le_dom_poly_.valeur();
99 const Champ_Face_PolyMAC_HFV& ch = ref_cast(Champ_Face_PolyMAC_HFV, equation().inconnue());
100 const IntTab& f_e = domaine.face_voisins(), &e_f = domaine.elem_faces(), &fcl = ch.fcl(), &equiv = domaine.equiv();
101 const DoubleTab& nf = domaine.face_normales(), &inco = ch.valeurs(), &xp = domaine.xp(), &xv = domaine.xv();
102 const DoubleVect& fs = domaine.face_surfaces(), &ve = domaine.volumes();
103
104 const std::string& nom_inco = ch.le_nom().getString();
105
106 if (!matrices.count(nom_inco) || semi_impl.count(nom_inco))
107 return; //pas de bloc diagonal ou semi-implicite -> rien a faire
108
109 const Pb_Multiphase *pbm = sub_type(Pb_Multiphase, equation().probleme()) ? &ref_cast(Pb_Multiphase, equation().probleme()) : nullptr;
110 const Masse_ajoutee_base *corr = pbm && pbm->has_correlation("masse_ajoutee") ? &ref_cast(Masse_ajoutee_base, pbm->get_correlation("masse_ajoutee")) : nullptr;
111 Matrice_Morse& mat = *matrices.at(nom_inco), mat2;
112
113 const int N = equation().inconnue().valeurs().line_size();
114
115 Stencil stencil(0, 2);
116
117 /* Ce bloc agit uniquement aux elements; la diagonale de la matrice est omise. */
118 for (int f = 0; f < domaine.nb_faces_tot(); f++)
119 {
120 // Verifie si la face est interne ou satisfait les conditions aux limites
121 if (f_e(f, 0) >= 0 && (f_e(f, 1) >= 0 || fcl(f, 0) == 3))
122 {
123 // Parcourt les elements associes a cette face
124 for (int i = 0; i < 2 ; i++)
125 {
126 const int e = f_e(f, i);
127 if (e < 0) continue; // elem virt
128
129 for (int j = 0; j < 2 ; j++)
130 {
131 const int eb = f_e(f, j);
132 // Parcourt les faces connectees a l'element courant
133 if (eb < 0) continue;
134
135 for (int k = 0; k < e_f.dimension(1); k++)
136 {
137 const int fb = e_f(e, k);
138 if (fb <0) continue;
139
140 if (fb < domaine.nb_faces())
141 {
142 int fc = equiv(f, i, k);
143 // Cas ou une equivalence entre faces existe
144 if (fc >= 0)
145 {
146 for (int n = 0; n < N; n++)
147 for (int m = (corr ? 0 : n); m < (corr ? N : n + 1); m++)
148 stencil.append_line(N * fb + n, N * fc + m);
149 }
150 // Cas sans equivalence : contributions entre faces de l'element
151 else if (f_e(f, 1) >= 0)
152 {
153 for (int l = 0; l < e_f.dimension(1); l++)
154 {
155 fc = e_f(eb, l);
156 if (fc < 0) continue;
157
158 const double critere = fs(fc) * domaine.dot(&xv(fc, 0), &nf(fb, 0), &xp(eb, 0));
159 if (std::abs(critere) > 1e-6 * ve(eb) * fs(fb))
160 for (int n = 0; n < N; n++)
161 for (int m = (corr ? 0 : n); m < (corr ? N : n + 1); m++)
162 stencil.append_line(N * fb + n, N * fc + m);
163 }
164 }
165 }
166 }
167 }
168 }
169 }
170 }
171
172 // Trie et retire les doublons dans le stencil
173 tableau_trier_retirer_doublons(stencil);
174
175 // Alloue une matrice clairsemee basee sur le stencil
176 Matrix_tools::allocate_morse_matrix(inco.size_totale(), inco.size_totale(), stencil, mat2);
177
178 // Ajoute mat2 a la matrice existante ou initialise 'mat'
179 if (mat.nb_colonnes())
180 mat += mat2;
181 else
182 mat = mat2;
183}
184
185// ajoute la contribution de la convection au second membre resu
186// renvoie resu
187void Op_Conv_EF_Stab_PolyMAC_HFV_Face::ajouter_blocs(matrices_t matrices, DoubleTab& secmem, const tabs_t& semi_impl) const
188{
189 const Domaine_Poly_base& domaine = le_dom_poly_.valeur();
190 const Champ_Face_PolyMAC_HFV& ch = ref_cast(Champ_Face_PolyMAC_HFV, equation().inconnue());
191 const Conds_lim& cls = la_zcl_poly_->les_conditions_limites();
192 const IntTab& f_e = domaine.face_voisins(), &e_f = domaine.elem_faces(), &fcl = ch.fcl(), &equiv = domaine.equiv();
193 const DoubleTab& vit = ch.passe(), &nf = domaine.face_normales(), &vfd = domaine.volumes_entrelaces_dir(), &xp = domaine.xp(), &xv = domaine.xv();
194 const DoubleVect& fs = domaine.face_surfaces(), &pe = porosite_e, &pf = porosite_f, &ve = domaine.volumes();
195
196 /* a_r : produit alpha_rho si Pb_Multiphase -> par semi_implicite, ou en recuperant le champ_conserve de l'equation de masse */
197 const std::string& nom_inco = ch.le_nom().getString();
198 const Pb_Multiphase *pbm = sub_type(Pb_Multiphase, equation().probleme()) ? &ref_cast(Pb_Multiphase, equation().probleme()) : nullptr;
199 const Masse_ajoutee_base *corr = pbm && pbm->has_correlation("masse_ajoutee") ? &ref_cast(Masse_ajoutee_base, pbm->get_correlation("masse_ajoutee")) : nullptr;
200 const DoubleTab& inco = semi_impl.count(nom_inco) ? semi_impl.at(nom_inco) : ch.valeurs(),
201 *a_r = !pbm ? nullptr : semi_impl.count("alpha_rho") ? &semi_impl.at("alpha_rho") : &pbm->equation_masse().champ_conserve().valeurs(),
202 *alp = pbm ? &pbm->equation_masse().inconnue().passe() : nullptr,
203 &rho = equation().milieu().masse_volumique().passe();
204
205 Matrice_Morse *mat = matrices.count(nom_inco) && !semi_impl.count(nom_inco) ? matrices.at(nom_inco) : nullptr;
206
207 const int N = inco.line_size(), D = dimension;
208
209 DoubleTrav dfac(2, N, N), masse(N, N);
210
211 // Parcourt toutes les faces du domaine
212 for (int f = 0; f < domaine.nb_faces_tot(); f++)
213 {
214 if (f_e(f, 0) >= 0 && (f_e(f, 1) >= 0 || fcl(f, 0) == 1 || fcl(f, 0) == 3))
215 {
216 // Calcul des contributions des faces
217 dfac = 0.;
218 for (int i = 0; i < 2; i++)
219 {
220 // Masse diagonale avec correction si necessaire
221 masse = 0.;
222 int e = f_e(f, (f_e(f, i) >= 0) ? i : 0);
223 for (int n = 0; n < N; n++)
224 masse(n, n) = a_r ? (*a_r)(e, n) : 1.;
225
226 if (corr)
227 corr->ajouter(&(*alp)(e, 0), &rho(e, 0), masse);
228
229 // Contribution a dfac
230 e = f_e(f, i);
231 int eb = f_e(f, i);
232 for (int n = 0; n < N; n++)
233 for (int m = 0; m < N; m++)
234 {
235 const double signe = (vit(f, m) * (i ? -1 : 1) >= 0) ? 1. : (vit(f, m) ? -1. : 0.);
236 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;
237 }
238 }
239
240 // Contributions aux matrices et au second membre
241 for (int i = 0; i < 2 ; i++)
242 {
243 const int e = f_e(f, i);
244 if (e < 0) continue;
245
246 for (int k = 0; k < e_f.dimension(1) ; k++)
247 {
248 const int fb = e_f(e, k);
249 if (fb < 0) continue;
250
251 if (fb < domaine.nb_faces())
252 {
253 int fc = equiv(f, i, k);
254 // Cas d'equivalence : face source -> face cible
255 if (fc >= 0 || f_e(f, 1) < 0)
256 {
257 for (int j = 0; j < 2; j++)
258 {
259 int eb = f_e(f, j);
260 int fd = (j == i) ? fb : fc; // Face ou element source
261
262 //multiplicateur pour passer de vf a ve
263 double mult = (fd < 0 || domaine.dot(&nf(fb, 0), &nf(fd, 0)) > 0) ? 1 : -1;
264 mult *= (fd >= 0) ? pf(fd) / pe(eb) : 1;
265
266 for (int n = 0; n < N; n++)
267 for (int m = 0; m < N; m++)
268 {
269 if (dfac(j, n, m))
270 {
271 double fac = (i ? -1 : 1) * vfd(fb, e != f_e(fb, 0)) * dfac(j, n, m) / ve(e);
272
273 // Mise a jour du second membre
274 if (fd >= 0)
275 secmem(fb, n) -= fac * mult * inco(fd, m);
276 else
277 {
278 // CL de Dirichlet
279 for (int d = 0; d < D; d++)
280 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);
281 }
282 if (!incompressible_)
283 secmem(fb, n) += fac * inco(fb, m);
284
285 // Mise a jour de la matrice
286 if (mat)
287 {
288 if (fd >= 0)
289 (*mat)(N * fb + n, N * fd + m) += fac * mult;
290
291 if (!incompressible_)
292 (*mat)(N * fb + n, N * fb + m) -= fac;
293 }
294 }
295 }
296 }
297 }
298 // Cas sans equivalence : n_f * operateur elementaire
299 else
300 {
301 for (int j = 0; j < 2; j++)
302 {
303 const int eb = f_e(f, j);
304 for (int l = 0; l < e_f.dimension(1) ; l++)
305 {
306 fc = e_f(eb, l);
307 if (fc < 0) continue;
308
309 double critere = fs(fc) * domaine.dot(&xv(fc, 0), &nf(fb, 0), &xp(eb, 0));
310 if (std::abs(critere) > 1e-6 * ve(eb) * fs(fb))
311 {
312 for (int n = 0; n < N; n++)
313 for (int m = 0; m < N; m++)
314 if (dfac(j, n, m))
315 {
316 double fac = (i ? -1 : 1) * vfd(fb, e != f_e(fb, 0)) * dfac(j, n, m) * ((eb == f_e(fc, 0)) ? 1 : -1) * critere / (ve(e) * ve(eb) * fs(fb));
317 secmem(fb, n) -= fac * inco(fc, m);
318 if (mat && fac)
319 (*mat)(N * fb + n, N * fc + m) += fac;
320 }
321 }
322 }
323 // Partie correction si 'comp'
324 if (!incompressible_)
325 {
326 for (int l = 0; l < e_f.dimension(1) ; l++)
327 {
328 fc = e_f(e, l);
329 if (fc < 0) continue;
330
331 double critere = fs(fc) * domaine.dot(&xv(fc, 0), &nf(fb, 0), &xp(e, 0));
332 if (std::abs(critere) > 1e-6 * ve(e) * fs(fb))
333 {
334 for (int n = 0; n < N; n++)
335 for (int m = 0; m < N; m++)
336 {
337 if (dfac(j, n, m))
338 {
339 double fac = (i ? -1 : 1) * vfd(fb, e != f_e(fb, 0)) * dfac(j, n, m) * ((e == f_e(fc, 0)) ? 1 : -1) * critere / (ve(e) * ve(e) * fs(fb));
340 secmem(fb, n) += fac * inco(fc, m);
341 if (mat && fac)
342 (*mat)(N * fb + n, N * fc + m) -= fac;
343 }
344 }
345 }
346 }
347 }
348 }
349 }
350 }
351 }
352 }
353 }
354 }
355}
: class Champ_Face_PolyMAC_HFV
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
double calculer_dt_stab() const override
Calcul dt_stab.
void dimensionner_blocs(matrices_t matrices, const tabs_t &semi_impl={ }) const override
void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl={ }) const override
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