16#include <Modele_turbulence_scal_base.h>
17#include <Echange_contact_PolyMAC_CDO.h>
18#include <Op_Diff_PolyMAC_CDO_Elem.h>
19#include <Domaine_Cl_PolyMAC_family.h>
20#include <Champ_Elem_PolyMAC_CDO.h>
21#include <Probleme_base.h>
22#include <Matrix_tools.h>
23#include <Array_tools.h>
24#include <TRUSTTab_parts.h>
53 bool flag =
Process::nproc() == 1 && le_dom_poly_->nb_elem() < 10000;
54 EChaine chl(flag ?
"Petsc Cholesky_lapack { quiet }" :
"Petsc Cholesky { quiet }");
56 solveur.nommer(
"Op_Diff_PolyMAC_CDO_Elem solver");
60 if (domaine.domaine().nb_joints() && domaine.domaine().joint(0).epaisseur() < 1)
61 Cerr <<
"Op_Diff_PolyMAC_CDO_Elem : largeur de joint insuffisante (minimum 1)!" << finl,
Process::exit();
64 flux_bords_.resize(domaine.premiere_face_int(), nb_comp);
70 domaine.domaine().creer_tableau_elements(
delta_e), domaine.creer_tableau_faces(
delta_f), domaine.creer_tableau_faces(
delta_f_int);
72 delta_int_a_jour_ = delta_a_jour_ = (
stab_ ? 0 : 1);
84 if (delta_int_a_jour_)
89 const DoubleVect& fs = domaine.face_surfaces(), &ve = domaine.volumes();
90 int i, j, k, l, e, f, fb, ne_tot = domaine.nb_elem_tot(), n, N = inco.
line_size();
95 DoubleTrav nu_ef(e_f.
dimension(1), N), de_num(N), de_den(N);
96 for (e = 0; e < domaine.nb_elem_tot(); e++)
98 de_num = 0, de_den = 0;
100 for (i = 0, j = domaine.m2d(e); j < domaine.m2d(e + 1); i++, j++)
103 for (f = e_f(e, i), k = domaine.w2i(j); k < domaine.w2i(j + 1); k++)
104 for (fb = e_f(e, l = domaine.w2j(k)), fac = fs(f) * fs(fb) / ve(e) * domaine.w2c(k), n = 0; n < N; n++)
106 fac_n = fac * nu_ef(l, n) * (inco(ne_tot + fb, n) - inco(e, n));
108 delta_f_int(f, n, 1) += std::fabs(inco(ne_tot + fb, n) - inco(ne_tot + f, n));
111 for (n = 0; n < N; n++)
113 fac = std::fabs(inco(e, n) - inco(ne_tot + f, n));
118 for (n = 0; n < N; n++)
119 delta_e(e, n) = de_den(n) > 1e-8 ? std::fabs(de_num(n)) / de_den(n) : 0;
122 delta_int_a_jour_ = 1;
130 const Conds_lim& cls = la_zcl_poly_->les_conditions_limites();
136 for (i = 0; i < cls.size(); i++)
140 for (f = 0; f < domaine.nb_faces_tot(); f++)
141 for (n = 0; n < N; n++)
145 for (i = 0; ch.
fcl()(f, 0) == 3 && i < 2; i++)
147 delta_f(f, n) = n_d[1] > 1e-8 ? std::fabs(n_d[0]) / n_d[1] : 0;
149 delta_f.echange_espace_virtuel();
167 Process::exit(
"Op_Diff_PolyMAC_CDO_Elem::dimensionner_bloc : invalid bloc number! p must be in [-1, 3]");
172 int i, j, k, l, e, f, ne_tot = domaine.nb_elem_tot(), nf_tot = domaine.nb_faces_tot(), n, N = ch.
valeurs().
line_size();
175 Stencil stencil(0, 2);
177 for (
int q = 0; q < 4; q++) sp[q].resize(0, 2);
179 for (e = 0; e < domaine.nb_elem_tot(); e++)
182 if (e < domaine.nb_elem())
183 for (n = 0; n < N; n++)
186 sp[0].append_line(N * e + n, N * e + n);
188 for (i = 0; i < e_f.
dimension(1) && (f = e_f(e, i)) >= 0; i++)
189 for (n = 0; f < domaine.nb_faces() && n < N; n++)
191 stencil.
append_line(N * (ne_tot + f) + n, N * e + n);
192 sp[2].append_line(N * f + n, N * e + n);
196 for (j = 0, k = domaine.m2d(e); k < domaine.m2d(e + 1); j++, k++)
197 for (f = e_f(e, j), l = domaine.w2i(k); l < domaine.w2i(k + 1); l++)
200 for (n = 0; e < domaine.nb_elem() && n < N; n++)
202 stencil.
append_line(N * e + n, N * (ne_tot + e_f(e, domaine.w2j(l))) + n);
203 sp[1].append_line(N * e + n, N * e_f(e, domaine.w2j(l)) + n);
207 for (n = 0; f < domaine.nb_faces() && n < N; n++)
209 stencil.
append_line(N * (ne_tot + f) + n, N * (ne_tot + e_f(e, domaine.w2j(l))) + n);
210 sp[3].append_line(N * f + n, N * e_f(e, domaine.w2j(l)) + n);
216 tableau_trier_retirer_doublons(stencil);
221 tableau_trier_retirer_doublons(sp[p]);
222 const int nx = N * ((p <= 1) ? ne_tot : nf_tot);
223 const int ny = N * ((p == 0 || p == 2) ? ne_tot : nf_tot);
232 const Conds_lim& cls = la_zcl_poly_->les_conditions_limites();
233 int i, j, k, l, f, n, N = ch.
valeurs().
line_size(), ne_tot = domaine.nb_elem_tot();
235 Stencil stencil(0, 2);
237 for (i = 0; i < cls.size(); i++)
248 for (n = 0; n < N; n++)
249 stencil.
append_line(N * (ne_tot + f) + n, N * l + n);
252 tableau_trier_retirer_doublons(stencil);
260 const Conds_lim& cls = la_zcl_poly_->les_conditions_limites();
261 int i, j, k, l, f, n, N = ch.
valeurs().
line_size(), ne_tot = domaine.nb_elem_tot();
265 for (i = 0; i < cls.size(); i++)
269 for (i = 0; i < cls.size(); i++)
276 for (j = 0; j < fvf.
nb_faces(); j++)
279 for (n = 0; n < N; n++)
280 resu(ne_tot + f, n) -= cl.
coeff(j, 0, n) * inco(ne_tot + f, n);
282 for (n = 0; n < N; n++)
285 resu(ne_tot + f, n) -= cl.
coeff(j, k + 1, n) * autre_inco(l, n);
288 resu(ne_tot + f, n) -= std::max(
delta_f(f, n), cl.
delta(j, k, n)) * (inco(ne_tot + f, n) - autre_inco(l, n));
298 const Conds_lim& cls = la_zcl_poly_->les_conditions_limites();
299 int i, j, k, l, f, n, N = ch.
valeurs().
line_size(), ne_tot = domaine.nb_elem_tot();
303 for (i = 0; i < cls.size(); i++)
307 for (i = 0; i < cls.size(); i++)
314 for (j = 0; j < fvf.
nb_faces(); j++)
316 for (n = 0; n < N; n++)
317 matrice(N * (ne_tot + f) + n, N * l + n) += cl.
coeff(j, k + 1, n) - (
stab_ ? std::max(
delta_f(f, n), cl.
delta(j, k, n)) : 0);
325 const Conds_lim& cls = la_zcl_poly_->les_conditions_limites();
326 const IntTab& e_f = domaine.elem_faces();
327 const DoubleVect& fs = domaine.face_surfaces(), &ve = domaine.volumes();
328 int i, j, e, f, fb, ne_tot = domaine.nb_elem_tot(), n, N = inco.
line_size();
329 bool elem_only = polymac_flica5 ? resu.
dimension_tot(0) == ne_tot :
false;
334 for (i = 0; i < cls.size(); i++)
339 DoubleTrav nu_ef(e_f.
dimension(1), N), mff(N), mfe(N), mee(N);
340 for (e = 0; e < ne_tot; e++)
343 int n_f = domaine.m2d(e + 1) - domaine.m2d(e);
344 for (
remplir_nu_ef(e, nu_ef), mee = 0, i = 0; i < n_f; i++, mee += mfe)
346 for (f = e_f(e, i), j = domaine.w2i(domaine.m2d(e) + i), mfe = 0; j < domaine.w2i(domaine.m2d(e) + i + 1); j++, mfe += mff)
348 for (fb = e_f(e, domaine.w2j(j)), n = 0, fac = fs(f) * fs(fb) / ve(e) * domaine.w2c(j); n < N; n++)
349 mff(n) = fac * nu_ef(domaine.w2j(j), n);
351 for (n = 0; ch.
fcl()(f, 0) < 6 && n < N; n++)
352 resu(ne_tot + f, n) -= mff(n) * inco(ne_tot + fb, n);
354 for (n = 0; f < domaine.premiere_face_int() && n < N; n++)
355 flux_bords_(f, n) -= mff(n) * inco(ne_tot + fb, n);
356 for (n = 0; n < N; n++)
357 resu(e, n) += mff(n) * inco(ne_tot + fb, n);
361 for (n = 0;
stab_ && ch.
fcl()(f, 0) < 4 && n < N; n++)
362 resu(ne_tot + f, n) -= std::max(
delta_f(f, n),
delta_f(fb, n)) * (inco(ne_tot + f, n) - inco(ne_tot + fb, n));
365 for (n = 0; ch.
fcl()(f, 0) < 6 && n < N; n++)
366 resu(ne_tot + f, n) += mfe(n) * inco(e, n);
367 for (n = 0; f < domaine.premiere_face_int() && n < N; n++)
372 if (ch.
fcl()(f, 0) > 0 && ch.
fcl()(f, 0) < 2 && f < domaine.nb_faces())
373 for (n = 0; n < N; n++)
375 * (inco(ch.
fcl()(f, 0) == 1 ? ne_tot + f : e, n) - ref_cast(
Echange_impose_base, cls[ch.
fcl()(f, 1)].valeur()).T_ext(ch.
fcl()(f, 2), n));
378 for (n = 0;
stab_ && ch.
fcl()(f, 0) < 4 && n < N; n++)
380 double corr = std::max(
delta_e(e, n),
delta_f(f, n)) * (inco(e, n) - inco(ne_tot + f, n));
381 resu(e, n) -= corr, resu(ne_tot + f, n) += corr;
384 for (n = 0; n < N; n++)
385 resu(e, n) -= mee(n) * inco(e, n);
393 if (ip > 3 || ip < -1)
394 Process::exit(
"Op_Diff_PolyMAC_CDO_Elem::contribuer_bloc : invalid bloc number! p must be in [-1, 3]");
398 const Conds_lim& cls = la_zcl_poly_->les_conditions_limites();
399 const IntTab& e_f = domaine.elem_faces();
400 const DoubleVect& fs = domaine.face_surfaces(), &ve = domaine.volumes();
401 int i, j, k, l, e, f, fb, ne_tot = domaine.nb_elem_tot(), n, N = inco.
line_size();
406 for (i = 0; i < cls.size(); i++)
411 DoubleTrav nu_ef(e_f.
dimension(1), N), mff(N), mfe(N), mee(N);
412 for (e = 0; e < ne_tot; e++)
414 int n_f = domaine.m2d(e + 1) - domaine.m2d(e);
415 for (
remplir_nu_ef(e, nu_ef), mee = 0, i = 0; i < n_f; i++, mee += mfe)
417 for (f = e_f(e, i), j = domaine.w2i(domaine.m2d(e) + i), mfe = 0; j < domaine.w2i(domaine.m2d(e) + i + 1); j++, mfe += mff)
419 for (fb = e_f(e, domaine.w2j(j)), n = 0, fac = fs(f) * fs(fb) / ve(e) * domaine.w2c(j); n < N; n++)
420 mff(n) = fac * nu_ef(domaine.w2j(j), n);
421 for (n = 0; f < domaine.nb_faces() && ((ch.
fcl()(f, 0) < 6 && ch.
fcl()(fb, 0) < 6) || ip > -1) && n < N; n++)
424 matrice(N * (ne_tot + f) + n, N * (ne_tot + fb) + n) += mff(n);
426 matrice(N * f + n, N * fb + n) += mff(n);
428 for (n = 0; e < domaine.nb_elem() && ch.
fcl()(fb, 0) < 6 && n < N; n++)
431 matrice(N * e + n, N * (ne_tot + fb) + n) -= mff(n);
433 matrice(N * e + n, N * fb + n) -= mff(n);
437 for (n = 0;
stab_ && ch.
fcl()(f, 0) < 4 && f < domaine.nb_faces() && n < N; n++)
438 for (k = 0, fac = std::max(
delta_f(f, n),
delta_f(fb, n)); k < 2; k++)
441 matrice(N * (ne_tot + f) + n, N * (ne_tot + (k ? fb : f)) + n) += (k ? -1 : 1) * fac;
443 matrice(N * f + n, N * (k ? fb : f) + n) += (k ? -1 : 1) * fac;
446 for (n = 0; f < domaine.nb_faces() && (ch.
fcl()(f, 0) < 6 || ip > -1) && n < N; n++)
449 matrice(N * (ne_tot + f) + n, N * e + n) -= mfe(n);
451 matrice(N * f + n, N * e + n) -= mfe(n);
455 if (ch.
fcl()(f, 0) == 1 && f < domaine.nb_faces())
456 for (n = 0; n < N; n++)
459 matrice(N * (ne_tot + f) + n, N * (ch.
fcl()(f, 0) == 1 ? ne_tot + f : e) + n) += fs(f) * ref_cast(
Echange_impose_base, cls[ch.
fcl()(f, 1)].valeur()).h_imp(ch.
fcl()(f, 2), n);
461 Process::exit(
"Echange_impose_base et diffusion explicite : pas bon!");
463 else if (ch.
fcl()(f, 0) == 3 && f < domaine.nb_faces())
466 for (j = ch.
fcl()(f, 2), n = 0; n < N; n++)
469 matrice(N * (ne_tot + f) + n, N * (ne_tot + f) + n) += cl.
coeff(j, 0, n);
471 Process::exit(
"Echange_impose_base et diffusion explicite : pas bon!");
474 for (n = 0; n < N; n++)
477 matrice(N * (ne_tot + f) + n, N * (ne_tot + f) + n) += std::max(
delta_f(f, n), cl.
delta(j, k, n));
479 Process::exit(
"Echange_impose_base et diffusion explicite : pas bon!");
484 for (n = 0;
stab_ && ch.
fcl()(f, 0) < 4 && n < N; n++)
487 for (k = 0; k < 2; k++)
488 for (l = 0; (k ? (f < domaine.nb_faces()) : (e < domaine.nb_elem())) && l < 2; l++)
491 matrice(N * (k ? ne_tot + f : e) + n, N * (l ? ne_tot + f : e) + n) += (k == l ? 1 : -1) * corr;
493 Process::exit(
"Echange_impose_base et diffusion explicite : pas bon!");
497 for (n = 0; e < domaine.nb_elem() && n < N; n++)
498 if (ip == -1 || (ip == 0))
499 matrice(N * e + n, N * e + n) += mee(n);
507 const int ne_tot = domaine.
nb_elem_tot(), nf_tot = domaine.nb_faces_tot();
524 if (!polymac_flica5)
return;
528 DoubleTab_parts inco_parts(inco);
529 DoubleTab_parts sm_parts(sm);
533 if (FF.nb_lignes() == 0)
551 FE.ajouter_multvect(inco_parts[0], sm_parts[1]);
553 if (FF.is_diagonal())
555 const int n = FF.nb_lignes();
556 for (
int i = 0; i < n; i++)
557 for (
auto k = FF.get_tab1()(i) - 1; k < FF.get_tab1()(i + 1) - 1; k++)
558 inco_parts[1][i] = sm_parts[1][i] / FF.get_coeff()(k);
559 inco_parts[1].echange_espace_virtuel();
572 statistics().end_count(STD_COUNTERS::system_solver,0,0);
573 Nom solv(
"Petsc Cholesky { quiet }");
574 Cerr <<
"Echec du solveur dans Op_Diff_PolyMAC_CDO_Elem..." << finl;
575 Cerr <<
"On change pour un solveur plus robuste (mais plus lent): " << solv << finl;
578 solveur.nommer(
"Op_Diff_PolyMAC_CDO_Elem solver");
class Champ_Fonc_base Base class of fields that are functions of a calculated quantity
const IntTab & fcl() const
DoubleTab & valeurs() override
Returns the array of field values at the current time.
virtual Frontiere_dis_base & frontiere_dis()
Returns the discretized boundary to which the boundary conditions apply.
class Conds_lim This class represents a vector of boundary conditions.
int elem_faces(int i, int j) const
Returns the index of the i-th face of element num_elem; the face numbering convention is.
An input stream whose source is a character string.
Echange_impose_base: This boundary condition is used only for the energy equation.
Class defining operators and methods for all reading operation in an input flow (file,...
virtual const RefObjU & get_modele(Type_modele type) const
virtual const Champ_Inc_base & inconnue() const =0
int num_face(const int) const
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
int nb_colonnes() const override
Return local number of columns (=size on the current proc).
int nb_lignes() const override
Return local number of lines (=size on the current proc).
Base class for scalar turbulence models coupled to a Navier-Stokes convection-diffusion equation.
const Champ_Fonc_base & conductivite_turbulente() const
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
class Nom: a character string for naming TRUST objects.
virtual int find(const char *const n) const
const Nom & que_suis_je() const
Returns the string identifying the class.
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
void dimensionner_bloc(Matrice_Morse &mat, const int p) const
void contribuer_bloc(const DoubleTab &inco, Matrice_Morse &matrice, const int i) const
DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const override
void contribuer_termes_croises(const DoubleTab &inco, const Probleme_base &autre_pb, const DoubleTab &autre_inco, Matrice_Morse &matrice) const override
void update_delta() const
void dimensionner(Matrice_Morse &mat) const override
DOES NOTHING - to override in derived classes.
void update_auxiliary_variables()
void ajouter_termes_croises(const DoubleTab &inco, const Probleme_base &autre_pb, const DoubleTab &autre_inco, DoubleTab &resu) const override
void update_delta_int() const
void completer() override
Associates the operator with the domaine_dis, the domaine_Cl_dis, and the unknown of its equation.
void contribuer_a_avec(const DoubleTab &, Matrice_Morse &) const override
DOES NOTHING - to override in derived classes.
Op_Diff_PolyMAC_CDO_Elem()
void dimensionner_termes_croises(Matrice_Morse &, const Probleme_base &autre_pb, int nl, int nc) const override
void remplir_nu_ef(int e, DoubleTab &nu_ef) const
void update_nu() const override
void completer() override
Associates the operator with the domaine_dis, the domaine_Cl_dis, and the unknown of its equation.
void associer_diffusivite_turbulente(const Champ_Fonc_base &)
SolveurSys & set_solveur()
Entree & lire_solveur(Entree &)
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
class Probleme_base It is a Probleme_U that is not a coupling.
static int nproc()
Returns the number of processors in the current group. See Comm_Group::nproc() and PE_Groups::current...
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
int resoudre_systeme(const Matrice_Base &matrice, const DoubleVect &secmem, DoubleVect &solution)
Base class for output streams.
virtual void declare_support_masse_volumique(int ok)
The constructor of a derived class that uses the density field must call this function with the value...
_SIZE_ dimension_tot(int) const override
_SIZE_ dimension(int d) const
const Objet_U & valeur() const