TrioCFD 1.9.9_beta
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 // For the convection treatment, standard polyhedra (not "seeing" boundary conditions)
86 // are distinguished from non-standard polyhedra (having at least one boundary face).
87 // A standard polyhedron has n facets on which the convection scheme is applied.
88 // For a non-standard polyhedron with Dirichlet boundary conditions, part of its
89 // facets are carried by the boundary faces.
90 // In short, for a polyhedron the convection treatment depends on the type
91 // (triangle, tetrahedron ...) and the number of Dirichlet faces.
92
93 int ncomp_ch_transporte;
94 if (transporte.nb_dim() == 1)
95 ncomp_ch_transporte=1;
96 else
97 ncomp_ch_transporte= transporte.dimension(1);
98
99 // Cerr << "ncomp_ch_transporte=" << ncomp_ch_transporte << finl;
100
101 // Reset the array used for
102 // computing the stability time step
103 fluent_ = 0;
104
105 // WARNING: issue with determining the flux (fluent)
106 // ******** set to 1 for now!!!
107 // fluent_ = 1.;
108
109
110 // Special treatment for periodic faces
111
112 int nb_faces_perio = 0;
113 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
114 {
115 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
116 if (sub_type(Periodique,la_cl.valeur()))
117 {
118 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
119 int num1 = le_bord.num_premiere_face();
120 int num2 = num1 + le_bord.nb_faces();
121 for (num_face=num1; num_face<num2; num_face++)
122 nb_faces_perio++;
123 }
124 }
125
126 DoubleTab tab;
127 if (ncomp_ch_transporte == 1)
128 tab.resize(nb_faces_perio);
129 else
130 tab.resize(nb_faces_perio,ncomp_ch_transporte);
131
132 nb_faces_perio=0;
133 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
134 {
135 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
136 if (sub_type(Periodique,la_cl.valeur()))
137 {
138 // const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
139 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
140 int num1 = le_bord.num_premiere_face();
141 int num2 = num1 + le_bord.nb_faces();
142 for (num_face=num1; num_face<num2; num_face++)
143 {
144 if (ncomp_ch_transporte == 1)
145 tab(nb_faces_perio) = resu(num_face);
146 else
147 for (int comp=0; comp<ncomp_ch_transporte; comp++)
148 tab(nb_faces_perio,comp) = resu(num_face,comp);
149 nb_faces_perio++;
150 }
151 }
152 }
153
154 // Cerr << "tab=" << tab << finl;
155
156 // Non-standard polyhedra are grouped into 2 sets in Domaine_VEF:
157 // - boundary and joint polyhedra
158 // - boundary and non-joint polyhedra
159 // Polyhedra are processed in the order in which they appear in the domain
160
161 // loop over polyhedra
162
163
164 // Loop to add the part: Gradient(U^2/2)
165 // ******* loop over elements
166 // 06/01/2000 Boundary conditions not yet handled here (except periodic)
167 const IntTab& KEL=domaine_VEF.type_elem().KEL();
168 for (poly=0; poly<nb_elem_tot; poly++)
169 {
170
171 rang = rang_elem_non_std(poly);
172
173 // compute the face indices of the polyhedron
174 for (face_adj=0; face_adj<nfac; face_adj++)
175 face[face_adj]= elem_faces(poly,face_adj);
176
177 // Find the global indices of all faces
178 for (fa7=0; fa7<nfa7; fa7++)
179 {
180 nu1=-1;
181 nu2=-1;
182 num10 = face[KEL(0,fa7)];
183 num20 = face[KEL(1,fa7)];
184 // The facet is surrounded by faces num1 and num2
185 // Cerr << "num1=" << num1 << " num2=" << num2 << finl;
186
187 // i=0;
188 // j=0;
189 // while(i<nfac)
190 // {
191 // num_int = face[i];
192 // if ((num_int!= num1)&&(num_int!= num2))
193 // {
194 // autre_num_face(j)=num_int;
195 // j++;
196 // }
197 // i++;
198 // }
199
200 // Find the indices of the other faces (local and global)
201
202 i=0;
203 j=0;
204 // k=0;
205 while(i<nfac)
206 {
207 num_int = face[i];
208 if (num_int == num10)
209 {
210 nu1=i;
211 }
212 else if (num_int == num20)
213 {
214 nu2=i;
215 }
216 else
217 {
218 autre_num_face_loc(j)=i;
219 autre_num_face(j)=num_int;
220 j++;
221 }
222 i++;
223 }
224
225 // Cerr << "num1=" << num1 << " num2=" << num2 << " autre_num_face(0)=" << autre_num_face(0) << finl;
226 // if (dimension==3)
227 // Cerr << "autre_num_face(1)=" << autre_num_face(1) << finl;
228
229 if (rang==-1)
230 {
231 for (i=0; i<dimension; i++)
232 cc[i] = facette_normales(poly,fa7,i);
233 }
234 else
235 for (i=0; i<dimension; i++)
236 cc[i] = normales_facettes_Cl(rang,fa7,i);
237
238 // Compute the scalar products u(xi).n.S // >>> fluent computation!!
239 for (i=0; i<nfac; i ++)
240 {
241 psc[i] = 0.;
242 for (j=0; j<dimension; j++)
243 {
244 psc[i]+= la_vitesse.valeurs()(face[i],j)*cc[j];
245 }
246 }
247
248 // Compute the flux
249 // Loop over components: uu+vv+(ww)
250 flux = 0.;
251 if (dimension == 2)
252 {
253 f_int = 2.*((psc[nu1]+psc[nu2])- psc[autre_num_face_loc(0)])/3.;
254 }
255 else
256 {
257 // (dimension == 3)
258 assert(dimension == 3);
259 {
260 f_int = 3.*(psc[nu1]+psc[nu2]);
261 f_int -= (psc[autre_num_face_loc(0)]+psc[autre_num_face_loc(1)]);
262 f_int /= 4.;
263 }
264 }
265 if (f_int >= 0.)
266 num_calc = num10;
267 else
268 num_calc = num20;
269
270 flux = 0.;
271 for (comp0=0; comp0<dimension; comp0++)
272 flux += la_vitesse.valeurs()(num_calc,comp0)*la_vitesse.valeurs()(num_calc,comp0);
273
274 for (comp0=0; comp0<dimension; comp0++)
275 {
276 resu(num10, comp0) -= 0.5*flux*cc[comp0];
277 resu(num20, comp0) += 0.5*flux*cc[comp0];
278 }
279
280 // *** ??? : flux (fluent) evaluation
281 if (f_int>0.)
282 {
283 // fluent_[num2] += std::fabs(f_int);
284 fluent_[num20] = ( fluent_[num20] > std::fabs(f_int))? fluent_[num20] : std::fabs(f_int);
285 }
286 else
287 {
288 fluent_[num10] = ( fluent_[num10] > std::fabs(f_int))? fluent_[num10] : std::fabs(f_int);
289 // fluent_[num1] += std::fabs(f_int);
290 }
291
292 }
293 }
294
295 // FIN DE LA BOUCLE SUR LES ELEMENTS
296 ////////// Apply compensation here, because the next loop is over faces.
297 ////////// Doing it at the end would count the face contribution twice.
298 int voisine;
299 nb_faces_perio = 0;
300 double diff1,diff2;
301
302 // Dimensioning the array of convective fluxes at the boundary
303 // of the computational domain
304 DoubleTab& flux_b = flux_bords_;
305 flux_b.resize(domaine_VEF.nb_faces_bord(),ncomp_ch_transporte);
306 flux_b = 0.;
307
308 // Loop over the boundaries to process the boundary conditions
309
310 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
311 {
312 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
313
314 if (sub_type(Periodique,la_cl.valeur()))
315 {
316 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
317 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
318 int num1 = le_bord.num_premiere_face();
319 int num2 = num1 + le_bord.nb_faces();
320 IntVect fait(le_bord.nb_faces());
321 fait = 0;
322 for (num_face=num1; num_face<num2; num_face++)
323 {
324 if (fait[num_face-num1] == 0)
325 {
326 voisine = la_cl_perio.face_associee(num_face-num1) + num1;
327
328 if (ncomp_ch_transporte == 1)
329 {
330 diff1 = resu(num_face)-tab(nb_faces_perio);
331 diff2 = resu(voisine)-tab(nb_faces_perio+voisine-num_face);
332 resu(voisine) += diff1;
333 resu(num_face) += diff2;
334 flux_b(voisine,0) += diff1;
335 flux_b(num_face,0) += diff2;
336 }
337 else
338 for (int comp=0; comp<ncomp_ch_transporte; comp++)
339 {
340 diff1 = resu(num_face,comp)-tab(nb_faces_perio,comp);
341 diff2 = resu(voisine,comp)-tab(nb_faces_perio+voisine-num_face,comp);
342 resu(voisine,comp) += diff1;
343 resu(num_face,comp) += diff2;
344 flux_b(voisine,comp) += diff1;
345 flux_b(num_face,comp) += diff2;
346 }
347
348 fait[num_face-num1]= 1;
349 fait[voisine-num1] = 1;
350 }
351 nb_faces_perio++;
352 }
353 }
354 }
355
356 /////////////////////////////////////////////////////
357 // Loop to add the vorticity part
358 // ****** Loop over faces
359
360 // Compute the vorticity
361 DoubleTab vorticite;
362 if (dimension == 2)
363 vorticite.resize(nb_elem);
364 else if (dimension == 3)
365 vorticite.resize(nb_elem,dimension);
366
367 vit.cal_rot_ordre1(vorticite);
368
369 // Cerr << "vorticite=" << vorticite << finl;
370
371 for (num_face=0; num_face<nb_faces; num_face++)
372 {
373 vol0=-1;
374 vol1=-1;
375 elem0 = face_voisins(num_face,0);
376 elem1 = face_voisins(num_face,1);
377
378 if (elem0 != -1)
379 vol0 = volumes(elem0);
380
381 if (elem1 != -1)
382 vol1 = volumes(elem1);
383
384 // Cerr << "vol0=" << vol0 << " vol1=" << vol1 << finl;
385
386 if (dimension == 2)
387 {
388 // for (comp=0;comp<dimension;comp++)
389 // {
390 assert(vol0>0);
391 assert(vol1>0);
392 inter = vorticite[elem0]*vol0/3.+vorticite[elem1]*vol1/3.;
393
394 resu(num_face,0) -= -inter*la_vitesse.valeurs()(num_face,1);
395 resu(num_face,1) -= inter*la_vitesse.valeurs()(num_face,0);
396
397 // minus sign because we are in the right-hand side
398
399 // *** PBL : flux (fluent) evaluation
400 // if(psc >= 0)
401 // fluent_[num2] += psc;
402 // else
403 // fluent_[num1] -= psc;
404 }
405 else if (dimension == 3)
406 {
407 assert(vol0>0);
408 assert(vol1>0);
409 // vect(a) = vorticite*Vol
410 a0 = vorticite(elem0,0)*vol0/4. + vorticite(elem1,0)*vol1/4.;
411 a1 = vorticite(elem0,1)*vol0/4. + vorticite(elem1,1)*vol1/4.;
412 a2 = vorticite(elem0,2)*vol0/4. + vorticite(elem1,2)*vol1/4.;
413
414 resu(num_face,0) -= a1*la_vitesse.valeurs()(num_face,2)-a2*la_vitesse.valeurs()(num_face,1) ;
415 resu(num_face,1) -= a2*la_vitesse.valeurs()(num_face,0)-a0*la_vitesse.valeurs()(num_face,2) ;
416 resu(num_face,2) -= a0*la_vitesse.valeurs()(num_face,1)-a1*la_vitesse.valeurs()(num_face,0) ;
417
418 // minus sign because we are in the right-hand side
419
420 // *** PBL : flux (fluent) evaluation
421 // if(psc >= 0)
422 // fluent_[num2] += psc;
423 // else
424 // fluent_[num1] -= psc;
425 }
426 }
427
428 //******* VERIF PERIO
429 Cerr << "DEBUT VERIF PERIO" << finl;
430 // Cerr << "nb_front_Cl=" << domaine_VEF.nb_front_Cl() << finl;
431 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
432 {
433 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
434
435 if (sub_type(Periodique,la_cl.valeur()))
436 {
437 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
438 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
439 int num1 = le_bord.num_premiere_face();
440 int num2 = num1 + le_bord.nb_faces();
441 // Cerr << "num1=" << num1 << " num2=" << num2 << finl;
442 for (num_face=num1; num_face<num2; num_face++)
443 {
444 voisine = la_cl_perio.face_associee(num_face-num1) + num1;
445 for (int ii=0; ii<dimension; ii++)
446 {
447 if ( resu(num_face,ii)!=resu(voisine,ii) )
448 {
449 Cerr << "Pbl de periodicite a la face" << num_face << finl;
450 Cerr << "diff = " << resu(num_face,ii)-resu(voisine,ii) << finl;
451 }
452 }
453 }
454 }
455 }
456 Cerr << "FIN VERIF PERIO" << finl;
457 //******* FIN VERIF PERIO
458
459 modifier_flux(*this);
460 return resu;
461}
Class Champ_Inc_base.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
void cal_rot_ordre1(DoubleTab &) const
class Cond_lim Generic class used to represent any class
Definition Cond_lim.h:31
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
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 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
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: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_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_
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