16#include <Assembleur_P_VDF.h>
17#include <Domaine_Cl_VDF.h>
18#include <Domaine_VDF.h>
19#include <Periodique.h>
21#include <Neumann_sortie_libre.h>
22#include <Dirichlet_entree_fluide_leaves.h>
23#include <Dirichlet_paroi_fixe.h>
24#include <Dirichlet_paroi_defilante.h>
25#include <Matrice_Bloc.h>
26#include <Option_VDF.h>
27#include <Champ_Fonc_Face_VDF.h>
28#include <Matrice_Morse_Sym.h>
29#include <Milieu_base.h>
30#include <Matrix_tools.h>
31#include <Pb_Multiphase.h>
35Assembleur_P_VDF::Assembleur_P_VDF() : has_P_ref(0) { }
61 const int nb_faces_bord = le_dom_VDF->nb_faces_bord();
65 const Conds_lim& les_cl = le_dom_Cl_VDF->les_conditions_limites();
66 const int nb_cl = les_cl.size();
67 int nb_faces_periodiques = 0;
68 for (
int num_cl = 0; num_cl < nb_cl; num_cl++)
76 const int nb_faces_cl = frontiere.
nb_faces();
78 for (
int i = 0; i < nb_faces_cl; i++)
82 if (face_associee > i)
84 const int num_face_global = num_premiere_face + i;
85 faces[nb_faces_periodiques] = num_face_global;
86 nb_faces_periodiques++;
93 return nb_faces_periodiques;
109 const Domaine_VDF& domaine_vdf = le_dom_VDF.valeur();
110 const IntTab& face_voisins = domaine_vdf.
face_voisins();
121 const int nb_elem = domaine_vdf.
nb_elem();
123 ArrOfInt carre_nb_non_zero(nb_elem);
125 ArrOfInt rect_nb_non_zero(nb_elem);
127 carre_nb_non_zero = 1;
128 rect_nb_non_zero = 0;
129 int carre_nb_non_zero_tot = nb_elem;
130 int rect_nb_non_zero_tot = 0;
135 ArrOfInt liste_faces_perio;
139 for (i = 0; i < nb_faces_internes + nb_faces_periodiques; i++)
142 if (i < nb_faces_internes)
143 face = premiere_face_interne + i;
145 face = liste_faces_perio[i - nb_faces_internes];
147 int elem0 = face_voisins(face,0);
148 int elem1 = face_voisins(face,1);
159 carre_nb_non_zero[elem0] ++;
160 carre_nb_non_zero_tot ++;
164 rect_nb_non_zero[elem0] ++;
165 rect_nb_non_zero_tot ++;
171 la_matrice.typer(
"Matrice_Bloc");
174 matrice.
get_bloc(0,0).typer(
"Matrice_Morse_Sym");
175 matrice.
get_bloc(0,1).typer(
"Matrice_Morse");
179 carre.dimensionner(nb_elem, carre_nb_non_zero_tot);
180 rect.
dimensionner(nb_elem, nb_elem_tot - nb_elem, rect_nb_non_zero_tot);
186 auto& carre_tab1 = carre.get_set_tab1();
202 for (i = 0; i < nb_elem; i++)
204 carre_tab1[i] = indice;
205 indice += carre_nb_non_zero[i];
207 carre_tab1[i] = indice;
210 for (i = 0; i < nb_elem; i++)
212 rect_tab1[i] = indice;
213 indice += rect_nb_non_zero[i];
215 rect_tab1[i] = indice;
220 auto& carre_tab2 = carre.get_set_tab2();
227 for (i = 1; i <= nb_elem; i++)
228 carre_tab2[carre_tab1[i-1]-1] = i;
230 carre_nb_non_zero = 1;
231 rect_nb_non_zero = 0;
234 for (
int i_face = 0; i_face < nb_faces_internes + nb_faces_periodiques; i_face++)
238 const int face = (i_face < nb_faces_internes)
239 ? premiere_face_interne + i_face
240 : liste_faces_perio[i_face - nb_faces_internes];
242 int elem0 = face_voisins(face,0);
243 int elem1 = face_voisins(face,1);
253 const int ligne = elem0 + 1;
256 const int colonne = elem1 + 1;
257 const int n = carre_nb_non_zero[ligne-1]++;
258 const auto index = carre_tab1[ligne-1] + n;
259 carre_tab2[index - 1] = colonne;
263 const int colonne = elem1 - nb_elem + 1;
264 const int n = rect_nb_non_zero[ligne-1]++;
265 const auto index = rect_tab1[ligne-1] + n;
266 rect_tab2[index - 1] = colonne;
283 const Domaine_VDF& domaine_vdf = le_dom_VDF.valeur();
284 const IntTab& face_voisins = domaine_vdf.
face_voisins();
285 const DoubleVect& face_surfaces = domaine_vdf.
face_surfaces();
287 const DoubleVect& porosite_face = le_dom_Cl_VDF->equation().milieu().porosite_face();
290 const DoubleVect * valeurs_rho = 0;
294 valeurs_rho = & (rho_ptr->
valeurs());
303 const int nb_elem = domaine_vdf.
nb_elem();
304 ArrOfInt carre_nb_non_zero(nb_elem);
305 ArrOfInt rect_nb_non_zero(nb_elem);
306 carre_nb_non_zero = 1;
307 rect_nb_non_zero = 0;
309 auto& carre_tab1 = carre.get_set_tab1();
311 auto& carre_coeff = carre.get_set_coeff();
325 ArrOfInt liste_faces_perio;
329 for (
int i_face = 0; i_face < nb_faces_internes + nb_faces_periodiques; i_face++)
333 const int num_face = (i_face < nb_faces_internes)
334 ? premiere_face_interne + i_face
335 : liste_faces_perio[i_face - nb_faces_internes];
337 const double rho_face = (valeurs_rho) ? (*valeurs_rho)[num_face] : 1.;
339 const double surface = face_surfaces[num_face];
340 const double volume = volumes_entrelaces[num_face];
341 const double porosite = porosite_face[num_face];
342 const double coefficient = surface * surface * porosite / (volume * rho_face);
344 int elem0 = face_voisins(num_face,0);
345 int elem1 = face_voisins(num_face,1);
355 const int ligne = elem0 + 1;
357 const auto index_diag = carre_tab1[ligne-1];
358 carre_coeff[index_diag - 1] += coefficient;
363 const auto index_diag1 = carre_tab1[elem1];
365 const int n = carre_nb_non_zero[ligne-1]++;
366 const auto index = index_diag + n;
368 carre_coeff[index_diag1 - 1] += coefficient;
370 carre_coeff[index - 1] = - coefficient;
371 assert(carre.get_tab2()(index - 1) == elem1 + 1);
376 const int n = rect_nb_non_zero[ligne-1]++;
377 const auto index = rect_tab1[ligne-1] + n;
379 rect_coeff[index - 1] = - coefficient;
380 assert(rect.
get_tab2()(index - 1) == elem1 - nb_elem + 1);
386 const Conds_lim& les_cl = le_dom_Cl_VDF->les_conditions_limites();
387 const int nb_cl = les_cl.size();
388 for (
int num_cl = 0; num_cl < nb_cl; num_cl++)
397 const int nfin = ndeb + la_front_dis.
nb_faces();
398 if (nfin>ndeb && est_egal(face_surfaces[ndeb],0))
400 Cerr <<
"\nFirst face surface is smaller than PrecisionGeom = " <<
precision_geom << finl;
401 Cerr <<
"May be you have an error in the definition of the boundary conditions." << finl;
402 Cerr <<
"The axis of revolution for this 2D calculation is along Y." << finl;
403 Cerr <<
"So you must specify symmetry boundary condition (symetrie keyword) for the boundary " << la_front_dis.
le_nom() << finl;
415 carre.set_est_definie(1);
417 const int nfin = ndeb + la_front_dis.
nb_faces();
418 for (
int num_face = ndeb; num_face < nfin; num_face++)
421 const double rho_face = (valeurs_rho) ? (*valeurs_rho)[num_face] : 1.;
423 const double surface = face_surfaces[num_face];
426 const double volume = volumes_entrelaces[num_face];
427 const double porosite = porosite_face[num_face];
429 assert(coefficient > 0.);
431 const int elem0 = face_voisins(num_face, 0);
432 const int elem1 = face_voisins(num_face, 1);
433 assert(elem0 == -1 || elem1 == -1);
434 const int elem = elem0 + elem1 + 1;
436 assert(elem < nb_elem);
437 const auto index = carre_tab1[elem];
438 carre_coeff[index - 1] += coefficient;
452 for (
int i = 0; i < nb_elem; i++)
454 const auto index = carre_tab1[i];
455 const double coeff_diagonal = carre_coeff[index - 1];
456 if (coeff_diagonal == 0.)
459 carre_coeff[index - 1] = 1.;
483 for (
int indice_cl = 0; indice_cl < nb_cond_lim; indice_cl++)
510 else if (sub_type(
Symetrie, la_cl_base))
520 Cerr <<
"Erreur dans Assembleur_P_VDF::modifier_secmem\n la condition aux limites ";
521 Cerr << la_cl_base.
que_suis_je() <<
" n'est pas prise en charge." << finl;
566 const int nb_faces = frontiere_vf.
nb_faces();
568 for (
int i = 0; i < nb_faces; i++)
570 const int num_face = num_premiere_face + i;
573 const int elem = face_voisins(num_face, 0) + face_voisins(num_face, 1) + 1;
574 secmem[elem] += coef;
599 int nb_dim = tab_gpoint.
nb_dim();
601 const int nb_faces = frontiere_vf.
nb_faces();
603 for (
int i = 0; i < nb_faces; i++)
605 const int num_face = num_premiere_face + i;
606 const double surface = face_surfaces(num_face);
607 const int elem0 = face_voisins(num_face, 0);
608 const int elem1 = face_voisins(num_face, 1);
611 const double signe = (elem0 < 0) ? 1. : -1.;
613 const int elem = elem0 + elem1 + 1;
615 const double gpoint = nb_dim==1 ? tab_gpoint(ori) : tab_gpoint(ch_unif ? 0 : i, ori);
617 secmem[elem] += signe * surface * gpoint;
640 int nb_elem=le_dom_VDF->domaine().nb_elem();
641 for(
int n=0; n<nb_elem; n++)
642 if (pression[n] < press_0)
643 press_0 = pression[n];
644 press_0 =
mp_min(press_0);
646 pression.echange_espace_virtuel();
655 Cerr <<
"Assemblage de la matrice pression : Assembleur_P_VDF::assembler" << finl;
662 remplir(matrice,volumes_entrelaces, 0);
674 Cerr <<
"Assemblage de la matrice pression : Assembleur_P_VDF::assembler" << finl;
679 const Domaine_VDF& domaine_vdf = le_dom_VDF.valeur();
682 remplir(matrice,volumes_entrelaces, 0);
706 Cerr <<
"Assemblage de la matrice pression : ";
707 Cerr <<
"Assembleur_P_VDF::assembler_rho_variable" << finl;
711 const Domaine_VDF& domaine_vdf = le_dom_VDF.valeur();
714 remplir(matrice,volumes_entrelaces, & rho);
739 Cerr <<
"Assemblage de la matrice pression : ";
740 Cerr <<
"Assembleur_P_VDF::assembler_QC" << finl;
743 const Domaine_VDF& domaine_vdf = le_dom_VDF.valeur();
746 remplir(matrice,volumes_entrelaces, 0);
754 Cerr<<
"Pressure matrix will not be defined."<<finl;
760 Cerr<<
"la_matrice(0,0)"<<la_matrice(0,0)<<finl;
761 Cerr<<
"Pas de pression imposee --> P(0)=0"<<finl;
773 if (aux_only)
return;
775 Stencil stencil(0, 2);
777 for (e = 0; e < le_dom_VDF->nb_elem(); e++)
778 for (n = 0; n < N; n++) stencil.
append_line(e, N * e + n);
784 if (aux_only)
return;
787 const DoubleVect& ve = le_dom_VDF->volumes(), &pe = le_dom_Cl_VDF->equation().milieu().porosite_elem();
790 for (e = 0; e < le_dom_VDF->nb_elem(); e++)
791 for (secmem(e) = -pe(e) * ve(e), n = 0; n < N; n++) secmem(e) += pe(e) * ve(e) * alpha(e, n);
793 for (e = 0; e < le_dom_VDF->nb_elem(); e++)
794 for (n = 0; n < N; n++) mat(e, N * e + n) = -pe(e) * ve(e);
800 const DoubleVect& pe = le_dom_Cl_VDF->equation().milieu().porosite_elem(), &ve = le_dom_VDF->volumes();
801 DoubleTab norm(le_dom_VDF->nb_elem());
802 for (
int e = 0; e < le_dom_VDF->nb_elem(); e++) norm(e) = pe(e) * ve(e);
808 return le_dom_VDF.valeur();
813 return le_dom_Cl_VDF.valeur();
const Domaine_dis_base & domaine_dis_base() const override
int assembler_mat(Matrice &, const DoubleVect &, int incr_pression, int resoudre_en_u) override
void modifier_secmem_pression_imposee(const Neumann_sortie_libre &cond_lim, const Front_VF &frontiere_vf, DoubleTab &secmem)
Modification du second membre du solveur en pression pour une condition "Neumann_sortie_libre".
int modifier_secmem(DoubleTab &) override
Modification du second membre pour appliquer les conditions aux limites.
int liste_faces_periodiques(ArrOfInt &faces)
Remplit le tableau faces avec la liste des indices des faces periodiques dans le tableau faces_voisin...
int assembler_QC(const DoubleTab &, Matrice &) override
Assemble la matrice de pression pour un fluide quasi compressible.
int modifier_solution(DoubleTab &) override
void assembler_continuite(matrices_t matrices, DoubleTab &secmem, int aux_only=0) const override
void modifier_secmem_vitesse_imposee(const Entree_fluide_vitesse_imposee &cond_lim, const Front_VF &frontiere_vf, DoubleTab &secmem)
Modification du second membre du systeme en pression pour une condition aux limites de vitesse impose...
DoubleTab norme_continuite() const override
int construire(Matrice &la_matrice)
Determine les elements non nuls de la matrice et prepare le stockage.
int assembler_rho_variable(Matrice &, const Champ_Don_base &rho) override
Assemblage de la matrice de pression M telle que M*P = div(porosite/rho * grad (P)).
const Domaine_Cl_dis_base & domaine_Cl_dis_base() const override
void associer_domaine_dis_base(const Domaine_dis_base &) override
void dimensionner_continuite(matrices_t matrices, int aux_only=0) const override
int assembler(Matrice &) override
Assemblage de la matrice de pression M telle que M*P = div(porosite * grad (P)).
void associer_domaine_cl_dis_base(const Domaine_Cl_dis_base &) override
void completer(const Equation_base &) override
int remplir(Matrice &la_matrice, const DoubleVect &volumes_entrelaces, const Champ_Don_base *rho_ptr)
Calcul des coefficients de la matrice de pression avec un champ de rho.
ArrOfDouble les_coeff_pression
int get_resoudre_en_u() const
Renvoie la valeur du drapeau resoudre_en_u_ (0 ou 1) Renvoie -1 si le drapeau n'a pas ete initialise.
int set_resoudre_en_u(int flag)
Definit la valeur du drapeau resoudre_en_u__.
int get_resoudre_increment_pression() const
Renvoie la valeur du drapeau resoudre_increment_pression_ (0 ou 1) Renvoie -1 si le drapeau n'a pas e...
int set_resoudre_increment_pression(int flag)
Definit la valeur du drapeau resoudre_increment_pression_.
classe Champ_Don_base classe de base des Champs donnes (non calcules)
DoubleTab & valeurs() override
Surcharge Champ_base::valeurs() Renvoie le tableau des valeurs.
classe Champ_Fonc_Face_VDF
classe Champ_front_base Classe de base pour la hierarchie des champs aux frontieres.
virtual const DoubleTab & derivee_en_temps() const
virtual bool instationnaire() const
classe Cond_lim_base Classe de base pour la hierarchie des classes qui representent les differentes c...
virtual Frontiere_dis_base & frontiere_dis()
Renvoie la frontiere discretisee a laquelle les conditions aux limites s'appliquent.
Champ_front_base & champ_front()
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
classe Dirichlet_paroi_defilante Impose la vitesse de paroi dnas une equation de type Navier_Stokes.
classe Dirichlet_paroi_fixe Represente une paroi immobile dans une equation de type Navier_Stokes.
classe Domaine_Cl_dis_base Les objets Domaine_Cl_dis_base representent les conditions aux limites
int nb_cond_lim() const
Renvoie le nombre de conditions aux limites.
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
int orientation(int) const override
inline DoubleVect& Domaine_VDF::porosite_face() {
virtual const DoubleVect & face_surfaces() const
DoubleVect & volumes_entrelaces()
int nb_faces_internes() const
une face est interne ssi elle separe deux elements.
int premiere_face_int() const
une face est interne ssi elle separe deux elements.
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
int nb_faces_bord() const
renvoie le nombre de faces sur lesquelles sont appliquees les conditions limites :
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
classe Entree_fluide_vitesse_imposee Cas particulier de la classe Dirichlet_entree_fluide
Class defining operators and methods for all reading operation in an input flow (file,...
classe Equation_base Le role d'une equation est le calcul d'un ou plusieurs champs....
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
int num_premiere_face() const
const Nom & le_nom() const override
Renvoie le nom de la frontiere geometrique.
virtual void dimensionner(int N, int M)
virtual const Matrice & get_bloc(int i, int j) const
Classe Matrice_Morse_Sym Represente une matrice M (creuse) symetrique stockee au format Morse.
Classe Matrice_Morse Represente une matrice M (creuse), non necessairement carree.
const auto & get_tab2() const
void dimensionner(int n, _SIZE_ nnz)
Size the matrix with n lines and n columns and nnz zero-values coefficients.
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).
void compacte(int elim_coeff_nul=0)
Method to check/clean the Matrice_Morse matrix: -Suppress coefficient defined several times.
void set_est_definie(int)
int get_est_definie() const
Classe Matrice Classe generique de la hierarchie des matrices.
classe Neumann_sortie_libre Cette classe represente une frontiere ouverte sans vitesse imposee
virtual double flux_impose(int i) const
Renvoie la valeur du flux impose sur la i-eme composante du champ representant le flux a la frontiere...
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.
static double precision_geom
virtual const Nom & le_nom() const
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
static double coeff_P_neumann
classe Pb_Multiphase Cette classe represente un probleme de thermohydraulique multiphase de type "3*N...
const Equation_base & equation(int) const override
Renvoie l'equation d'hydraulique de type Navier_Stokes_std si i=0 Renvoie l'equation de la thermique ...
classe Periodique Cette classe represente une condition aux limites periodique.
int face_associee(int i) const
static double mp_min(double)
static double mp_max(double)
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Classe de base des flux de sortie.
classe Symetrie Sur les faces de symetrie on a les proprietes suivantes:
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
_SIZE_ dimension(int d) const
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")