TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Conv_Muscl_old_VEF_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 <Op_Conv_Muscl_old_VEF_Face.h>
17#include <Champ_P1NC.h>
18#include <Neumann_sortie_libre.h>
19#include <Periodique.h>
20
21Implemente_instanciable_sans_constructeur(Op_Conv_Muscl_old_VEF_Face,"Op_Conv_Muscl_old_VEF_P1NC",Op_Conv_VEF_base);
22// XD convection_muscl_old convection_deriv muscl_old NO_BRACE Only for VEF discretization.
23
25{
26 return s << que_suis_je() ;
27}
28
30{
31 return s ;
32}
33
34//
35// Member functions of class Op_Conv_Muscl_old_VEF_Face
36//
37
38
39
40//////////////////////////////////////////////////////////////
41// MUSCL functions
42////////////////////////////////////////////////////////////////
43
44#define sgn(x) (x>0) ? 1:-1
45inline double minmod(double grad1, double grad2, double gradc)
46{
47 int s1=sgn(grad1);
48 int s2=sgn(grad2);
49 int sc=sgn(gradc);
50 double gradlim;
51 if ((s1==s2) && (s2==sc))
52 {
53 gradlim=std::min(std::fabs(grad1), std::fabs(grad2));
54 gradlim=std::min(std::fabs(gradlim), std::fabs(gradc));
55 return sc*gradlim;
56 }
57 else
58 return 0;
59}
60
61
62
63////////////////////////////////////////////////////////////////////
64//
65// Implementation of member functions
66//
67// of class Op_Conv_Muscl_old_VEF_Face
68//
69////////////////////////////////////////////////////////////////////
70
71
72DoubleTab& Op_Conv_Muscl_old_VEF_Face::ajouter(const DoubleTab& transporte,
73 DoubleTab& resu) const
74{
75 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
76 const Domaine_VEF& domaine_VEF = ref_cast(Domaine_VEF, le_dom_vef.valeur());
77 const Champ_Inc_base& la_vitesse=vitesse_.valeur();
78 const DoubleVect& porosite_face = equation().milieu().porosite_face();
79 const IntTab& elem_faces = domaine_VEF.elem_faces();
80 const DoubleTab& face_normales = domaine_VEF.face_normales();
81 const auto& facette_normales = domaine_VEF.facette_normales();
82 const Domaine& domaine = domaine_VEF.domaine();
83
84 const int nfa7 = domaine_VEF.type_elem().nb_facette();
85
86 const int nb_elem_tot = domaine_VEF.nb_elem_tot();
87 const IntVect& rang_elem_non_std = domaine_VEF.rang_elem_non_std();
88 const IntTab& face_voisins = domaine_VEF.face_voisins();
89 const DoubleVect& volumes = domaine_VEF.volumes();
90
91 const DoubleTab& normales_facettes_Cl = domaine_Cl_VEF.normales_facettes_Cl();
92 int premiere_face_int = domaine_VEF.premiere_face_int();
93 int nfac = domaine.nb_faces_elem();
94 int nsom = domaine.nb_som_elem();
95 int nb_som_facette = domaine.type_elem()->nb_som_face();
96 double inverse_nb_som_facette=1./nb_som_facette;
97 DoubleTab& vecteur_face_facette = ref_cast_non_const(Domaine_VEF,domaine_VEF).vecteur_face_facette();
98
99 // For convection treatment, we distinguish standard polyhedra
100 // which do not "see" boundary conditions, from non-standard
101 // polyhedra which have at least one boundary face.
102 // A standard polyhedron has n facets on which the convection
103 // scheme is applied.
104 // For a non-standard polyhedron with Dirichlet boundary conditions,
105 // some facets are carried by boundary faces.
106 // In short, for a polyhedron, convection treatment depends
107 // on the type (triangle, tetrahedron ...) and the number of Dirichlet faces.
108
109 const Elem_VEF_base& type_elemvef= domaine_VEF.type_elem();
110 int istetra=0;
111 Nom nom_elem=type_elemvef.que_suis_je();
112 if ((nom_elem=="Tetra_VEF")||(nom_elem=="Tri_VEF"))
113 istetra=1;
114
115 double psc;
116 int poly,face_adj,fa7,i,j,n_bord;
117 int num_face, rang ,itypcl;
118 int num10,num20,num_som;
119 int ncomp_ch_transporte;
120 if (transporte.nb_dim() == 1)
121 ncomp_ch_transporte=1;
122 else
123 ncomp_ch_transporte= transporte.dimension(1);
124
125 // Special treatment for periodic faces
126 int nb_faces_perio = 0;
127 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
128 {
129 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
130 if (sub_type(Periodique,la_cl.valeur()))
131 {
132 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
133 int num1 = le_bord.num_premiere_face();
134 int num2 = num1 + le_bord.nb_faces();
135 for (num_face=num1; num_face<num2; num_face++)
136 nb_faces_perio++;
137 }
138 }
139
140 DoubleTab tab;
141 if (ncomp_ch_transporte == 1)
142 tab.resize(nb_faces_perio);
143 else
144 tab.resize(nb_faces_perio,ncomp_ch_transporte);
145
146 nb_faces_perio=0;
147 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
148 {
149 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
150 if (sub_type(Periodique,la_cl.valeur()))
151 {
152 // const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
153 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
154 int num1 = le_bord.num_premiere_face();
155 int num2 = num1 + le_bord.nb_faces();
156 for (num_face=num1; num_face<num2; num_face++)
157 {
158 if (ncomp_ch_transporte == 1)
159 tab(nb_faces_perio) = resu(num_face);
160 else
161 for (int comp=0; comp<ncomp_ch_transporte; comp++)
162 tab(nb_faces_perio,comp) = resu(num_face,comp);
163 nb_faces_perio++;
164 }
165 }
166 }
167
168 int fac=0,elem1,elem2,comp;
169 int nb_faces_ = domaine_VEF.nb_faces();
170 IntVect face(nfac);
171
172 DoubleTab gradient_elem(nb_elem_tot,ncomp_ch_transporte,dimension);
173 // (du/dx du/dy dv/dx dv/dy) per element
174 DoubleTab gradient(0, ncomp_ch_transporte, dimension);
175 domaine_VEF.creer_tableau_faces(gradient);
176
177 // (du/dx du/dy dv/dx dv/dy) per face
178 // gradient_elem=0.; already done by the constructor
179
180 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
181
182 Champ_P1NC::calcul_gradient(transporte,gradient_elem,domaine_Cl_VEF);
183
184 // We have gradient_elem per element
185
186 ////////////////////////////////////////////////////////////////////////////////////////////////////////
187 // Minmod limitation
188 //
189 // Loop over faces
190 //
191 for (fac=0; fac< premiere_face_int; fac++)
192 {
193 for (comp=0; comp<ncomp_ch_transporte; comp++)
194 for (i=0; i<dimension; i++)
195 gradient(fac, comp, i)
196 /* upwind: */= 0;
197
198 } // end of the face loop
199
200 for (; fac<nb_faces_; fac++)
201 {
202 elem1=face_voisins(fac,0);
203 elem2=face_voisins(fac,1);
204 double vol1=volumes(elem1);
205 double vol2=volumes(elem2);
206 double inverse_voltot=1./(vol1+vol2);
207 for (comp=0; comp<ncomp_ch_transporte; comp++)
208 for (i=0; i<dimension; i++)
209 {
210 double grad1=gradient_elem(elem1, comp, i);
211 double grad2=gradient_elem(elem2, comp, i);
212 double gradc=(vol1*grad1 + vol2*grad2)*inverse_voltot;
213 gradient(fac, comp, i) = minmod(grad1, grad2, gradc);
214 }
215 } // end of the face loop
216
217 gradient.echange_espace_virtuel();
218
219
220 DoubleVect vs(dimension);
221 DoubleVect vc(dimension);
222 DoubleTab vsom(nsom,dimension);
223 DoubleVect cc(dimension);
224
225
226 const IntTab& KEL=type_elemvef.KEL();
227
228 // Reset to zero the array used for
229 // the computation of the stability time step
230 fluent_ = 0;
231
232 // Non-standard polyhedra are sorted in 2 groups in Domaine_VEF:
233 // - boundary and joint polyhedra
234 // - boundary and non-joint polyhedra
235 // Polyhedra are processed in the order they appear
236 // in the domain
237
238 // loop over polyhedra
239 const DoubleTab& vitesse_face=la_vitesse.valeurs();
240
241 for (poly=0; poly<nb_elem_tot; poly++)
242 {
243
244 rang = rang_elem_non_std(poly);
245 if (rang==-1)
246 itypcl=0;
247 else
248 itypcl=domaine_Cl_VEF.type_elem_Cl(rang);
249
250 // compute the face indices of the polyhedron
251 for (face_adj=0; face_adj<nfac; face_adj++)
252 face(face_adj)= elem_faces(poly,face_adj);
253
254 for (j=0; j<dimension; j++)
255 {
256 vs(j) = vitesse_face(face(0),j)*porosite_face(face(0));
257 for (i=1; i<nfac; i++)
258 vs(j)+= vitesse_face(face(i),j)*porosite_face(face(i));
259 }
260 // compute velocity at the vertices of the polyhedra
261 // Shape functions implemented in Champs_P1_impl or Champs_Q1_impl will be used
262 if (istetra==1)
263 {
264 for (i=0; i<nsom; i++)
265 for (j=0; j<dimension; j++)
266 vsom(i,j) = vs[j] - dimension*vitesse_face(face[i],j)*porosite_face(face[i]);
267 }
268 else
269 {
270 // to be valid with hexahedra (slower to compute...)
271 int ncomp;
272 for (j=0; j<nsom; j++)
273 {
274 num_som = domaine.sommet_elem(poly,j);
275 for (ncomp=0; ncomp<dimension; ncomp++)
276 vsom(j,ncomp) = la_vitesse.valeur_a_sommet_compo(num_som,poly,ncomp);
277 }
278 }
279
280
281 // compute vc (at the intersection of the 3 facets)
282 type_elemvef.calcul_vc(face,vc,vs,vsom,vitesse(),itypcl,porosite_face);
283
284 // Loop over facets of the non-standard polyhedron:
285 for (fa7=0; fa7<nfa7; fa7++)
286 {
287 num10 = face(KEL(0,fa7));
288 num20 = face(KEL(1,fa7));
289 // facet normals
290 if (rang==-1)
291 for (i=0; i<dimension; i++)
292 cc[i] = facette_normales(poly, fa7, i);
293 else
294 for (i=0; i<dimension; i++)
295 cc[i] = normales_facettes_Cl(rang,fa7,i);
296
297 // Apply the convection scheme to each vertex of the facet
298 for (i=0; i<nb_som_facette; i++)
299 {
300 psc =0;
301 if (i==nb_som_facette-1)
302 {
303 // Treat the vertex coincident with the centroid of the polyhedron
304 for (j=0; j<dimension; j++)
305 psc += vc[j]*cc[j];
306 }
307 else
308 {
309 // Treat the vertex or vertices that are also vertices of the polyhedron
310 for (j=0; j<dimension; j++)
311 psc+= vsom(KEL(i+2,fa7),j)*cc[j];
312 }
313 psc *= inverse_nb_som_facette;
314
315 // Compute convmuscl (previously in a function that was not always inlined by the compiler)
316 int comp2,amont,ii;
317 double flux;
318 if (psc >= 0)
319 {
320 amont = num10;
321 fluent_(num20) += psc;
322 }
323 else
324 {
325 amont = num20;
326 fluent_(num10) -= psc;
327 }
328 if (ncomp_ch_transporte == 1)
329 {
330 flux = transporte(amont);
331 if (psc >= 0)
332 for (ii=0; ii<dimension; ii++)
333 flux += gradient(amont,0,ii)*vecteur_face_facette(poly,fa7,ii,0);
334 else
335 for (ii=0; ii<dimension; ii++)
336 flux += gradient(amont,0,ii)*vecteur_face_facette(poly,fa7,ii,1);
337
338 flux*=psc;
339 resu(num10) -= flux;
340 resu(num20) += flux;
341 }
342 else
343 for (comp2=0; comp2<ncomp_ch_transporte; comp2++)
344 {
345 flux = transporte(amont,comp2);
346 if (psc >= 0)
347 for (ii=0; ii<dimension; ii++)
348 flux += gradient(amont,comp2,ii)*vecteur_face_facette(poly,fa7,ii,0);
349 else
350 for (ii=0; ii<dimension; ii++)
351 flux += gradient(amont,comp2,ii)*vecteur_face_facette(poly,fa7,ii,1);
352 flux *= psc;
353 resu(num10,comp2) -= flux;
354 resu(num20,comp2) += flux;
355 }
356
357 } // end of the loop over facet vertices
358 } // end of the loop over facets
359 } // end of the loop
360
361
362
363
364 int voisine;
365 nb_faces_perio = 0;
366 double diff1,diff2;
367
368 // Loop over the boundaries to process the boundary conditions
369 // a convection term is taken into account for
370 // Neumann_sortie_libre boundary conditions only
371
372 // Dimensioning the array of convective fluxes at the boundary of the computational
373 // domain
374 DoubleTab& flux_b = flux_bords_;
375 flux_b.resize(domaine_VEF.nb_faces_bord(),ncomp_ch_transporte);
376 flux_b = 0.;
377
378 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
379 {
380 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
381
382 if (sub_type(Neumann_sortie_libre,la_cl.valeur()))
383 {
384 const Neumann_sortie_libre& la_sortie_libre = ref_cast(Neumann_sortie_libre, la_cl.valeur());
385 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
386 int num1 = le_bord.num_premiere_face();
387 int num2 = num1 + le_bord.nb_faces();
388 for (num_face=num1; num_face<num2; num_face++)
389 {
390 psc =0;
391 for (i=0; i<dimension; i++)
392 psc += la_vitesse.valeurs()(num_face,i)*face_normales(num_face,i)*porosite_face(num_face);
393 if (psc>0)
394 if (ncomp_ch_transporte == 1)
395 {
396 resu(num_face) -= psc*transporte(num_face);
397 flux_b(num_face,0) -= psc*transporte(num_face);
398 }
399 else
400 for (i=0; i<ncomp_ch_transporte; i++)
401 {
402 resu(num_face,i) -= psc*transporte(num_face,i);
403 flux_b(num_face,i) -= psc*transporte(num_face,i);
404 }
405 else
406 {
407 if (ncomp_ch_transporte == 1)
408 {
409 resu(num_face) -= psc*la_sortie_libre.val_ext(num_face-num1);
410 flux_b(num_face,0) -= psc*la_sortie_libre.val_ext(num_face-num1);
411 }
412 else
413 for (i=0; i<ncomp_ch_transporte; i++)
414 {
415 resu(num_face,i) -= psc*la_sortie_libre.val_ext(num_face-num1,i);
416 flux_b(num_face,i) -= psc*la_sortie_libre.val_ext(num_face-num1,i);
417 }
418 fluent_(num_face) -= psc;
419 }
420 }
421 }
422 else if (sub_type(Periodique,la_cl.valeur()))
423 {
424 const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
425 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
426 int num1 = le_bord.num_premiere_face();
427 int num2 = num1 + le_bord.nb_faces();
428 IntVect fait(le_bord.nb_faces());
429 fait = 0;
430 for (num_face=num1; num_face<num2; num_face++)
431 {
432 if (fait[num_face-num1] == 0)
433 {
434 voisine = la_cl_perio.face_associee(num_face-num1) + num1;
435
436 if (ncomp_ch_transporte == 1)
437 {
438 diff1 = resu(num_face)-tab(nb_faces_perio);
439 diff2 = resu(voisine)-tab(nb_faces_perio+voisine-num_face);
440 resu(voisine) += diff1;
441 resu(num_face) += diff2;
442 flux_b(voisine,0) += diff1;
443 flux_b(num_face,0) += diff2;
444 }
445 else
446 for (int comp2=0; comp2<ncomp_ch_transporte; comp2++)
447 {
448 diff1 = resu(num_face,comp2)-tab(nb_faces_perio,comp2);
449 diff2 = resu(voisine,comp2)-tab(nb_faces_perio+voisine-num_face,comp2);
450 resu(voisine,comp2) += diff1;
451 resu(num_face,comp2) += diff2;
452 flux_b(voisine,comp2) += diff1;
453 flux_b(num_face,comp2) += diff2;
454 }
455
456 fait[num_face-num1]= 1;
457 fait[voisine-num1] = 1;
458 }
459 nb_faces_perio++;
460 }
461 }
462 }
463
464
465 modifier_flux(*this);
466 return resu;
467}
Class Champ_Inc_base.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
static DoubleTab & calcul_gradient(const DoubleTab &, DoubleTab &, const Domaine_Cl_VEF &)
virtual double valeur_a_sommet_compo(int, int, int) const
Returns the compo-th coordinate of the values at the element le_poly at the vertex sommet.
class Cond_lim Generic class used to represent any class
Definition Cond_lim.h:31
int type_elem_Cl(int i) const
DoubleTab & normales_facettes_Cl()
const Cond_lim & les_conditions_limites(int) const
Returns the i-th boundary condition.
class Domaine_VEF
Definition Domaine_VEF.h:53
IntVect & rang_elem_non_std()
Definition Domaine_VEF.h:85
const Elem_VEF_base & type_elem() const
Definition Domaine_VEF.h:74
auto & facette_normales()
Definition Domaine_VEF.h:83
int nb_faces() const
Returns the total number of faces.
Definition Domaine_VF.h:471
void creer_tableau_faces(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
double volumes(int i) const
Definition Domaine_VF.h:113
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.
Definition Domaine_VF.h:542
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_elem_tot() const
int nb_front_Cl() const
const Domaine & domaine() const
virtual void calcul_vc(const ArrOfInt &, ArrOfDouble &, const ArrOfDouble &, const DoubleTab &, const Champ_Inc_base &, int, const DoubleVect &) const =0
const IntTab & KEL() const
virtual int nb_facette() const =0
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual const Milieu_base & milieu() const =0
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
DoubleVect & porosite_face()
Definition Milieu_base.h:62
const Equation_base & equation() const
Returns the reference to the equation pointed to by MorEqn::mon_equation.
Definition MorEqn.h:62
Neumann_sortie_libre This class represents an open boundary without imposed velocity.
double val_ext(int i) const override
Returns the value of the i-th component of the field imposed on the exterior of the boundary.
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_Conv_Muscl_old_VEF_Face
DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const override
class Op_Conv_VEF_base
const Champ_Inc_base & vitesse() const
void modifier_flux(const Operateur_base &) const
DoubleTab flux_bords_
class Periodique This class represents a periodic boundary condition.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
Base class for output streams.
Definition Sortie.h:52
int nb_dim() const
Definition TRUSTTab.h:199
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133