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");
classe Champ_Fonc_base Classe de base des champs qui sont fonction d'une grandeur calculee
const IntTab & fcl() const
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
virtual Frontiere_dis_base & frontiere_dis()
Renvoie la frontiere discretisee a laquelle les conditions aux limites s'appliquent.
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
int elem_faces(int i, int j) const
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Une entree dont la source est une chaine de caracteres.
classe Echange_impose_base: Cette condition limite sert uniquement pour l'equation d'energie.
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
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).
int nb_lignes() const override
Return local number of lines (=size on the current proc).
Classe Modele_turbulence_scal_base Cette classe represente un modele de turbulence pour une equation ...
const Champ_Fonc_base & conductivite_turbulente() const
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
class Nom Une chaine de caractere pour nommer les objets de TRUST
virtual int find(const char *const n) const
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
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
Associe l'operateur au domaine_dis, le domaine_Cl_dis, et a l'inconnue de son 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
Associe l'operateur au domaine_dis, le domaine_Cl_dis, et a l'inconnue de son equation.
void associer_diffusivite_turbulente(const Champ_Fonc_base &)
SolveurSys & set_solveur()
Entree & lire_solveur(Entree &)
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
classe Probleme_base C'est un Probleme_U qui n'est pas un couplage.
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
int resoudre_systeme(const Matrice_Base &matrice, const DoubleVect &secmem, DoubleVect &solution)
Classe de base des flux de sortie.
virtual void declare_support_masse_volumique(int ok)
Le constructeur d'une classe derivee qui se sert de la masse volumique doit appeler cette fonction av...
_SIZE_ dimension_tot(int) const override
_SIZE_ dimension(int d) const
const Objet_U & valeur() const