TrioCFD 1.9.8
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// Fonctions de la classe Op_Conv_Muscl_old_VEF_Face
36//
37
38
39
40//////////////////////////////////////////////////////////////
41// Fonctions de MUSCL
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 des fonctions
66//
67// de la classe 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 // Pour le traitement de la convection on distingue les polyedres
100 // standard qui ne "voient" pas les conditions aux limites et les
101 // polyedres non standard qui ont au moins une face sur le bord.
102 // Un polyedre standard a n facettes sur lesquelles on applique le
103 // schema de convection.
104 // Pour un polyedre non standard qui porte des conditions aux limites
105 // de Dirichlet, une partie des facettes sont portees par les faces.
106 // En bref pour un polyedre le traitement de la convection depend
107 // du type (triangle, tetraedre ...) et du nombre de faces de Dirichlet.
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 // Traitement particulier pour les faces de periodicite
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) pour un poly
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) pour une face
178 // gradient_elem=0.; deja fait par le constructeur
179
180 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
181
182 Champ_P1NC::calcul_gradient(transporte,gradient_elem,domaine_Cl_VEF);
183
184 // On a les gradient_elem par elements
185
186 ////////////////////////////////////////////////////////////////////////////////////////////////////////
187 // Limitation minmod
188 //
189 // Boucle sur les 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 /* amont : */= 0;
197
198 } // fin du for faces
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 } // fin du for faces
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 // On remet a zero le tableau qui sert pour
229 // le calcul du pas de temps de stabilite
230 fluent_ = 0;
231
232 // Les polyedres non standard sont ranges en 2 groupes dans le Domaine_VEF:
233 // - polyedres bords et joints
234 // - polyedres bords et non joints
235 // On traite les polyedres en suivant l'ordre dans lequel ils figurent
236 // dans le domaine
237
238 // boucle sur les polys
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 // calcul des numeros des faces du polyedre
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 // calcul de la vitesse aux sommets des polyedres
261 // On va utliser les fonctions de forme implementees dans la classe Champs_P1_impl ou Champs_Q1_impl
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 // pour que cela soit valide avec les hexa (c'est + lent a calculer...)
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 // calcul de vc (a l'intersection des 3 facettes)
282 type_elemvef.calcul_vc(face,vc,vs,vsom,vitesse(),itypcl,porosite_face);
283
284 // Boucle sur les facettes du polyedre non standard:
285 for (fa7=0; fa7<nfa7; fa7++)
286 {
287 num10 = face(KEL(0,fa7));
288 num20 = face(KEL(1,fa7));
289 // normales aux facettes
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 // On applique le schema de convection a chaque sommet de la facette
298 for (i=0; i<nb_som_facette; i++)
299 {
300 psc =0;
301 if (i==nb_som_facette-1)
302 {
303 // On traite le sommet confondu avec le centre de gravite du polyedre
304 for (j=0; j<dimension; j++)
305 psc += vc[j]*cc[j];
306 }
307 else
308 {
309 // On traite le ou les sommets qui sont aussi des sommets du polyedre
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 // Calcul de convmuscl (auparavant dans une fonction qui n'etait pas toujours inlinee par le compilateur)
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 } // fin de la boucle sur les sommets de facette
358 } // fin de la boucle sur les facettes
359 } // fin de la boucle
360
361
362
363
364 int voisine;
365 nb_faces_perio = 0;
366 double diff1,diff2;
367
368 // Boucle sur les bords pour traiter les conditions aux limites
369 // il y a prise en compte d'un terme de convection pour les
370 // conditions aux limites de Neumann_sortie_libre seulement
371
372 // Dimensionnement du tableau des flux convectifs au bord du domaine
373 // de calcul
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}
Classe Champ_Inc_base.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
static DoubleTab & calcul_gradient(const DoubleTab &, DoubleTab &, const Domaine_Cl_VEF &)
virtual double valeur_a_sommet_compo(int, int, int) const
renvoi la compo eme corrdonne des valeurs a l'element le_poly au sommet sommet
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
int type_elem_Cl(int i) const
DoubleTab & normales_facettes_Cl()
const Cond_lim & les_conditions_limites(int) const
Renvoie la i-ieme condition aux limites.
class Domaine_VEF
Definition Domaine_VEF.h:54
IntVect & rang_elem_non_std()
Definition Domaine_VEF.h:86
const Elem_VEF_base & type_elem() const
Definition Domaine_VEF.h:75
auto & facette_normales()
Definition Domaine_VEF.h:84
int nb_faces() const
renvoie le nombre global de 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
renvoie le numero de le ieme face de la maille num_elem la facon dont ces faces sont numerotees est
Definition Domaine_VF.h:543
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_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
Renvoie la reference sur l'equation pointe par MorEqn::mon_equation.
Definition MorEqn.h:62
classe Neumann_sortie_libre Cette classe represente une frontiere ouverte sans vitesse imposee
double val_ext(int i) const override
Renvoie la valeur de la i-eme composante du champ impose a l'exterieur de la frontiere.
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_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_
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
int face_associee(int i) const
Definition Periodique.h:35
Classe de base des flux de sortie.
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