16#include <Modele_turbulence_scal_base.h>
17#include <Echange_externe_impose.h>
18#include <Op_Dift_Stab_VEF_Face.h>
19#include <Scalaire_impose_paroi.h>
20#include <Neumann_sortie_libre.h>
21#include <Check_espace_virtuel.h>
22#include <Dirichlet_homogene.h>
23#include <Neumann_homogene.h>
24#include <Porosites_champ.h>
25#include <Neumann_paroi.h>
26#include <Periodique.h>
27#include <Champ_P1NC.h>
50double my_minimum(
double a,
double b,
double c)
52 if (a <= b)
return (a <= c) ? a : c;
53 else if (b <= c)
return b;
57double my_maximum(
double a,
double b,
double c)
59 if (a >= b)
return (a >= c) ? a : c;
60 else if (b >= c)
return b;
64double my_minimum(
double a,
double b)
66 return (a <= b) ? a : b;
69double my_maximum(
double a,
double b)
71 return (a >= b) ? a : b;
78 Motcle accouverte =
"{", accfermee =
"}", motlu;
83 les_mots[2] =
"nu_transp";
84 les_mots[3] =
"nut_transp";
85 les_mots[4] =
"standard";
86 les_mots[5] =
"new_jacobian";
90 if (motlu != accouverte)
91 Process::exit(
"Error in Op_Dift_Stab_VEF_Face::readOn(). Option keywords must be preceded by an open brace { !");
94 while (motlu != accfermee)
96 int rang = les_mots.search(motlu);
109 is >> nut_transp_lu_;
118 Cerr <<
"Error in Op_Dift_Stab_VEF_Face::readOn(). Word " << motlu <<
" is unknown !" << finl;
119 Cerr <<
"Known keywords are : " << les_mots << finl;
127 if (motlu != accfermee)
129 Cerr <<
"Error in Op_Dift_Stab_VEF_Face::readOn(). Final known keyword is the closing brace sign } !" << finl;
140inline double aij_extradiag__(
const Op_Dift_Stab_VEF_Face& z_class,
const int elem,
const int facei,
const int facej,
const int dim,
const int dim2,
const double nu_elem)
143 const IntTab& face_voisins = domaine_VEF.
face_voisins();
144 const DoubleTab& face_normales = domaine_VEF.
face_normales();
145 const DoubleVect& volumes = domaine_VEF.
volumes();
147 double volume = 0., signei = 1., signej = 1., aij = 0.;
153 volume = 1. / volumes(elem);
156 if (face_voisins(facei, 0) != elem) signei = -1.;
157 if (face_voisins(facej, 0) != elem) signej = -1.;
159 aij = face_normales(facei, dim2) * face_normales(facej, dim);
160 aij *= signei * signej;
166template <Type_Champ _TYPE_>
167void ajouter_operateur_centre__(
const Op_Dift_Stab_VEF_Face& z_class,
const DoubleTab& Aij_diag,
const DoubleTab& nu,
const DoubleTab& inconnue, DoubleTab& resu)
169 constexpr bool is_VECT = (_TYPE_ == Type_Champ::VECTORIEL);
172 const IntTab& elem_faces = domaine_VEF.
elem_faces();
174 double nu_elem = 0., aij = 0.;
176 for (
int elem = 0; elem < nb_elem_tot; elem++)
178 if (is_VECT) nu_elem = nu(elem);
180 for (
int facei_loc = 0; facei_loc < nb_faces_elem; facei_loc++)
182 const int facei = elem_faces(elem, facei_loc);
185 for (
int facej_loc = facei_loc + 1; facej_loc < nb_faces_elem; facej_loc++)
187 const int facej = elem_faces(elem, facej_loc);
189 if (!is_VECT) aij = Aij_diag(elem, facei_loc, facej_loc);
191 for (
int nc = 0; nc < nb_comp; nc++)
193 if (is_VECT) aij = Aij_diag(elem, facei_loc, facej_loc, nc);
195 const double delta_ij = aij * (inconnue(facej, nc) - inconnue(facei, nc));
196 resu(facei, nc) += delta_ij;
197 resu(facej, nc) -= delta_ij;
203 for (
int facej_loc = 0; facej_loc < nb_faces_elem; facej_loc++)
204 if (facej_loc != facei_loc)
206 const int facej = elem_faces(elem, facej_loc);
208 for (
int nc = 0; nc < nb_comp; nc++)
209 for (
int nc2 = nc + 1; nc2 < nb_comp; nc2++)
211 aij = aij_extradiag__(z_class, elem, facei, facej, nc, nc2, nu_elem);
213 double delta_ij = aij * (inconnue(facej, nc2) - inconnue(facei, nc2));
214 resu(facei, nc) += delta_ij;
216 delta_ij = aij * (inconnue(facej, nc) - inconnue(facei, nc));
217 resu(facej, nc2) -= delta_ij;
224template <Type_Champ _TYPE_>
225void calculer_coefficients__(
const Op_Dift_Stab_VEF_Face& z_class,
const DoubleTab& nu,
const DoubleTab& nu2 , DoubleTab& Aij)
227 constexpr bool is_VECT = (_TYPE_ == Type_Champ::VECTORIEL);
231 const DoubleTab& face_normales = domaine_VEF.
face_normales();
232 const DoubleVect& volumes = domaine_VEF.
volumes();
237 assert(Aij.
dimension(1) == nb_faces_elem);
238 assert(Aij.
dimension(2) == nb_faces_elem);
243 assert(Aij.
nb_dim() == 4);
247 assert(Aij.
nb_dim() == 3);
249 double nu2_elem = 0.;
251 for (
int elem = 0; elem < nb_elem_tot; elem++)
253 double volume = 1. / volumes(elem);
255 double nu_elem = nu(elem);
260 nu2_elem = nu2(elem);
264 for (
int facei_loc = 0; facei_loc < nb_faces_elem; facei_loc++)
266 const int facei = elem_faces(elem, facei_loc);
269 if (face_voisins(facei, 0) != elem) signei = -1;
271 for (
int facej_loc = facei_loc + 1; facej_loc < nb_faces_elem; facej_loc++)
273 const int facej = elem_faces(elem, facej_loc);
276 if (face_voisins(facej, 0) != elem) signej = -1;
281 psc += face_normales(facei, dim) * face_normales(facej, dim);
283 psc *= signei * signej;
288 Aij(elem, facei_loc, facej_loc) = psc;
289 Aij(elem, facej_loc, facei_loc) = psc;
293 for (
int dim = 0; dim < nb_comp; dim++)
295 Aij(elem, facei_loc, facej_loc, dim) = psc;
296 Aij(elem, facej_loc, facei_loc, dim) = psc;
300 for (
int dim = 0; dim < nb_comp; dim++)
302 psc = face_normales(facei, dim) * face_normales(facej, dim);
303 psc *= signei * signej;
306 Aij(elem, facei_loc, facej_loc, dim) += psc;
307 Aij(elem, facej_loc, facei_loc, dim) += psc;
319void Op_Dift_Stab_VEF_Face::ajouter_diffusion(
const DoubleTab& Aij,
const DoubleTab& inconnueTab, DoubleTab& resuTab,
const bool is_VECT)
const
322 const IntTab& elem_faces = domaine_VEF.
elem_faces();
324 const DoubleVect& inconnue = inconnueTab;
325 DoubleVect& resu = resuTab;
326 int elem = 0, facei_loc = 0, facei = 0, facej_loc = 0, facej = 0, dim = 0;
327 double inc_i = 0., inc_j = 0., delta_ij = 0., dij = 0.;
329 for (elem = 0; elem < nb_elem_tot; elem++)
330 for (facei_loc = 0; facei_loc < nb_faces_elem; facei_loc++)
332 facei = elem_faces(elem, facei_loc);
333 for (facej_loc = facei_loc + 1; facej_loc < nb_faces_elem; facej_loc++)
335 facej = elem_faces(elem, facej_loc);
337 for (dim = 0; dim < nb_comp; dim++)
339 const double aij = Aij(elem, facei_loc, facej_loc, dim);
344 inc_i = inconnue[facei * nb_comp + dim];
345 inc_j = inconnue[facej * nb_comp + dim];
346 delta_ij = dij * (inc_j - inc_i);
348 resu[facei * nb_comp + dim] += delta_ij;
349 resu[facej * nb_comp + dim] -= delta_ij;
354 const double aij = Aij(elem, facei_loc, facej_loc);
358 for (dim = 0; dim < nb_comp; dim++)
360 inc_i = inconnue[facei * nb_comp + dim];
361 inc_j = inconnue[facej * nb_comp + dim];
362 delta_ij = dij * (inc_j - inc_i);
364 resu[facei * nb_comp + dim] += delta_ij;
365 resu[facej * nb_comp + dim] -= delta_ij;
373void Op_Dift_Stab_VEF_Face::ajouter_antidiffusion(
const DoubleTab& Aij,
const DoubleTab& inconnueTab, DoubleTab& resuTab,
const bool is_VECT)
const
376 const DoubleTab& xv = domaine_VEF.
xv();
377 const IntTab& elem_faces = domaine_VEF.
elem_faces();
381 const DoubleVect& inconnue = inconnueTab;
382 DoubleVect& resu = resuTab;
386 int elem = 0, facei_loc = 0, facei = 0, facej_loc = 0, facej = 0, dim = 0, dim2 = 0;
387 double inc_i = 0., inc_j = 0., delta_ij = 0., delta_imax = 0., delta_imin = 0.;
388 double delta_jmax = 0., delta_jmin = 0., sij = 0., muij = 0., muji = 0.;
390 bool ok_facei =
false, ok_facej =
false;
392 DoubleTab Minima(nb_faces_tot), Maxima(nb_faces_tot);
394 for (dim = 0; dim < nb_comp; dim++)
396 calculer_min_max(inconnueTab, dim, Minima,
false );
397 calculer_min_max(inconnueTab, dim, Maxima,
true );
399 for (elem = 0; elem < nb_elem_tot; elem++)
400 for (facei_loc = 0; facei_loc < nb_faces_elem; facei_loc++)
402 facei = elem_faces(elem, facei_loc);
403 ok_facei = is_dirichlet_faces_(facei);
404 inc_i = inconnue[facei * nb_comp + dim];
406 delta_imin = Minima(facei) - inc_i;
407 delta_imax = Maxima(facei) - inc_i;
408 assert(delta_imax >= 0.);
409 assert(delta_imin <= 0.);
411 for (facej_loc = facei_loc + 1; facej_loc < nb_faces_elem; facej_loc++)
413 const double aij = is_VECT ? Aij(elem, facei_loc, facej_loc, dim) : Aij(elem, facei_loc, facej_loc);
417 facej = elem_faces(elem, facej_loc);
418 ok_facej = is_dirichlet_faces_(facej);
419 inc_j = inconnue[facej * nb_comp + dim];
422 rij(dim2) = xv(facej, dim2) - xv(facei, dim2);
427 delta_ij = inc_i - inc_j;
428 delta_jmin = Minima(facej) - inc_j;
429 delta_jmax = Maxima(facej) - inc_j;
430 assert(delta_jmax >= 0.);
431 assert(delta_jmin <= 0.);
433 muij = calculer_gradients(facei, rij);
434 muji = calculer_gradients(facej, rji);
442 if (!ok_facei && !ok_facej)
443 sij = my_minimum(muij, delta_ij, muji);
444 if (!ok_facei && ok_facej)
445 sij = my_minimum(muij, delta_ij);
446 if (ok_facei && !ok_facej)
447 sij = my_minimum(delta_ij, muji);
449 else if (delta_ij < 0.)
454 if (!ok_facei && !ok_facej)
455 sij = my_maximum(muij, delta_ij, muji);
456 if (!ok_facei && ok_facej)
457 sij = my_maximum(muij, delta_ij);
458 if (ok_facei && !ok_facej)
459 sij = my_maximum(delta_ij, muji);
462 resu[facei * nb_comp + dim] -= aij * sij;
463 resu[facej * nb_comp + dim] += aij * sij;
471double Op_Dift_Stab_VEF_Face::calculer_gradients(
int facei,
const DoubleTab& rij)
const
475 const DoubleTab& face_normales = domaine_VEF.
face_normales();
476 const DoubleVect& volumes = domaine_VEF.
volumes();
478 double volume = 0., signek = 0., psc = 0., mu_ij = 0.;
479 int elem = 0, elem_loc = 0, facei_loc = 0, facek_loc = 0, facek = 0, dim = 0;
481 for (elem_loc = 0; elem_loc < 2; elem_loc++)
483 facei_loc = get_num_fac_loc(facei, elem_loc);
484 elem = face_voisins(facei, elem_loc);
488 volume += volumes(elem);
490 for (facek_loc = 0; facek_loc < nb_faces_elem; facek_loc++)
491 if (facek_loc != facei_loc)
493 facek = elem_faces(elem, facek_loc);
496 if (face_voisins(facek, 0) != elem)
501 psc += face_normales(facek, dim) * rij(dim);
516void Op_Dift_Stab_VEF_Face::calculer_min_max(
const DoubleTab& inconnueTab,
int& dim, DoubleTab& minima_ou_maxima,
const bool is_max)
const
521 const IntTab& elem_faces = domaine_VEF.
elem_faces();
522 int elem = 0, facei_loc = 0, facei = 0, facej_loc = 0, facej = 0;
523 double inc_i = 0., inc_j = 0.;
524 const DoubleVect& inconnue = inconnueTab;
526 assert(minima_ou_maxima.
nb_dim() == 1);
527 assert(minima_ou_maxima.
dimension(0) == nb_faces_tot);
528 assert(dim < nb_comp);
530 for (facei = 0; facei < nb_faces_tot; facei++)
531 minima_ou_maxima(facei) = inconnue[facei * nb_comp + dim];
533 for (elem = 0; elem < nb_elem_tot; elem++)
534 for (facei_loc = 0; facei_loc < nb_faces_elem; facei_loc++)
536 facei = elem_faces(elem, facei_loc);
538 inc_i = inconnue[facei * nb_comp + dim];
539 double& min_ou_maxi = minima_ou_maxima(facei);
541 for (facej_loc = facei_loc + 1; facej_loc < nb_faces_elem; facej_loc++)
543 facej = elem_faces(elem, facej_loc);
545 inc_j = inconnue[facej * nb_comp + dim];
546 double& min_ou_maxj = minima_ou_maxima(facej);
550 if (inc_j > min_ou_maxi)
552 if (inc_i > min_ou_maxj)
557 if (inc_j < min_ou_maxi)
559 if (inc_i < min_ou_maxj)
567 const int nb_bords = les_cl.size();
568 int num1 = 0, num2 = 0, n_bord = 0, ind_face = 0;
570 for (n_bord = 0; n_bord < nb_bords; n_bord++)
573 const Front_VF& le_bord = ref_cast(Front_VF, la_cl->frontiere_dis());
578 if (sub_type(Periodique, la_cl.valeur()))
580 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
582 for (ind_face = num1; ind_face < num2; ind_face++)
589 double& min_ou_maxi = minima_ou_maxima(facei);
590 double& min_ou_maxj = minima_ou_maxima(facej);
593 if (min_ou_maxi > min_ou_maxj)
594 min_ou_maxj = min_ou_maxi;
595 if (min_ou_maxj > min_ou_maxi)
596 min_ou_maxi = min_ou_maxj;
600 if (min_ou_maxi < min_ou_maxj)
601 min_ou_maxj = min_ou_maxi;
602 if (min_ou_maxj < min_ou_maxi)
603 min_ou_maxi = min_ou_maxj;
619 const int nb_bord = les_cl.size(), nb_faces_tot = domaine_VEF.
nb_faces_tot();
622 is_dirichlet_faces_.resize(nb_faces_tot);
623 is_dirichlet_faces_ = 0;
625 for (
int n_bord = 0; n_bord < nb_bord; n_bord++)
629 int nb_faces_bord_tot = le_bord.
nb_faces_tot(), face = -1;
632 for (ind_face = 0; ind_face < nb_faces_bord_tot; ind_face++)
635 is_dirichlet_faces_(face) = 1;
640void Op_Dift_Stab_VEF_Face::ajouter_cas_scalaire(
const DoubleTab& inconnue,
const DoubleTab& nu,
const DoubleTab& nu_turb_m, DoubleTab& resu2)
const
644 DoubleTab Aij(nb_elem_tot, nb_faces_elem, nb_faces_elem), nu_total(nu);
645 nu_total += nu_turb_m;
647 calculer_coefficients__<Type_Champ::SCALAIRE>(*
this, nu_total, nu_total , Aij);
648 ajouter_operateur_centre__<Type_Champ::SCALAIRE>(*
this, Aij, nu, inconnue, resu2);
652 ajouter_diffusion(Aij, inconnue, resu2,
false );
653 ajouter_antidiffusion(Aij, inconnue, resu2,
false );
657void Op_Dift_Stab_VEF_Face::ajouter_cas_vectoriel(
const DoubleTab& inconnue,
const DoubleTab& nu,
const DoubleTab& nu_turb_m, DoubleTab& resu2)
const
662 DoubleTab Aij_diag(nb_elem_tot, nb_faces_elem, nb_faces_elem, nb_comp);
664 DoubleTab nu_total(nu);
665 if (nu_lu_ == 0) nu_total = 0.;
666 if (nut_lu_) nu_total += nu_turb_m;
668 DoubleTab nu_transp_total(nu);
669 if (nu_transp_lu_ == 0) nu_transp_total = 0.;
670 if (nut_transp_lu_) nu_transp_total += nu_turb_m;
672 calculer_coefficients__<Type_Champ::VECTORIEL>(*
this, nu_total, nu_transp_total, Aij_diag);
673 ajouter_operateur_centre__<Type_Champ::VECTORIEL>(*
this, Aij_diag, nu_transp_total, inconnue, resu2);
677 ajouter_diffusion(Aij_diag, inconnue, resu2,
true );
678 ajouter_antidiffusion(Aij_diag, inconnue, resu2,
true );
689 flux_bords_.resize(le_dom_vef->nb_faces_bord(), nb_comp);
692 DoubleTab resu2(resu);
696 DoubleTab nu, nu_turb_m, tab_inconnue_;
701 modif_par_porosite_si_flag(
nu_, nu, !marq, porosite_elem);
702 modif_par_porosite_si_flag(nu_turb, nu_turb_m, !marq, porosite_elem);
703 const DoubleTab& inconnue = modif_par_porosite_si_flag(inconnue_org, tab_inconnue_, marq, porosite_face);
705 assert_espace_virtuel_vect(nu);
706 assert_espace_virtuel_vect(inconnue);
707 assert_espace_virtuel_vect(nu_turb_m);
710 Debog::verifier(
"Op_Dift_Stab_VEF_Face::ajouter inconnue_org", inconnue_org);
713 if (
equation().inconnue().nature_du_champ() != vectoriel)
714 ajouter_cas_scalaire(inconnue, nu, nu_turb_m, resu2);
716 ajouter_cas_vectoriel(inconnue, nu, nu_turb_m, resu2);
731 DoubleTab nu, nu_turb;
737 modif_par_porosite_si_flag(
nu_, nu, !marq, porosite_elem);
738 modif_par_porosite_si_flag(nu_turb_, nu_turb, !marq, porosite_elem);
740 DoubleVect porosite_eventuelle(
equation().milieu().porosite_face());
741 if (!marq) porosite_eventuelle = 1;
743 if (
equation().inconnue().nature_du_champ() == vectoriel)
DoubleTab & valeurs() override
Overrides Champ_base::valeurs() Returns the array of values.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
class Cond_lim Generic class used to represent any class
class Conds_lim This class represents a vector of boundary conditions.
static void verifier(const char *const msg, double)
Classe Dirichlet_homogene This class is the base class of the hierarchy of homogeneous Dirichlet-type...
Dirichlet This class is the base class of the hierarchy of Dirichlet-type boundary conditions.
int nb_faces_elem(int=0) const
Returns the number of faces of type i of the geometric elements that make up the domain.
const Cond_lim & les_conditions_limites(int) const
Returns the i-th boundary condition.
int nb_faces_tot() const
Returns the total number of faces.
virtual double face_normales(int face, int comp) const
double xv(int num_face, int k) const
double volumes(int i) const
const IntTab & get_num_fac_loc() const
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.
int face_voisins(int num_face, int i) const
Returns the neighbouring element of num_face in direction i.
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
virtual const Milieu_base & milieu() const =0
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,.
DoubleVect & porosite_elem()
DoubleVect & porosite_face()
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
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.
const Champ_Fonc_base & diffusivite_turbulente() const
int phi_psi_diffuse(const Equation_base &eq) const
Determine whether to compute div(phi nu grad Psi) or div(nu grad Phi psi).
virtual void remplir_nu(DoubleTab &) const
const Domaine_VEF & domaine_vef() const
const Domaine_Cl_VEF & domaine_cl_vef() const
void contribuer_a_avec(const DoubleTab &, Matrice_Morse &) const override
DOES NOTHING - to override in derived classes.
DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const override
void completer() override
Associates the operator with the domaine_dis, the domaine_Cl_dis, and the unknown of its equation.
void modifie_pour_cl_gen(const DoubleTab &, DoubleTab &, DoubleTab &) const
void ajouter_contribution_bord_gen(const DoubleTab &, Matrice_Morse &, const DoubleTab &, const DoubleTab &, const DoubleVect &) const
void ajouter_contribution_interne_gen(const DoubleTab &inco, Matrice_Morse &mat, const DoubleTab &nu, const DoubleTab &nu_turb, const DoubleVect &porosite_eventuelle) const
void completer() override
Associates the operator with the domaine_dis, the domaine_Cl_dis, and the unknown of its equation.
void modifier_matrice_pour_periodique_apres_contribuer(Matrice_Morse &matrice, const Equation_base &) const
Sums the 2 rows of the associated periodic faces, allowing computations in the code without needing t...
void modifier_matrice_pour_periodique_avant_contribuer(Matrice_Morse &matrice, const Equation_base &) const
Divides the coefficients on the periodic face rows by 2 in preparation for applying modifier_matrice_...
void modifier_flux(const Operateur_base &) const
int face_associee(int i) const
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Base class for output streams.
_SIZE_ dimension(int d) const