TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Op_Grad_VDF_Face.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Neumann_sortie_libre.h>
17#include <Check_espace_virtuel.h>
18#include <Dirichlet_homogene.h>
19#include <Schema_Temps_base.h>
20#include <Navier_Stokes_std.h>
21#include <Op_Grad_VDF_Face.h>
22#include <communications.h>
23#include <Champ_Face_VDF.h>
24#include <Pb_Multiphase.h>
25#include <EcrFicPartage.h>
26#include <Champ_P0_VDF.h>
27#include <Matrix_tools.h>
28#include <Domaine_Cl_VDF.h>
29#include <Array_tools.h>
30#include <Option_VDF.h>
31#include <TRUSTTrav.h>
32#include <Periodique.h>
33#include <Dirichlet.h>
34#include <Symetrie.h>
35#include <Perf_counters.h>
36
37Implemente_instanciable(Op_Grad_VDF_Face,"Op_Grad_VDF_Face",Op_Grad_VDF_Face_base);
38
39Sortie& Op_Grad_VDF_Face::printOn(Sortie& s) const { return s << que_suis_je(); }
40Entree& Op_Grad_VDF_Face::readOn(Entree& s) { return s; }
41
43{
44 const Domaine_VDF& zvdf = le_dom_vdf.valeur();
45 if (flux_bords_.size_array()==0) flux_bords_.resize(zvdf.nb_faces_bord(),dimension);
46 flux_bords_ = 0.;
47 const Domaine_Cl_VDF& zclvdf = la_zcl_vdf.valeur();
48 const Navier_Stokes_std& eqn_hydr = ref_cast(Navier_Stokes_std,equation());
49 const Champ_P0_VDF& la_pression_P0 = ref_cast(Champ_P0_VDF,eqn_hydr.pression_pa());
50 const DoubleTab& pression_P0 = la_pression_P0.valeurs();
51 const DoubleVect& face_surfaces = zvdf.face_surfaces();
52 int nb_bord = zvdf.nb_front_Cl();
53 for (int n_bord=0; n_bord<nb_bord; n_bord++)
54 {
55 const Cond_lim& la_cl = zclvdf.les_conditions_limites(n_bord);
56 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
57 int ndeb = le_bord.num_premiere_face();
58 int nfin = ndeb + le_bord.nb_faces();
59 for (int face=ndeb; face<nfin; face++)
60 {
61 int elem0 = face_voisins(face,0);
62 int ori = orientation(face);
63 double n0 = face_surfaces(face)*porosite_surf(face);
64 if (elem0 != -1) flux_bords_(face,ori) = (pression_P0(elem0))*n0 ;
65 else
66 {
67 int elem1 = face_voisins(face,1);
68 flux_bords_(face,ori) = -(pression_P0(elem1))*n0 ;
69 }
70 } // fin for face
71 } // fin for n_bord
72}
73
75{
76 const int impr_mom=le_dom_vdf->domaine().moments_a_imprimer();
77 const int impr_sum=(le_dom_vdf->domaine().bords_a_imprimer_sum().est_vide() ? 0:1);
78 const int impr_bord=(le_dom_vdf->domaine().bords_a_imprimer().est_vide() ? 0:1);
80 const Domaine_VDF& zvdf = le_dom_vdf.valeur();
81 const Domaine_Cl_VDF& zclvdf = la_zcl_vdf.valeur();
82 int face, ori;
83 DoubleTab xgr;
84 if (impr_mom) xgr = zvdf.calculer_xgr();
85 // flux_bords contains the sum of flux on each boundary:
86 DoubleTrav tab_flux_bords(3,zvdf.nb_front_Cl(),3);
87 tab_flux_bords=0.;
88 /* flux_bord(k) -> flux_bords2(0,num_cl,k)
89 flux_bord_perio1(k) -> flux_bords2(1,num_cl,k)
90 flux_bord_perio2(k) -> flux_bords2(2,num_cl,k)
91 moment(k) -> flux_bords2(3,num_cl,k) */
92 int nb_bord = zvdf.nb_front_Cl();
93 for (int n_bord=0; n_bord<nb_bord; n_bord++)
94 {
95 const Cond_lim& la_cl = zclvdf.les_conditions_limites(n_bord);
96 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
97 int impr_boundary = (zvdf.domaine().bords_a_imprimer_sum().contient(le_bord.le_nom()) ? 1 : 0);
98 int ndeb = le_bord.num_premiere_face();
99 int nfin = ndeb + le_bord.nb_faces();
100
101 for (face=ndeb; face<nfin; face++)
102 {
103 ori = orientation(face);
104 tab_flux_bords(0, n_bord, ori) += flux_bords_(face,ori) ;
105
106 if (dimension == 2)
107 {
108 if (impr_mom)
109 tab_flux_bords(2, n_bord, 2) +=flux_bords_(face,1)*xgr(face,0)-flux_bords_(face,0)*xgr(face,1);
110 if (impr_boundary)
111 {
112 tab_flux_bords(1, n_bord, 0) += flux_bords_(face,0) ;
113 tab_flux_bords(1, n_bord, 1) += flux_bords_(face,1) ;
114 }
115 }
116 else if (dimension == 3)
117 {
118 if (impr_mom)
119 {
120 tab_flux_bords(2, n_bord, 0) +=flux_bords_(face,2)*xgr(face,1)-flux_bords_(face,1)*xgr(face,2);
121 tab_flux_bords(2, n_bord, 1) +=flux_bords_(face,0)*xgr(face,2)-flux_bords_(face,2)*xgr(face,0);
122 tab_flux_bords(2, n_bord, 2) +=flux_bords_(face,1)*xgr(face,0)-flux_bords_(face,0)*xgr(face,1);
123 }
124 if (impr_boundary)
125 {
126 tab_flux_bords(1, n_bord, 0) += flux_bords_(face,0) ;
127 tab_flux_bords(1, n_bord, 1) += flux_bords_(face,1) ;
128 tab_flux_bords(1, n_bord, 2) += flux_bords_(face,2) ;
129 }
130 }
131 } // fin for face
132 } // fin for n_bord
133
134 // Sum on all process:
135 mp_sum_for_each_item(tab_flux_bords);
136
137 // Write the boundary fluxes:
138 if (je_suis_maitre())
139 {
141 ouvrir_fichier(Flux_grad_moment,"moment",impr_mom);
142 ouvrir_fichier(Flux_grad_sum,"sum",impr_sum);
143 Flux_grad.add_col(sch.temps_courant());
144 if (impr_mom) Flux_grad_moment.add_col(sch.temps_courant());
145 if (impr_sum) Flux_grad_sum.add_col(sch.temps_courant());
146 for (int n_bord=0; n_bord<nb_bord; n_bord++)
147 {
148 if (dimension == 2)
149 {
150 Flux_grad.add_col(tab_flux_bords(0, n_bord, 0));
151 Flux_grad.add_col(tab_flux_bords(0, n_bord, 1));
152 if (impr_sum)
153 {
154 Flux_grad_sum.add_col(tab_flux_bords(1, n_bord, 0));
155 Flux_grad_sum.add_col(tab_flux_bords(1, n_bord, 1));
156 }
157 if (impr_mom) Flux_grad_moment.add_col(tab_flux_bords(2, n_bord, 2));
158 }
159
160 if (dimension == 3)
161 {
162 Flux_grad.add_col(tab_flux_bords(0, n_bord, 0));
163 Flux_grad.add_col(tab_flux_bords(0, n_bord, 1));
164 Flux_grad.add_col(tab_flux_bords(0, n_bord, 2));
165 if (impr_sum)
166 {
167 Flux_grad_sum.add_col(tab_flux_bords(1, n_bord, 0));
168 Flux_grad_sum.add_col(tab_flux_bords(1, n_bord, 1));
169 Flux_grad_sum.add_col(tab_flux_bords(1, n_bord, 2));
170 }
171 if (impr_mom)
172 {
173 Flux_grad_moment.add_col(tab_flux_bords(2, n_bord, 0));
174 Flux_grad_moment.add_col(tab_flux_bords(2, n_bord, 1));
175 Flux_grad_moment.add_col(tab_flux_bords(2, n_bord, 2));
176 }
177 }
178 }
179 Flux_grad << finl;
180 if (impr_sum) Flux_grad_sum << finl;
181 if (impr_mom) Flux_grad_moment << finl;
182 }
183
184 const LIST(Nom)& Liste_bords_a_imprimer = zvdf.domaine().bords_a_imprimer();
185 if (!Liste_bords_a_imprimer.est_vide())
186 {
187 EcrFicPartage Flux_grad_face;
188 ouvrir_fichier_partage(Flux_grad_face,"",impr_bord);
189 for (int n_bord=0; n_bord<nb_bord; n_bord++)
190 {
191 const Cond_lim& la_cl = zclvdf.les_conditions_limites(n_bord);
192 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
193 int ndeb = le_bord.num_premiere_face();
194 int nfin = ndeb + le_bord.nb_faces();
195 if (zvdf.domaine().bords_a_imprimer().contient(le_bord.le_nom()))
196 {
197 if (je_suis_maitre())
198 {
199 Flux_grad_face << "# Force par face sur " << le_bord.le_nom() << " au temps ";
200 sch.imprimer_temps_courant(Flux_grad_face);
201 Flux_grad_face << " : " << finl;
202 }
203 for (face=ndeb; face<nfin; face++)
204 {
205 Flux_grad_face << "# Face a x= " << zvdf.xv(face,0) << " y= " << zvdf.xv(face,1);
206 if (dimension==3) Flux_grad_face << " z= " << zvdf.xv(face,2);
207 Flux_grad_face << " : Fx= " << flux_bords_(face, 0) << " Fy= " << flux_bords_(face, 1);
208 if (dimension==3) Flux_grad_face << " Fz= " << flux_bords_(face, 2);
209 Flux_grad_face << finl;
210 }
211 Flux_grad_face.syncfile();
212 }
213 }
214 }
215 return 1;
216}
217
218void Op_Grad_VDF_Face::dimensionner_blocs(matrices_t matrices, const tabs_t& semi_impl) const
219{
220 if (!matrices.count("pression")) return; //rien a faire
221
222 const Domaine_VDF& zvdf = le_dom_vdf.valeur();
223 Stencil sten(0, 2);
224
225 const Champ_Face_VDF& ch = ref_cast(Champ_Face_VDF, equation().inconnue());
226 const DoubleTab& vit = ch.valeurs(), &press = le_champ_inco ? le_champ_inco->valeurs() : ref_cast(Navier_Stokes_std, equation()).pression().valeurs();
227 const int N = vit.line_size(), M = press.line_size();
228 Matrice_Morse *mat = matrices["pression"], mat2;
229
230 for (int f = 0; f < zvdf.nb_faces(); f++)
231 for (int i = 0, e; i < 2; i++)
232 if ((e = zvdf.face_voisins(f, i)) >= 0)
233 for (int n = 0, m = 0; n < N; n++, m += (M > 1))
234 sten.append_line(N * f + n, M * e + m); /* bloc (face, elem )*/
235
236 tableau_trier_retirer_doublons(sten);
237 Matrix_tools::allocate_morse_matrix(vit.size_totale(), press.size_totale(), sten, mat2);
238 mat->nb_colonnes() ? *mat += mat2 : *mat = mat2;
239}
240
241
242void Op_Grad_VDF_Face::ajouter_blocs(matrices_t matrices, DoubleTab& secmem, const tabs_t& semi_impl) const
243{
244 Matrice_Morse *mat = matrices.count("pression") ? matrices.at("pression") : nullptr;
245 const DoubleTab& inco = semi_impl.count("pression") ? semi_impl.at("pression") : (le_champ_inco ? le_champ_inco->valeurs() : ref_cast(Navier_Stokes_std, equation()).pression().valeurs()),
246 *alp = sub_type(Pb_Multiphase, equation().probleme()) ? &ref_cast(Pb_Multiphase, equation().probleme()).equation_masse().inconnue().passe() : nullptr;
247
248 assert_espace_virtuel_vect(inco);
249
250 const Domaine_VDF& zvdf = le_dom_vdf.valeur();
251 const Domaine_Cl_VDF& zclvdf = la_zcl_vdf.valeur();
252 const DoubleVect& face_surfaces = zvdf.face_surfaces(), &vf = zvdf.volumes_entrelaces();
253 const DoubleTab& vfd = zvdf.volumes_entrelaces_dir();
254 const int M = inco.line_size(), N = secmem.line_size();
255
256 // Boucle sur les bords pour traiter les conditions aux limites
257 for (int n_bord = 0; n_bord < zvdf.nb_front_Cl(); n_bord++)
258 {
259 const Cond_lim& la_cl = zclvdf.les_conditions_limites(n_bord);
260 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
261 const int ndeb = le_bord.num_premiere_face(), nfin = ndeb + le_bord.nb_faces();
262
263 if ( sub_type(Neumann_sortie_libre,la_cl.valeur()) )
264 {
265 const Neumann_sortie_libre& la_cl_typee = ref_cast(Neumann_sortie_libre, la_cl.valeur());
266 for (int num_face = ndeb; num_face < nfin; num_face++)
267 for (int n = 0, m = 0; n < N; n++, m += (M > 1))
268 {
269 const double P_imp = la_cl_typee.flux_impose(num_face-ndeb, m);
270
271 const int n0 = face_voisins(num_face,0);
272 if (n0 != -1)
273 {
274 const double coef = face_surfaces(num_face)*porosite_surf(num_face) * Option_VDF::coeff_P_neumann * (alp ? (*alp)(n0, n) : 1);
275 if(mat) (*mat)(N * num_face + n, M * n0 + m) -= coef;
276 secmem(num_face, n) -= coef * (P_imp - inco(n0, m));
277 }
278 else
279 {
280 const int n1 = face_voisins(num_face,1);
281 const double coef = face_surfaces(num_face)*porosite_surf(num_face) * Option_VDF::coeff_P_neumann * (alp ? (*alp)(n1, n) : 1.0);
282 if(mat) (*mat)(N * num_face + n, M * n1 + m) += coef;
283 secmem(num_face, n) -= coef * (inco(n1, m) - P_imp);
284 }
285 }
286 }
287 else if (sub_type(Periodique,la_cl.valeur())) // Correction periodicite
288 {
289 for (int f = ndeb; f < nfin; f++)
290 for (int n = 0, m = 0; n < N; n++, m += (M > 1))
291 {
292 const int n0 = face_voisins(f, 0), n1 = face_voisins(f, 1);
293 const double alpha_face = alp ? (vfd(f, 0) * (*alp)(n0, n) + vfd(f, 1) * (*alp)(n1, n)) / vf(f) : 1.0;
294 const double coef = face_surfaces(f) * porosite_surf(f) * alpha_face;
295 secmem(f, n) -= coef * (inco(n1, m) - inco(n0, m));
296 }
297 }
298 else if (sub_type(Symetrie,la_cl.valeur())) { /* Do nothing */ }
299 else if ( (sub_type(Dirichlet,la_cl.valeur())) || (sub_type(Dirichlet_homogene,la_cl.valeur())) ) { /* Do nothing */ }
300 }
301
302 // Boucle sur les faces internes
303 for (int f = zvdf.premiere_face_int(); f < zvdf.nb_faces(); f++)
304 for (int n = 0, m = 0; n < N; n++, m += (M > 1))
305 {
306 const int n0 = face_voisins(f, 0), n1 = face_voisins(f, 1);
307 // XXX : Elie Saikali : attention : on code alpha grad(P) et pas grad(alpha.P) !! Sinon on manque des termes ... (voir avec Antoine sinon)
308 const double alpha_face = alp ? (vfd(f, 0) * (*alp)(n0, n) + vfd(f, 1) * (*alp)(n1, n)) / vf(f) : 1.0;
309 const double coef = face_surfaces(f) * porosite_surf(f) * alpha_face;
310 if(mat)
311 {
312 (*mat)(N * f + n, M * n0 + m) -= coef;
313 (*mat)(N * f + n, M * n1 + m) += coef;
314 }
315 secmem(f, n) -= coef * (inco(n1, m) - inco(n0, m));
316 }
317
318 secmem.echange_espace_virtuel();
319}
class Champ_Face_VDF Cette classe sert a representer un champ vectoriel dont on ne calcule
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
classe Champ_P0_VDF Classe qui represente un champ discret P0 par element associe a un domaine discre...
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
Classe Dirichlet_homogene Cette classe est la classe de base de la hierarchie des conditions aux limi...
classe Dirichlet Cette classe est la classe de base de la hierarchie des conditions aux limites de ty...
Definition Dirichlet.h:31
class Domaine_Cl_VDF
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VDF
Definition Domaine_VDF.h:64
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
int nb_faces() const
renvoie le nombre global de faces.
Definition Domaine_VF.h:471
DoubleVect & volumes_entrelaces()
Definition Domaine_VF.h:99
const DoubleTab & volumes_entrelaces_dir() const
Definition Domaine_VF.h:102
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
DoubleTab calculer_xgr() const
calcul le tableau xgr pour le calcul des moments des forces aux bords :
int premiere_face_int() const
une face est interne ssi elle separe deux elements.
Definition Domaine_VF.h:463
int face_voisins(int num_face, int i) const
renvoie l'element voisin de numface dans la direction i.
Definition Domaine_VF.h:418
int nb_faces_bord() const
renvoie le nombre de faces sur lesquelles sont appliquees les conditions limites :
Definition Domaine_VF.h:513
int nb_front_Cl() const
const Domaine & domaine() const
Sortie & syncfile() override
Provoque l'ecriture sur disque des donnees accumulees sur les differents processeurs depuis le dernie...
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
Probleme_base & probleme()
Renvoie le probleme associe a l'equation.
class Front_VF
Definition Front_VF.h:36
int nb_faces() const
Definition Front_VF.h:53
int num_premiere_face() const
Definition Front_VF.h:63
const Nom & le_nom() const override
Renvoie le nom de la frontiere geometrique.
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).
static void allocate_morse_matrix(const int nb_lines, const int nb_columns, const Stencil &stencil, Matrice_Morse &matrix, const bool &attach_stencil_to_matrix=false)
const Equation_base & equation() const
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
classe Navier_Stokes_std Cette classe porte les termes de l'equation de la dynamique
Champ_Inc_base & pression_pa()
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...
Definition Neumann.cpp:35
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
class Op_Grad_VDF_Face Cette classe represente l'operateur de gradient
int impr(Sortie &os) const override
DOES NOTHING - to override in derived classes.
void dimensionner_blocs(matrices_t matrices, const tabs_t &semi_impl) const override
void ajouter_blocs(matrices_t matrices, DoubleTab &secmem, const tabs_t &semi_impl) const override
void calculer_flux_bords() const override
DoubleTab flux_bords_
void ouvrir_fichier_partage(EcrFicPartage &, const Nom &, const int flag=1) const
Ouverture/creation d'un fichier d'impression d'un operateur A surcharger dans les classes derivees.
void ouvrir_fichier(SFichier &os, const Nom &, const int flag=1) const
Ouverture/creation d'un fichier d'impression d'un operateur A surcharger dans les classes derivees.
static double coeff_P_neumann
Definition Option_VDF.h:31
classe Pb_Multiphase Cette classe represente un probleme de thermohydraulique multiphase de type "3*N...
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
const Schema_Temps_base & schema_temps() const
Renvoie le schema en temps associe au probleme.
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:193
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
class Schema_Temps_base
double temps_courant() const
Renvoie le temps courant.
void imprimer_temps_courant(SFichier &) const
Classe de base des flux de sortie.
Definition Sortie.h:52
classe Symetrie Sur les faces de symetrie on a les proprietes suivantes:
Definition Symetrie.h:37
void append_line(_TYPE_)
Definition TRUSTTab.tpp:213
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
int line_size() const
Definition TRUSTVect.tpp:67
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")