TrioCFD 1.9.9_beta
TrioCFD documentation
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 } // end for face
71 } // end 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 } // end for face
132 } // end 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; //nothing to do
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 // Loop over boundaries to process boundary conditions
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 // Loop over internal faces
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 : note: we code alpha grad(P) and not grad(alpha.P)!! Otherwise terms are missing ... (check with Antoine if needed)
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
DoubleTab & valeurs() override
Returns the array of field values at the current time.
class Champ_P0_VDF Class representing a P0 discrete field per element associated with a discretized d...
class Cond_lim Generic class used to represent any class
Definition Cond_lim.h:31
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.
Definition Dirichlet.h:31
class Domaine_Cl_VDF
const Cond_lim & les_conditions_limites(int) const
Returns the i-th boundary condition.
class Domaine_VDF
Definition Domaine_VDF.h:61
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
int nb_faces() const
Returns the total number of 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
Computes the xgr array for the computation of moments of forces at boundaries.
int premiere_face_int() const
A face is internal if and only if it separates two elements.
Definition Domaine_VF.h:463
int face_voisins(int num_face, int i) const
Returns the neighbouring element of num_face in direction i.
Definition Domaine_VF.h:418
int nb_faces_bord() const
Returns the number of faces on which boundary conditions are applied:
Definition Domaine_VF.h:512
int nb_front_Cl() const
const Domaine & domaine() const
Sortie & syncfile() override
Triggers writing to disk of the data accumulated on the different processors since the last call to s...
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
Probleme_base & probleme()
Returns the problem associated with the 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
Returns the name of the geometric boundary.
Matrice_Morse class - Represents a (sparse) matrix M, not necessarily square,.
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
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
Navier_Stokes_std This class carries the terms of the momentum equation.
Champ_Inc_base & pression_pa()
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...
Definition Neumann.cpp:35
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
static int dimension
Definition Objet_U.h:94
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
class Op_Grad_VDF_Face This class represents the gradient operator
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
Opening/creation of a shared file for printing an operator. To override in derived classes.
void ouvrir_fichier(SFichier &os, const Nom &, const int flag=1) const
Opening/creation of a file for printing an operator. To override in derived classes.
static double coeff_P_neumann
Definition Option_VDF.h:31
Multiphase thermohydraulics problem of type "3*N equations":
class Periodique This class represents a periodic boundary condition.
Definition Periodique.h:31
const Schema_Temps_base & schema_temps() const
Returns the time scheme associated with the problem.
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:194
static int je_suis_maitre()
Returns 1 if on the master processor of the current group (i.e. me() == 0), 0 otherwise.
Definition Process.cpp:82
class Schema_Temps_base
double temps_courant() const
Returns the current time.
void imprimer_temps_courant(SFichier &) const
Base class for output streams.
Definition Sortie.h:52
Symetrie On symmetry faces, the following properties hold:
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")