TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Conv_Vort_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_Vort_VEF_Face.h>
17#include <Champ_P1NC.h>
18#include <Periodique.h>
19
20Implemente_instanciable(Op_Conv_Vort_VEF_Face,"Op_Conv_Conserve_Ec_VEF_P1NC",Op_Conv_VEF_base);
21
22
23//// printOn
24//
25
27{
28 return s << que_suis_je() ;
29}
30
31//// readOn
32//
33
35{
36 return s ;
37}
38
39
40DoubleTab& Op_Conv_Vort_VEF_Face::ajouter(const DoubleTab& transporte,
41 DoubleTab& resu) const
42{
43 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
44 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
45 const Champ_Inc_base& la_vitesse=vitesse_.valeur();
46 const Champ_P1NC& vit = ref_cast(Champ_P1NC,vitesse_.valeur());
47
48 const IntTab& elem_faces = domaine_VEF.elem_faces();
49 const IntTab& face_voisins = domaine_VEF.face_voisins();
50 const auto& facette_normales = domaine_VEF.facette_normales();
51 const Domaine& domaine = domaine_VEF.domaine();
52 const int nb_faces = domaine_VEF.nb_faces();
53 const int nfa7 = domaine_VEF.type_elem().nb_facette();
54 const int nb_elem = domaine_VEF.nb_elem();
55 const int nb_elem_tot = domaine_VEF.nb_elem_tot();
56 const IntVect& rang_elem_non_std = domaine_VEF.rang_elem_non_std();
57
58
59 const DoubleTab& normales_facettes_Cl = domaine_Cl_VEF.normales_facettes_Cl();
60
61 int nfac = domaine.nb_faces_elem();
62
63 const DoubleVect& volumes = domaine_VEF.volumes();
64 int comp0;
65 double flux;//,flux_int;
66 int num_face;
67 int elem0,elem1;
68 double vol0,vol1;
69 double inter,a0,a1,a2,f_int;
70
71 IntVect face(nfac);
72 DoubleVect cc(dimension);
73 DoubleTab psc(nfac);
74
75 int num_int;
76 IntTab autre_num_face(dimension-1);
77 IntTab autre_num_face_loc(dimension-1);
78 int poly,face_adj,fa7,i,j,n_bord;
79 int rang ;
80 int num10, num20;
81 int nu1, nu2;
82 int num_calc;
83
84
85 // Pour le traitement de la convection on distingue les polyedres
86 // standard qui ne "voient" pas les conditions aux limites et les
87 // polyedres non standard qui ont au moins une face sur le bord.
88 // Un polyedre standard a n facettes sur lesquelles on applique le
89 // schema de convection.
90 // Pour un polyedre non standard qui porte des conditions aux limites
91 // de Dirichlet, une partie des facettes sont portees par les faces.
92 // En bref pour un polyedre le traitement de la convection depend
93 // du type (triangle, tetraedre ...) et du nombre de faces de Dirichlet.
94
95 int ncomp_ch_transporte;
96 if (transporte.nb_dim() == 1)
97 ncomp_ch_transporte=1;
98 else
99 ncomp_ch_transporte= transporte.dimension(1);
100
101 // Cerr << "ncomp_ch_transporte=" << ncomp_ch_transporte << finl;
102
103 // On remet a zero le tableau qui sert pour
104 // le calcul du pas de temps de stabilite
105 fluent_ = 0;
106
107 // ATENTION : PBL pour determiner le fluent
108 // ******** on le met a 1!!!
109 // fluent_ = 1.;
110
111
112 // Traitement particulier pour les faces de periodicite
113
114 int nb_faces_perio = 0;
115 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
116 {
117 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
118 if (sub_type(Periodique,la_cl.valeur()))
119 {
120 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
121 int num1 = le_bord.num_premiere_face();
122 int num2 = num1 + le_bord.nb_faces();
123 for (num_face=num1; num_face<num2; num_face++)
124 nb_faces_perio++;
125 }
126 }
127
128 DoubleTab tab;
129 if (ncomp_ch_transporte == 1)
130 tab.resize(nb_faces_perio);
131 else
132 tab.resize(nb_faces_perio,ncomp_ch_transporte);
133
134 nb_faces_perio=0;
135 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
136 {
137 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
138 if (sub_type(Periodique,la_cl.valeur()))
139 {
140 // const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
141 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
142 int num1 = le_bord.num_premiere_face();
143 int num2 = num1 + le_bord.nb_faces();
144 for (num_face=num1; num_face<num2; num_face++)
145 {
146 if (ncomp_ch_transporte == 1)
147 tab(nb_faces_perio) = resu(num_face);
148 else
149 for (int comp=0; comp<ncomp_ch_transporte; comp++)
150 tab(nb_faces_perio,comp) = resu(num_face,comp);
151 nb_faces_perio++;
152 }
153 }
154 }
155
156 // Cerr << "tab=" << tab << finl;
157
158 // Les polyedres non standard sont ranges en 2 groupes dans le Domaine_VEF:
159 // - polyedres bords et joints
160 // - polyedres bords et non joints
161 // On traite les polyedres en suivant l'ordre dans lequel ils figurent
162 // dans le domaine
163
164 // boucle sur les polys
165
166
167 // Boucle pour ajouter la partie : Gradient(U^2/2)
168 // ******* boucle sur les elements
169 // 06/01/2000 On ne s'occupe pas encore des conditions aux limites (sauf periodique)
170 const IntTab& KEL=domaine_VEF.type_elem().KEL();
171 for (poly=0; poly<nb_elem_tot; poly++)
172 {
173
174 rang = rang_elem_non_std(poly);
175
176 // calcul des numeros des faces du polyedre
177 for (face_adj=0; face_adj<nfac; face_adj++)
178 face[face_adj]= elem_faces(poly,face_adj);
179
180 // On cherche les numeros globaux de toutes les faces
181 for (fa7=0; fa7<nfa7; fa7++)
182 {
183 nu1=-1;
184 nu2=-1;
185 num10 = face[KEL(0,fa7)];
186 num20 = face[KEL(1,fa7)];
187 // La facette est entouree des faces num1 et num2
188 // Cerr << "num1=" << num1 << " num2=" << num2 << finl;
189
190 // i=0;
191 // j=0;
192 // while(i<nfac)
193 // {
194 // num_int = face[i];
195 // if ((num_int!= num1)&&(num_int!= num2))
196 // {
197 // autre_num_face(j)=num_int;
198 // j++;
199 // }
200 // i++;
201 // }
202
203 // On cherche le numero des autres faces (locaux et globaux)
204
205 i=0;
206 j=0;
207 // k=0;
208 while(i<nfac)
209 {
210 num_int = face[i];
211 if (num_int == num10)
212 {
213 nu1=i;
214 }
215 else if (num_int == num20)
216 {
217 nu2=i;
218 }
219 else
220 {
221 autre_num_face_loc(j)=i;
222 autre_num_face(j)=num_int;
223 j++;
224 }
225 i++;
226 }
227
228 // Cerr << "num1=" << num1 << " num2=" << num2 << " autre_num_face(0)=" << autre_num_face(0) << finl;
229 // if (dimension==3)
230 // Cerr << "autre_num_face(1)=" << autre_num_face(1) << finl;
231
232 if (rang==-1)
233 {
234 for (i=0; i<dimension; i++)
235 cc[i] = facette_normales(poly,fa7,i);
236 }
237 else
238 for (i=0; i<dimension; i++)
239 cc[i] = normales_facettes_Cl(rang,fa7,i);
240
241 // On calcule les produits scalaires u(xi).n.S // >>> calcul de fluent!!
242 for (i=0; i<nfac; i ++)
243 {
244 psc[i] = 0.;
245 for (j=0; j<dimension; j++)
246 {
247 psc[i]+= la_vitesse.valeurs()(face[i],j)*cc[j];
248 }
249 }
250
251 // Calcul du flux
252 // Boucle sur les composantes : uu+vv+(ww)
253 flux = 0.;
254 if (dimension == 2)
255 {
256 f_int = 2.*((psc[nu1]+psc[nu2])- psc[autre_num_face_loc(0)])/3.;
257 }
258 else
259 {
260 // (dimension == 3)
261 assert(dimension == 3);
262 {
263 f_int = 3.*(psc[nu1]+psc[nu2]);
264 f_int -= (psc[autre_num_face_loc(0)]+psc[autre_num_face_loc(1)]);
265 f_int /= 4.;
266 }
267 }
268 if (f_int >= 0.)
269 num_calc = num10;
270 else
271 num_calc = num20;
272
273 flux = 0.;
274 for (comp0=0; comp0<dimension; comp0++)
275 flux += la_vitesse.valeurs()(num_calc,comp0)*la_vitesse.valeurs()(num_calc,comp0);
276
277 for (comp0=0; comp0<dimension; comp0++)
278 {
279 resu(num10, comp0) -= 0.5*flux*cc[comp0];
280 resu(num20, comp0) += 0.5*flux*cc[comp0];
281 }
282
283 // *** ??? : evaluation du fluent
284 if (f_int>0.)
285 {
286 // fluent_[num2] += std::fabs(f_int);
287 fluent_[num20] = ( fluent_[num20] > std::fabs(f_int))? fluent_[num20] : std::fabs(f_int);
288 }
289 else
290 {
291 fluent_[num10] = ( fluent_[num10] > std::fabs(f_int))? fluent_[num10] : std::fabs(f_int);
292 // fluent_[num1] += std::fabs(f_int);
293 }
294
295 }
296 }
297
298 // FIN DE LA BOUCLE SUR LES ELEMENTS
299 ////////// On fait la compensation ici, car la boucle suivante est sur les faces
300 ////////// En le faisant a la fin, on aurait deux fois la contribution aux faces
301 int voisine;
302 nb_faces_perio = 0;
303 double diff1,diff2;
304
305 // Dimensionnement du tableau des flux convectifs au bord du domaine
306 // de calcul
307 DoubleTab& flux_b = flux_bords_;
308 flux_b.resize(domaine_VEF.nb_faces_bord(),ncomp_ch_transporte);
309 flux_b = 0.;
310
311 // Boucle sur les bords pour traiter les conditions aux limites
312
313 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
314 {
315 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
316
317 if (sub_type(Periodique,la_cl.valeur()))
318 {
319 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
320 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
321 int num1 = le_bord.num_premiere_face();
322 int num2 = num1 + le_bord.nb_faces();
323 IntVect fait(le_bord.nb_faces());
324 fait = 0;
325 for (num_face=num1; num_face<num2; num_face++)
326 {
327 if (fait[num_face-num1] == 0)
328 {
329 voisine = la_cl_perio.face_associee(num_face-num1) + num1;
330
331 if (ncomp_ch_transporte == 1)
332 {
333 diff1 = resu(num_face)-tab(nb_faces_perio);
334 diff2 = resu(voisine)-tab(nb_faces_perio+voisine-num_face);
335 resu(voisine) += diff1;
336 resu(num_face) += diff2;
337 flux_b(voisine,0) += diff1;
338 flux_b(num_face,0) += diff2;
339 }
340 else
341 for (int comp=0; comp<ncomp_ch_transporte; comp++)
342 {
343 diff1 = resu(num_face,comp)-tab(nb_faces_perio,comp);
344 diff2 = resu(voisine,comp)-tab(nb_faces_perio+voisine-num_face,comp);
345 resu(voisine,comp) += diff1;
346 resu(num_face,comp) += diff2;
347 flux_b(voisine,comp) += diff1;
348 flux_b(num_face,comp) += diff2;
349 }
350
351 fait[num_face-num1]= 1;
352 fait[voisine-num1] = 1;
353 }
354 nb_faces_perio++;
355 }
356 }
357 }
358
359 /////////////////////////////////////////////////////
360 // Boucle pour ajouter la partie avec la vorticite
361 // ****** Boucle sur les faces
362
363 // Calcul de la vorticite
364 DoubleTab vorticite;
365 if (dimension == 2)
366 vorticite.resize(nb_elem);
367 else if (dimension == 3)
368 vorticite.resize(nb_elem,dimension);
369
370 vit.cal_rot_ordre1(vorticite);
371
372 // Cerr << "vorticite=" << vorticite << finl;
373
374 for (num_face=0; num_face<nb_faces; num_face++)
375 {
376 vol0=-1;
377 vol1=-1;
378 elem0 = face_voisins(num_face,0);
379 elem1 = face_voisins(num_face,1);
380
381 if (elem0 != -1)
382 vol0 = volumes(elem0);
383
384 if (elem1 != -1)
385 vol1 = volumes(elem1);
386
387 // Cerr << "vol0=" << vol0 << " vol1=" << vol1 << finl;
388
389 if (dimension == 2)
390 {
391 // for (comp=0;comp<dimension;comp++)
392 // {
393 assert(vol0>0);
394 assert(vol1>0);
395 inter = vorticite[elem0]*vol0/3.+vorticite[elem1]*vol1/3.;
396
397 resu(num_face,0) -= -inter*la_vitesse.valeurs()(num_face,1);
398 resu(num_face,1) -= inter*la_vitesse.valeurs()(num_face,0);
399
400 // signe - car on est dans le second membre
401
402 // *** PBL : evaluation du fluent
403 // if(psc >= 0)
404 // fluent_[num2] += psc;
405 // else
406 // fluent_[num1] -= psc;
407 }
408 else if (dimension == 3)
409 {
410 assert(vol0>0);
411 assert(vol1>0);
412 // vect(a) = vorticite*Vol
413 a0 = vorticite(elem0,0)*vol0/4. + vorticite(elem1,0)*vol1/4.;
414 a1 = vorticite(elem0,1)*vol0/4. + vorticite(elem1,1)*vol1/4.;
415 a2 = vorticite(elem0,2)*vol0/4. + vorticite(elem1,2)*vol1/4.;
416
417 resu(num_face,0) -= a1*la_vitesse.valeurs()(num_face,2)-a2*la_vitesse.valeurs()(num_face,1) ;
418 resu(num_face,1) -= a2*la_vitesse.valeurs()(num_face,0)-a0*la_vitesse.valeurs()(num_face,2) ;
419 resu(num_face,2) -= a0*la_vitesse.valeurs()(num_face,1)-a1*la_vitesse.valeurs()(num_face,0) ;
420
421 // signe - car on est dans le second membre
422
423 // *** PBL : evaluation du fluent
424 // if(psc >= 0)
425 // fluent_[num2] += psc;
426 // else
427 // fluent_[num1] -= psc;
428 }
429 }
430
431 //******* VERIF PERIO
432 Cerr << "DEBUT VERIF PERIO" << finl;
433 // Cerr << "nb_front_Cl=" << domaine_VEF.nb_front_Cl() << finl;
434 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
435 {
436 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
437
438 if (sub_type(Periodique,la_cl.valeur()))
439 {
440 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
441 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
442 int num1 = le_bord.num_premiere_face();
443 int num2 = num1 + le_bord.nb_faces();
444 // Cerr << "num1=" << num1 << " num2=" << num2 << finl;
445 for (num_face=num1; num_face<num2; num_face++)
446 {
447 voisine = la_cl_perio.face_associee(num_face-num1) + num1;
448 for (int ii=0; ii<dimension; ii++)
449 {
450 if ( resu(num_face,ii)!=resu(voisine,ii) )
451 {
452 Cerr << "Pbl de periodicite a la face" << num_face << finl;
453 Cerr << "diff = " << resu(num_face,ii)-resu(voisine,ii) << finl;
454 }
455 }
456 }
457 }
458 }
459 Cerr << "FIN VERIF PERIO" << finl;
460 //******* FIN VERIF PERIO
461
462 modifier_flux(*this);
463 return resu;
464}
Classe Champ_Inc_base.
DoubleTab & valeurs() override
Renvoie le tableau des valeurs du champ au temps courant.
void cal_rot_ordre1(DoubleTab &) const
classe Cond_lim Classe generique servant a representer n'importe quelle classe
Definition Cond_lim.h:31
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
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 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
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
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
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_VEF_base
class Op_Conv_Vort_VEF_Face
DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const override
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