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) { }
60 const int nb_faces_bord = le_dom_VDF->nb_faces_bord();
64 const Conds_lim& les_cl = le_dom_Cl_VDF->les_conditions_limites();
65 const int nb_cl = les_cl.size();
66 int nb_faces_periodiques = 0;
67 for (
int num_cl = 0; num_cl < nb_cl; num_cl++)
75 const int nb_faces_cl = frontiere.
nb_faces();
77 for (
int i = 0; i < nb_faces_cl; i++)
81 if (face_associee > i)
83 const int num_face_global = num_premiere_face + i;
84 faces[nb_faces_periodiques] = num_face_global;
85 nb_faces_periodiques++;
92 return nb_faces_periodiques;
108 const Domaine_VDF& domaine_vdf = le_dom_VDF.valeur();
109 const IntTab& face_voisins = domaine_vdf.
face_voisins();
120 const int nb_elem = domaine_vdf.
nb_elem();
122 ArrOfInt carre_nb_non_zero(nb_elem);
124 ArrOfInt rect_nb_non_zero(nb_elem);
126 carre_nb_non_zero = 1;
127 rect_nb_non_zero = 0;
128 int carre_nb_non_zero_tot = nb_elem;
129 int rect_nb_non_zero_tot = 0;
134 ArrOfInt liste_faces_perio;
138 for (i = 0; i < nb_faces_internes + nb_faces_periodiques; i++)
141 if (i < nb_faces_internes)
142 face = premiere_face_interne + i;
144 face = liste_faces_perio[i - nb_faces_internes];
146 int elem0 = face_voisins(face,0);
147 int elem1 = face_voisins(face,1);
158 carre_nb_non_zero[elem0] ++;
159 carre_nb_non_zero_tot ++;
163 rect_nb_non_zero[elem0] ++;
164 rect_nb_non_zero_tot ++;
170 la_matrice.typer(
"Matrice_Bloc");
173 matrice.
get_bloc(0,0).typer(
"Matrice_Morse_Sym");
174 matrice.
get_bloc(0,1).typer(
"Matrice_Morse");
178 carre.dimensionner(nb_elem, carre_nb_non_zero_tot);
179 rect.
dimensionner(nb_elem, nb_elem_tot - nb_elem, rect_nb_non_zero_tot);
185 auto& carre_tab1 = carre.get_set_tab1();
201 for (i = 0; i < nb_elem; i++)
203 carre_tab1[i] = indice;
204 indice += carre_nb_non_zero[i];
206 carre_tab1[i] = indice;
209 for (i = 0; i < nb_elem; i++)
211 rect_tab1[i] = indice;
212 indice += rect_nb_non_zero[i];
214 rect_tab1[i] = indice;
218 auto& carre_tab2 = carre.get_set_tab2();
225 for (i = 1; i <= nb_elem; i++)
226 carre_tab2[carre_tab1[i-1]-1] = i;
228 carre_nb_non_zero = 1;
229 rect_nb_non_zero = 0;
232 for (
int i_face = 0; i_face < nb_faces_internes + nb_faces_periodiques; i_face++)
236 const int face = (i_face < nb_faces_internes)
237 ? premiere_face_interne + i_face
238 : liste_faces_perio[i_face - nb_faces_internes];
240 int elem0 = face_voisins(face,0);
241 int elem1 = face_voisins(face,1);
251 const int ligne = elem0 + 1;
254 const int colonne = elem1 + 1;
255 const int n = carre_nb_non_zero[ligne-1]++;
256 const auto index = carre_tab1[ligne-1] + n;
257 carre_tab2[index - 1] = colonne;
261 const int colonne = elem1 - nb_elem + 1;
262 const int n = rect_nb_non_zero[ligne-1]++;
263 const auto index = rect_tab1[ligne-1] + n;
264 rect_tab2[index - 1] = colonne;
281 const Domaine_VDF& domaine_vdf = le_dom_VDF.valeur();
282 const IntTab& face_voisins = domaine_vdf.
face_voisins();
283 const DoubleVect& face_surfaces = domaine_vdf.
face_surfaces();
285 const DoubleVect& porosite_face = le_dom_Cl_VDF->equation().milieu().porosite_face();
288 const DoubleVect * valeurs_rho = 0;
292 valeurs_rho = & (rho_ptr->
valeurs());
301 const int nb_elem = domaine_vdf.
nb_elem();
302 ArrOfInt carre_nb_non_zero(nb_elem);
303 ArrOfInt rect_nb_non_zero(nb_elem);
304 carre_nb_non_zero = 1;
305 rect_nb_non_zero = 0;
307 auto& carre_tab1 = carre.get_set_tab1();
309 auto& carre_coeff = carre.get_set_coeff();
323 ArrOfInt liste_faces_perio;
327 for (
int i_face = 0; i_face < nb_faces_internes + nb_faces_periodiques; i_face++)
331 const int num_face = (i_face < nb_faces_internes)
332 ? premiere_face_interne + i_face
333 : liste_faces_perio[i_face - nb_faces_internes];
335 const double rho_face = (valeurs_rho) ? (*valeurs_rho)[num_face] : 1.;
337 const double surface = face_surfaces[num_face];
338 const double volume = volumes_entrelaces[num_face];
339 const double porosite = porosite_face[num_face];
340 const double coefficient = surface * surface * porosite / (volume * rho_face);
342 int elem0 = face_voisins(num_face,0);
343 int elem1 = face_voisins(num_face,1);
353 const int ligne = elem0 + 1;
355 const auto index_diag = carre_tab1[ligne-1];
356 carre_coeff[index_diag - 1] += coefficient;
361 const auto index_diag1 = carre_tab1[elem1];
363 const int n = carre_nb_non_zero[ligne-1]++;
364 const auto index = index_diag + n;
366 carre_coeff[index_diag1 - 1] += coefficient;
368 carre_coeff[index - 1] = - coefficient;
369 assert(carre.get_tab2()(index - 1) == elem1 + 1);
374 const int n = rect_nb_non_zero[ligne-1]++;
375 const auto index = rect_tab1[ligne-1] + n;
377 rect_coeff[index - 1] = - coefficient;
378 assert(rect.
get_tab2()(index - 1) == elem1 - nb_elem + 1);
384 const Conds_lim& les_cl = le_dom_Cl_VDF->les_conditions_limites();
385 const int nb_cl = les_cl.size();
386 for (
int num_cl = 0; num_cl < nb_cl; num_cl++)
395 const int nfin = ndeb + la_front_dis.
nb_faces();
396 if (nfin>ndeb && est_egal(face_surfaces[ndeb],0))
398 Cerr <<
"\nFirst face surface is smaller than PrecisionGeom = " <<
precision_geom << finl;
399 Cerr <<
"May be you have an error in the definition of the boundary conditions." << finl;
400 Cerr <<
"The axis of revolution for this 2D calculation is along Y." << finl;
401 Cerr <<
"So you must specify symmetry boundary condition (symetrie keyword) for the boundary " << la_front_dis.
le_nom() << finl;
413 carre.set_est_definie(1);
415 const int nfin = ndeb + la_front_dis.
nb_faces();
416 for (
int num_face = ndeb; num_face < nfin; num_face++)
419 const double rho_face = (valeurs_rho) ? (*valeurs_rho)[num_face] : 1.;
421 const double surface = face_surfaces[num_face];
424 const double volume = volumes_entrelaces[num_face];
425 const double porosite = porosite_face[num_face];
427 assert(coefficient > 0.);
429 const int elem0 = face_voisins(num_face, 0);
430 const int elem1 = face_voisins(num_face, 1);
431 assert(elem0 == -1 || elem1 == -1);
432 const int elem = elem0 + elem1 + 1;
434 assert(elem < nb_elem);
435 const auto index = carre_tab1[elem];
436 carre_coeff[index - 1] += coefficient;
450 for (
int i = 0; i < nb_elem; i++)
452 const auto index = carre_tab1[i];
453 const double coeff_diagonal = carre_coeff[index - 1];
454 if (coeff_diagonal == 0.)
457 carre_coeff[index - 1] = 1.;
481 for (
int indice_cl = 0; indice_cl < nb_cond_lim; indice_cl++)
508 else if (sub_type(
Symetrie, la_cl_base))
518 Cerr <<
"Error in Assembleur_P_VDF::modifier_secmem\n the boundary condition ";
519 Cerr << la_cl_base.
que_suis_je() <<
" is not supported." << finl;
564 const int nb_faces = frontiere_vf.
nb_faces();
566 for (
int i = 0; i < nb_faces; i++)
568 const int num_face = num_premiere_face + i;
571 const int elem = face_voisins(num_face, 0) + face_voisins(num_face, 1) + 1;
572 secmem[elem] += coef;
597 int nb_dim = tab_gpoint.
nb_dim();
599 const int nb_faces = frontiere_vf.
nb_faces();
601 for (
int i = 0; i < nb_faces; i++)
603 const int num_face = num_premiere_face + i;
604 const double surface = face_surfaces(num_face);
605 const int elem0 = face_voisins(num_face, 0);
606 const int elem1 = face_voisins(num_face, 1);
609 const double signe = (elem0 < 0) ? 1. : -1.;
611 const int elem = elem0 + elem1 + 1;
613 const double gpoint = nb_dim==1 ? tab_gpoint(ori) : tab_gpoint(ch_unif ? 0 : i, ori);
615 secmem[elem] += signe * surface * gpoint;
638 int nb_elem=le_dom_VDF->domaine().nb_elem();
639 for(
int n=0; n<nb_elem; n++)
640 if (pression[n] < press_0)
641 press_0 = pression[n];
642 press_0 =
mp_min(press_0);
644 pression.echange_espace_virtuel();
653 Cerr <<
"Assembling the pressure matrix: Assembleur_P_VDF::assembler" << finl;
660 remplir(matrice,volumes_entrelaces, 0);
672 Cerr <<
"Assembling the pressure matrix: Assembleur_P_VDF::assembler" << finl;
677 const Domaine_VDF& domaine_vdf = le_dom_VDF.valeur();
680 remplir(matrice,volumes_entrelaces, 0);
704 Cerr <<
"Assembling the pressure matrix: ";
705 Cerr <<
"Assembleur_P_VDF::assembler_rho_variable" << finl;
709 const Domaine_VDF& domaine_vdf = le_dom_VDF.valeur();
712 remplir(matrice,volumes_entrelaces, & rho);
736 Cerr <<
"Assembling the pressure matrix: ";
737 Cerr <<
"Assembleur_P_VDF::assembler_QC" << finl;
740 const Domaine_VDF& domaine_vdf = le_dom_VDF.valeur();
743 remplir(matrice,volumes_entrelaces, 0);
751 Cerr<<
"Pressure matrix will not be defined."<<finl;
757 Cerr<<
"la_matrice(0,0)"<<la_matrice(0,0)<<finl;
758 Cerr<<
"No imposed pressure --> P(0)=0"<<finl;
770 if (aux_only)
return;
772 Stencil stencil(0, 2);
774 for (e = 0; e < le_dom_VDF->nb_elem(); e++)
775 for (n = 0; n < N; n++) stencil.
append_line(e, N * e + n);
781 if (aux_only)
return;
784 const DoubleVect& ve = le_dom_VDF->volumes(), &pe = le_dom_Cl_VDF->equation().milieu().porosite_elem();
787 for (e = 0; e < le_dom_VDF->nb_elem(); e++)
788 for (secmem(e) = -pe(e) * ve(e), n = 0; n < N; n++) secmem(e) += pe(e) * ve(e) * alpha(e, n);
790 for (e = 0; e < le_dom_VDF->nb_elem(); e++)
791 for (n = 0; n < N; n++) mat(e, N * e + n) = -pe(e) * ve(e);
797 const DoubleVect& pe = le_dom_Cl_VDF->equation().milieu().porosite_elem(), &ve = le_dom_VDF->volumes();
798 DoubleTab norm(le_dom_VDF->nb_elem());
799 for (
int e = 0; e < le_dom_VDF->nb_elem(); e++) norm(e) = pe(e) * ve(e);
805 return le_dom_VDF.valeur();
810 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)
Modifies the right-hand side of the pressure solver for a "Neumann_sortie_libre" condition.
int modifier_secmem(DoubleTab &) override
Modifies the right-hand side to apply boundary conditions.
int liste_faces_periodiques(ArrOfInt &faces)
Fills the array faces with the list of indices of the periodic faces in the face_voisins array.
int assembler_QC(const DoubleTab &, Matrice &) override
Assembles the pressure matrix for a quasi-compressible fluid.
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)
Modifies the right-hand side of the pressure system for an imposed velocity boundary condition.
DoubleTab norme_continuite() const override
int construire(Matrice &la_matrice)
Determines the nonzero entries of the matrix and prepares the storage.
int assembler_rho_variable(Matrice &, const Champ_Don_base &rho) override
Assembles the pressure matrix M such that M*P = div(porosity/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
Assembles the pressure matrix M such that M*P = div(porosity * 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)
Computes the coefficients of the pressure matrix with a rho field.
ArrOfDouble les_coeff_pression
int get_resoudre_en_u() const
Returns the value of the resoudre_en_u_ flag (0 or 1) Returns -1 if the flag has not been initialized...
int set_resoudre_en_u(int flag)
Sets the value of the resoudre_en_u__ flag.
int get_resoudre_increment_pression() const
Returns the value of the resoudre_increment_pression_ flag (0 or 1) Returns -1 if the flag has not be...
int set_resoudre_increment_pression(int flag)
Sets the value of the resoudre_increment_pression_ flag.
class Champ_Don_base base class of Given Fields (not calculated)
DoubleTab & valeurs() override
Overrides Champ_base::valeurs() Returns the array of values.
class Champ_Fonc_Face_VDF
class Champ_front_base Base class for the hierarchy of boundary fields.
virtual const DoubleTab & derivee_en_temps() const
virtual bool instationnaire() const
class Cond_lim_base Base class for the hierarchy of classes that represent the different boundary con...
virtual Frontiere_dis_base & frontiere_dis()
Returns the discretized boundary to which the boundary conditions apply.
Champ_front_base & champ_front()
class Conds_lim This class represents a vector of boundary conditions.
Dirichlet_paroi_defilante Imposes the wall velocity in an equation of type Navier_Stokes.
Dirichlet_paroi_fixe Represents a fixed wall in a Navier-Stokes type equation.
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
int nb_cond_lim() const
Returns the number of boundary conditions.
const Cond_lim & les_conditions_limites(int) const
Returns the i-th boundary condition.
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
A face is internal if and only if it separates two elements.
int premiere_face_int() const
A face is internal if and only if it separates two elements.
int face_voisins(int num_face, int i) const
Returns the neighbouring element of num_face in direction i.
int nb_faces_bord() const
Returns the number of faces on which boundary conditions are applied:
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
Entree_fluide_vitesse_imposee Special case of the class Dirichlet_entree_fluide.
Class defining operators and methods for all reading operation in an input flow (file,...
class Equation_base The role of an equation is the calculation of one or more fields....
Probleme_base & probleme()
Returns the problem associated with the equation.
int num_premiere_face() const
const Nom & le_nom() const override
Returns the name of the geometric boundary.
virtual void dimensionner(int N, int M)
virtual const Matrice & get_bloc(int i, int j) const
Matrice_Morse_Sym class - Represents a sparse symmetric matrix M stored in Morse format.
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
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
Matrice class - Generic class in the matrix hierarchy.
Neumann_sortie_libre This class represents an open boundary without imposed velocity.
virtual double flux_impose(int i) const
Returns the value of the imposed flux on the i-th component of the field representing the flux at the...
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.
static double precision_geom
virtual const Nom & le_nom() const
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
static double coeff_P_neumann
Multiphase thermohydraulics problem of type "3*N equations":
const Equation_base & equation(int) const override
Returns the equation at index i (const version).
class Periodique This class represents a periodic boundary condition.
int face_associee(int i) const
static double mp_min(double)
static double mp_max(double)
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
static int je_suis_maitre()
Returns 1 if on the master processor of the current group (i.e. me() == 0), 0 otherwise.
Base class for output streams.
Symetrie On symmetry faces, the following properties hold:
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")