TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Conv_kschemas_VEF.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_kschemas_VEF.h>
17#include <Periodique.h>
18#include <Neumann_sortie_libre.h>
19
20Implemente_base(Op_Conv_kschemas_VEF,"Op_Conv_kschemas_VEF_P1NC",Op_Conv_VEF_base);
21
22
24{
25 return s << que_suis_je() ;
26}
27
29{
30 return s ;
31}
32
33void Op_Conv_kschemas_VEF::associer(const Domaine_dis_base& domaine_dis, const Domaine_Cl_dis_base& domaine_cl_dis, const Champ_Inc_base& ch)
34{
35 // CCa le 28/05/99 The Kquick scheme does not work in parallel!!
37 {
38 Cerr << "WARNING: kquick scheme does not work in parallel !!!" << finl;
39 exit();
40 }
41
42 Op_Conv_VEF_base::associer(domaine_dis, domaine_cl_dis, ch);
43}
44
45
46//////////////////////////////////////////////////////////////
47// Functions for the k-schemes.
48////////////////////////////////////////////////////////////////
49
50// convkschemas : utility function for convection
51
52void convkschemas(const double K, const int ncomp, int dimension, const int poly ,
53 const int poly1, const int poly2,const int jel0,
54 const int jel1,const double psc ,const DoubleTab& tab1 ,
55 DoubleVect& fluent, DoubleVect& flux,
56 const DoubleVect& rx0, const DoubleTab& gradient_elem )
57{
58
59 int comp,amont,i,elem1,elem2;
60 double CF,UTC,deltat0,deltat1,deltat;
61 DoubleVect rx(dimension);
62 deltat0 = 0.;
63 deltat1 = 0.;
64
65 ////////////////////////////////////////////////////////////////////////
66 // Test on boundaries
67 ////////////////////////////////////////////////////////////////////////
68 if ((poly1==-1) || (poly2==-1))
69 {
70 if (psc >= 0)
71 {
72 amont = jel0;
73 fluent[jel1] += psc;
74 }
75 else
76 {
77 amont = jel1;
78 fluent[jel0] -= psc;
79 }
80
81 for (comp=0; comp<ncomp; comp++)
82 flux(comp) = tab1(amont,comp);
83
84 }
85 else
86 {
87 if (psc >= 0)
88 {
89 amont = jel0;
90 rx = rx0;
91 elem1 = poly;
92 elem2 = poly1;
93 fluent(jel1) += psc;
94 }
95 else
96 {
97 amont = jel1;
98 rx = rx0;
99 rx *= -1.;
100 elem1 = poly;
101 elem2 = poly2;
102 fluent(jel0) -= psc;
103 }
104
105 for (comp=0; comp<ncomp; comp++)
106 {
107 deltat0 = deltat1 = 0.0;
108 flux(comp) = tab1(amont,comp);
109 //Cerr << " flux(" << comp << ") ie phiamont= " << flux(comp) << finl;
110
111 for (i=0; i<dimension; i++)
112 {
113 deltat0 += gradient_elem(elem1,comp,i)*rx(i);
114 deltat1 += gradient_elem(elem2,comp,i)*rx(i);
115 }
116
117 if (K == 0.5)
118 {
119 deltat = deltat0 + deltat1;
120
121 if (std::fabs(deltat) <= 1.e-5)
122 {
123 CF = 0.125;
124 }
125 else
126 {
127 UTC = deltat1 / deltat;
128
129 if ( (UTC <= -1.) || (UTC >= 1.5) ) CF = 0.125;
130 else if ((UTC > -1.) && (UTC <= 0.)) CF = 0.5 + 0.375*UTC;
131 else if ((UTC > 0.) && (UTC <= 0.25)) CF = 0.5 - 0.625*sqrt(UTC);
132 else if ((UTC > 0.25) && (UTC < 1.5 )) CF = 0.25* std::fabs(UTC - 1.);
133 else
134 {
135 CF=0.;
137 }
138 }
139 // Compute the flux
140 flux(comp) += (0.5 - CF)*deltat0 + CF*deltat1 ;
141 //Cerr << " flux(" << comp << ")= " << flux(comp) << finl;
142 }
143 else
144 {
145 // Compute the flux
146 flux(comp) += 0.25*((1.+K)*deltat0 + (1.-K)*deltat1) ;
147 }
148 }
149
150 }
151}
152
153//////////////////////////////////////////////////////////////////////////
154// Procedure AJOUTER
155/////////////////////////////////////////////////////////////////////////
156
157DoubleTab& Op_Conv_kschemas_VEF::ajouter(const DoubleTab& transporte,
158 DoubleTab& resu) const
159{
160 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
161 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
162 const DoubleVect& porosite_face = equation().milieu().porosite_face();
163 const Champ_Inc_base& la_vitesse=vitesse_.valeur();
164 const IntTab& elem_faces = domaine_VEF.elem_faces();
165 const DoubleTab& face_normales = domaine_VEF.face_normales();
166 const auto& facette_normales = domaine_VEF.facette_normales();
167 const Domaine& domaine = domaine_VEF.domaine();
168 const int nb_faces = domaine_VEF.nb_faces();
169 const int nfa7 = domaine_VEF.type_elem().nb_facette();
170 const int nb_elem = domaine_VEF.nb_elem();
171 const int nb_elem_tot = domaine_VEF.nb_elem_tot();
172 const IntVect& rang_elem_non_std = domaine_VEF.rang_elem_non_std();
173 const IntTab& face_voisins = domaine_VEF.face_voisins();
174 const DoubleVect& volumes = domaine_VEF.volumes();
175 const DoubleTab& xv = domaine_VEF.xv();
176 const DoubleTab& xg = domaine_VEF.xp();
177 const DoubleTab& coord = domaine.coord_sommets();
178 int premiere_face_int = domaine_VEF.premiere_face_int();
179 const IntTab& les_Polys = domaine.les_elems();
180
181 const DoubleTab& normales_facettes_Cl = domaine_Cl_VEF.normales_facettes_Cl();
182
183 int nfac = domaine.nb_faces_elem();
184 int nsom = domaine.nb_som_elem();
185 int nb_som_facette = domaine.type_elem()->nb_som_face();
186
187 // For the convection treatment, standard polyhedra (not "seeing" boundary conditions)
188 // are distinguished from non-standard polyhedra (having at least one boundary face).
189 // A standard polyhedron has n facets on which the convection scheme is applied.
190 // For a non-standard polyhedron with Dirichlet boundary conditions, part of its
191 // facets are carried by the boundary faces.
192 // In short, for a polyhedron the convection treatment depends on the type
193 // (triangle, tetrahedron ...) and the number of Dirichlet faces.
194
195 double psc;
196 int poly,poly1,poly2,face_adj,fa7,i,j,n_bord;
197 int num_face, rang ,itypcl;
198 int num10,num20,num3,num_som;
199
200 // MODIF SB su 10/09/03
201 // For the following 3 elements, there are as many vertices as faces
202 // making up the geometric element.
203 // Problem with hexahedra: 8 vertices and 6 faces, so using the array
204 // face[i] no longer works.
205 // The method retained to avoid computing velocity at vertices without
206 // the shape functions is therefore not usable for hexahedra,
207 // where the Face=>vertices array exists but not its inverse.
208 // Too costly; porosity extension to hexahedra is not done for now.
209
210 int istetra=0;
211 const Elem_VEF_base& type_elemvef= domaine_VEF.type_elem();
212 Nom nom_elem=type_elemvef.que_suis_je();
213 if ((nom_elem=="Tetra_VEF")||(nom_elem=="Tri_VEF")) istetra=1;
214
215 const int ncomp_ch_transporte= transporte.line_size();
216 int fac,elem1,elem2,comp0;
217 int nb_faces_ = domaine_VEF.nb_faces();
218 IntVect face(nfac);
219
220 DoubleVect flux(ncomp_ch_transporte);
221 DoubleVect fluxsom(ncomp_ch_transporte);
222 DoubleVect fluxg(ncomp_ch_transporte);
223
224 // Special treatment for periodic faces
225 int nb_faces_perio = 0;
226 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
227 {
228 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
229 if (sub_type(Periodique,la_cl.valeur()))
230 {
231 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
232 int num1 = le_bord.num_premiere_face();
233 int num2 = num1 + le_bord.nb_faces();
234 for (num_face=num1; num_face<num2; num_face++)
235 nb_faces_perio++;
236 }
237 }
238
239 DoubleTab tab(nb_faces_perio,ncomp_ch_transporte);
240
241 nb_faces_perio=0;
242 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
243 {
244 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
245 if (sub_type(Periodique,la_cl.valeur()))
246 {
247 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
248 int num1 = le_bord.num_premiere_face();
249 int num2 = num1 + le_bord.nb_faces();
250 for (num_face=num1; num_face<num2; num_face++)
251 {
252 for (int comp=0; comp<ncomp_ch_transporte; comp++)
253 tab(nb_faces_perio,comp) = resu(num_face,comp);
254 nb_faces_perio++;
255 }
256 }
257 }
258
259
260 ///////////////////////////////////////////////////////////////////////////////////////////////
261 // <
262 // gradient computation; < [ Ujp*np/vol(j) ]
263 // j
264 ////////////////////////////////////////////////////////////////////////////////////////////////
265 DoubleTab gradient_elem(0, ncomp_ch_transporte, dimension);
266 domaine_VEF.domaine().creer_tableau_elements(gradient_elem);
267 // Loop over faces
268
269
270 for (fac=0; fac< premiere_face_int; fac++)
271 {
272 elem1=face_voisins(fac,0);
273 if(ncomp_ch_transporte==1)
274 for (i=0; i<dimension; i++)
275 {
276 gradient_elem(elem1, 0, i) +=
277 face_normales(fac,i)*transporte(fac);
278 }
279 else
280 for (comp0=0; comp0<ncomp_ch_transporte; comp0++)
281 for (i=0; i<dimension; i++)
282 gradient_elem(elem1, comp0, i) +=
283 face_normales(fac,i)*transporte(fac,comp0);
284 // dUcomp/dXi
285 } // end of for faces
286
287 for (; fac<nb_faces_; fac++)
288 {
289 elem1=face_voisins(fac,0);
290 elem2=face_voisins(fac,1);
291 if(ncomp_ch_transporte==1)
292 for (i=0; i<dimension; i++)
293 {
294 gradient_elem(elem1, 0, i) +=
295 face_normales(fac,i)*transporte(fac);
296 gradient_elem(elem2, 0, i) -=
297 face_normales(fac,i)*transporte(fac);
298 }
299 else
300 for (comp0=0; comp0<ncomp_ch_transporte; comp0++)
301 for (i=0; i<dimension; i++)
302 {
303 gradient_elem(elem1, comp0, i) +=
304 face_normales(fac,i)*transporte(fac,comp0);
305 gradient_elem(elem2, comp0, i) -=
306 face_normales(fac,i)*transporte(fac,comp0);
307 }
308 // dUcomp/dXi
309 } // end of for faces
310
311 for (int elem=0; elem<nb_elem; elem++)
312 for (comp0=0; comp0<ncomp_ch_transporte; comp0++)
313 for (i=0; i<dimension; i++)
314 gradient_elem(elem,comp0,i) /= volumes(elem);
315
316 gradient_elem.echange_espace_virtuel();
317
318 ////////////////////////////////////////////////////////////////////////////////////
319 // We have gradient_elem per element
320 ////////////////////////////////////////////////////////////////////////////////////
321
322 DoubleVect vs(dimension);
323 DoubleVect vc(dimension);
324 DoubleTab vsom(nsom,dimension);
325 DoubleVect cc(dimension);
326 double xm;
327
328 // Reset the array used for
329 // computing the stability time step
330 fluent_ = 0;
331
332 // Non-standard polyhedra are grouped into 2 sets in Domaine_VEF:
333 // - boundary and joint polyhedra
334 // - boundary and non-joint polyhedra
335 // Polyhedra are processed in the order in which they appear in the domain
336
337 //////////////////////////////////////////////////////////////////////////////////////
338 // loop over polyhedra
339 //////////////////////////////////////////////////////////////////////////////////////
340 const IntTab& KEL=domaine_VEF.type_elem().KEL();
341 for (poly=0; poly<nb_elem; poly++)
342 {
343 rang = rang_elem_non_std(poly);
344 if (rang==-1)
345 itypcl=0;
346 else
347 itypcl=domaine_Cl_VEF.type_elem_Cl(rang);
348
349 // compute the face indices of the polyhedron
350 for (face_adj=0; face_adj<nfac; face_adj++)
351 face(face_adj)= elem_faces(poly,face_adj);
352
353 int scom;
354 DoubleVect rx0(dimension);
355
356 // compute velocity at the vertices of the polyhedra
357 for (j=0; j<dimension; j++)
358 {
359 vs(j) = la_vitesse.valeurs()(face(0),j)*porosite_face(face(0));
360 for (i=1; i<nfac; i++)
361 vs(j)+= la_vitesse.valeurs()(face(i),j)*porosite_face(face(i));
362 }
363
364 //int ncomp;
365 if (istetra==1)
366 {
367 for (j=0; j<nsom; j++)
368 {
369 for (int ncomp=0; ncomp<Objet_U::dimension; ncomp++)
370 vsom(j,ncomp) =vs[ncomp] - Objet_U::dimension*la_vitesse.valeurs()(face[j],ncomp)*porosite_face(face[j]);
371 }
372 }
373 else
374 {
375 // to be valid with hexahedra
376 // Use the shape functions implemented in class Champs_P1_impl or Champs_Q1_impl
377 //int ncomp;
378 for (j=0; j<nsom; j++)
379 {
380 num_som = domaine.sommet_elem(poly,j);
381 for (int ncomp=0; ncomp<dimension; ncomp++)
382 {
383 vsom(j,ncomp) = la_vitesse.valeur_a_sommet_compo(num_som,poly,ncomp);
384 }
385 }
386 }
387 // compute the velocity at the centre of gravity
388 domaine_VEF.type_elem().calcul_vc(face,vc,vs,vsom,vitesse(),itypcl,porosite_face);
389
390 // Loop over facets of the non-standard polyhedron:
391 for (fa7=0; fa7<nfa7; fa7++)
392 {
393 //Cerr << "the facet being studied is " << fa7 << finl;
394 // fa7 separates num1 and num2. num3 is the third face (2D).
395
396 num10 = face(KEL(0,fa7));
397 num20 = face(KEL(1,fa7));
398 num3 = face(KEL(2,fa7));
399
400 // Determine the neighbouring elements at faces num1 and num2
401
402 poly1 = face_voisins(num10,0);
403 if (poly1==poly)
404 poly1 = face_voisins(num10,1);
405
406 poly2 = face_voisins(num20,0);
407 if (poly2==poly)
408 poly2 = face_voisins(num20,1);
409
410 scom = les_Polys(poly,KEL(2,fa7));
411
412 // compute rx0, distance between the midpoints of 'num i'
413
414 for (i=0; i<dimension; i++)
415 rx0(i) = xv(num20,i)-xv(num10,i);
416
417 // facet normals
418
419 if (rang==-1)
420 for (i=0; i<dimension; i++)
421 cc[i] = facette_normales(poly, fa7, i);
422 else
423 for (i=0; i<dimension; i++)
424 cc[i] = normales_facettes_Cl(rang,fa7,i);
425
426 /////////////////////////////////////////////////////////////////////////
427 // Process the point for which velocity = 0.5*(vertex_velocity + midpoint_velocity)
428 /////////////////////////////////////////////////////////////////////////
429
430 for (i=0; i<nb_som_facette-1; i++)
431 {
432 //////////////////////////////////////////////////////////////////////////
433 //Determination of PhiIJ at the midpoint between the vertex and the center of num3
434 /////////////////////////////////////////////////////////////////////////
435
436 psc = 0;
437 for (j=0; j<dimension; j++)
438 psc+=((vsom(KEL(i+2,fa7),j) + la_vitesse.valeurs()(num3,j) * porosite_face(num3)))*cc[j];
439 psc *=0.5;
440 convkschemas(K,ncomp_ch_transporte,dimension,poly,poly1,poly2,num10,num20,psc,transporte,
441 fluent_,flux,rx0,gradient_elem);
442
443 ////////////////////////////////////////////////////////////////////////////////////////////////////////
444 //Gradient limiter. Computed at the same time as the flux.
445 // gradient(K0) = teta*gradient(K0)+ (1-teta)*gradient(K1 or K2)
446 ////////////////////////////////////////////////////////////////////////////////////////////////////////
447
448 double teta = 0.5;
449
450 /////////////////////////////////////////////////////////////////////////
451 // Process the vertices that are also vertices of the polyhedron
452 /////////////////////////////////////////////////////////////////////////
453
454 // XXX XXX XXX : Attention : we can not factorize more... the code is not the same
455 if (ncomp_ch_transporte == 1)
456 {
457 for (j=0; j<dimension; j++)
458 {
459 xm = 0.5 *(coord(scom,j)+xv(num3,j));
460 if (psc >= 0)
461 {
462 if (poly1==-1)
463 fluxsom(0) += gradient_elem(poly,0,j)*(coord(scom,j)-xm);
464 else
465 fluxsom(0) += (teta*gradient_elem(poly,0,j) + (1.- teta)*gradient_elem(poly1,0,j))*(coord(scom,j)-xm);
466 }
467 else
468 {
469 if (poly2==-1)
470 fluxsom(0) += gradient_elem(poly,0,j)*(coord(scom,j)-xm);
471 else
472 fluxsom(0) += (teta*gradient_elem(poly,0,j) + (1.- teta)*gradient_elem(poly2,0,j))*(coord(scom,j)-xm);
473 }
474 }
475 fluxsom(0) += flux(0);
476 fluxsom(0) *= psc;
477 }
478 else
479 {
480 for (comp0=0; comp0<ncomp_ch_transporte; comp0++)
481 {
482 fluxsom(comp0) = flux(comp0);
483 for (j=0; j<dimension; j++)
484 {
485 xm = 0.5 *(coord(scom,j)+xv(num3,j));
486 if (psc >= 0)
487 {
488 if (poly1==-1)
489 fluxsom(comp0) += gradient_elem(poly,comp0,j)*(coord(scom,j)-xm);
490 else
491 fluxsom(comp0) += (teta*gradient_elem(poly,comp0,j) + (1.-teta)*gradient_elem(poly1,comp0,j))*(coord(scom,j)-xm);
492 }
493 else
494 {
495 if (poly2==-1)
496 fluxsom(comp0) += gradient_elem(poly,comp0,j)*(coord(scom,j)-xm);
497 else
498 fluxsom(comp0) += (teta*gradient_elem(poly,comp0,j) + (1.-teta)*gradient_elem(poly2,comp0,j))*(coord(scom,j)-xm);
499 }
500 }
501 fluxsom(comp0) *= psc;
502 }
503 }
504
505 ////////////////////////////////////////////////////////////////////////////
506 // process the centre of gravity
507 ////////////////////////////////////////////////////////////////////////////
508
509 // XXX XXX XXX : Attention : we can not factorize more... the code is not the same
510 if (ncomp_ch_transporte == 1)
511 {
512 for (j=0; j<dimension; j++)
513 {
514 xm = 0.5 *(coord(scom,j)+xv(num3,j));
515 if (psc >= 0)
516 {
517 if (poly1==-1)
518 fluxg(0) += gradient_elem(poly,0,j)*(xg(poly,j)-xm);
519 else
520 fluxg(0) += (teta*gradient_elem(poly,0,j) + (1.- teta)*gradient_elem(poly1,0,j))*(xg(poly,j)-xm);
521 }
522
523 else
524 {
525 if (poly2==-1)
526 fluxg(0) += gradient_elem(poly,0,j)*(xg(poly,j)-xm);
527 else
528 fluxg(0) += (teta*gradient_elem(poly,0,j) + (1.- teta)*gradient_elem(poly2,0,j))*(xg(poly,j)-xm);
529 }
530 }
531
532 fluxg(0) += flux(0);
533 fluxg(0) *= psc;
534 }
535 else
536 {
537 for (comp0=0; comp0<ncomp_ch_transporte; comp0++)
538 {
539 fluxg(comp0) = flux(comp0);
540 for (j=0; j<dimension; j++)
541 {
542 xm = 0.5 *(coord(scom,j)+xv(num3,j));
543 if (psc >= 0)
544 {
545 if (poly1==-1)
546 fluxg(comp0) += gradient_elem(poly,comp0,j)*(xg(poly,j)-xm);
547 else
548 fluxg(comp0) += (teta*gradient_elem(poly,comp0,j) + (1.-teta)*gradient_elem(poly1,comp0,j))*(xg(poly,j)-xm);
549 }
550
551 else
552 {
553 if (poly2==-1)
554 fluxg(comp0) += gradient_elem(poly,comp0,j)*(xg(poly,j)-xm);
555 else
556 fluxg(comp0) += (teta*gradient_elem(poly,comp0,j) + (1.-teta)*gradient_elem(poly2,comp0,j))*(xg(poly,j)-xm);
557 }
558 }
559 fluxg(comp0) *= psc;
560 }
561 }
562 //////////////////////////////////////////////////////////////////////////////
563 // Integration of u.n.flux
564 /////////////////////////////////////////////////////////////////////////////
565 for (comp0=0; comp0<ncomp_ch_transporte; comp0++)
566 {
567 resu(num10,comp0) -= ( 0.5*(fluxsom(comp0)+fluxg(comp0)) );
568 resu(num20,comp0) += ( 0.5*(fluxsom(comp0)+fluxg(comp0)) );
569 }
570 }
571 }
572 } // end of the loop
573
574 // Process joint elements of thickness 1
575 for (poly=0; poly<nb_elem_tot; poly++)
576 {
577 // Check if a face of the polyhedron is a joint face
578 for (face_adj=0; face_adj<nfac; face_adj++)
579 if(face_adj<nb_faces) break;
580 if(face_adj<nfac)
581 {
582 rang = rang_elem_non_std(poly);
583 if (rang==-1)
584 itypcl=0;
585 else
586 itypcl=domaine_Cl_VEF.type_elem_Cl(rang);
587
588 // compute the face indices of the polyhedron
589 for (face_adj=0; face_adj<nfac; face_adj++)
590 {
591 face(face_adj)= elem_faces(poly,face_adj);
592 //Cerr << "the faces of the element are: " << face(face_adj) << finl;
593 }
594
595 int scom;
596 DoubleVect rx0(dimension);
597
598 // compute velocity at the vertices of the polyhedra
599 for (j=0; j<dimension; j++)
600 {
601 vs(j) = la_vitesse.valeurs()(face(0),j)*porosite_face(face(0));
602 for (i=1; i<nfac; i++)
603 vs(j)+= la_vitesse.valeurs()(face(i),j)*porosite_face(face(j));
604 }
605 int ncomp;
606 for (j=0; j<nsom; j++)
607 {
608 num_som = domaine.sommet_elem(poly,j);
609 for (ncomp=0; ncomp<dimension; ncomp++)
610 vsom(j,ncomp) = la_vitesse.valeur_a_sommet_compo(num_som,poly,ncomp);
611 }
612 // compute the velocity at the centre of gravity
613
614 domaine_VEF.type_elem().calcul_vc(face,vc,vs,vsom,vitesse(),itypcl,porosite_face);
615
616
617 // Loop over facets of the non-standard polyhedron:
618
619 for (fa7=0; fa7<nfa7; fa7++)
620 {
621 //Cerr << "the facet being studied is " << fa7 << finl;
622 // fa7 separates num1 and num2. num3 is the third face (2D).
623
624 num10 = face(KEL(0,fa7));
625 num20 = face(KEL(1,fa7));
626 num3 = face(KEL(2,fa7));
627
628 // Determine the neighbouring elements at faces num1 and num2
629
630 poly1 = face_voisins(num10,0);
631 if (poly1==poly)
632 {
633 poly1 = face_voisins(num10,1);
634 }
635
636 poly2 = face_voisins(num20,0);
637 if (poly2==poly)
638 {
639 poly2 = face_voisins(num20,1);
640 }
641
642 scom = les_Polys(poly,KEL(2,fa7));
643
644 // compute rx0, distance between the midpoints of 'num i'
645
646 for (i=0; i<dimension; i++)
647 rx0(i) = xv(num20,i)-xv(num10,i);
648
649 // facet normals
650
651 if (rang==-1)
652 for (i=0; i<dimension; i++)
653 cc[i] = facette_normales(poly, fa7, i);
654 else
655 for (i=0; i<dimension; i++)
656 cc[i] = normales_facettes_Cl(rang,fa7,i);
657
658 /////////////////////////////////////////////////////////////////////////
659 // Process the point where velocity = 0.5(vitsommet + vitmilieu)
660 /////////////////////////////////////////////////////////////////////////
661
662 for (i=0; i<nb_som_facette-1; i++)
663 {
664 //////////////////////////////////////////////////////////////////////////
665 //Determine PhiIJ at the midpoint between the vertex and the midpoint of num3
666 /////////////////////////////////////////////////////////////////////////
667
668 psc = 0;
669 for (j=0; j<dimension; j++)
670 psc+=((vsom(KEL(i+2,fa7),j) + la_vitesse.valeurs()(num3,j) * porosite_face(num3)))*cc[j];
671 psc *=0.5;
672 convkschemas(K,ncomp_ch_transporte,dimension,poly,poly1,poly2,num10,num20,psc,transporte,
673 fluent_,flux,rx0,gradient_elem);
674
675
676 ////////////////////////////////////////////////////////////////////////////////////////////////////////
677 //Gradient limiter. Computed at the same time as the flux.
678 // gradient(K0) = teta*gradient(K0)+ (1-teta)*gradient(K1 or K2)
679 ////////////////////////////////////////////////////////////////////////////////////////////////////////
680
681 double teta = 0.5;
682
683 /////////////////////////////////////////////////////////////////////////
684 // Process the vertices that are also vertices of the polyhedron
685 /////////////////////////////////////////////////////////////////////////
686
687 // XXX XXX XXX : Attention : we can not factorize more... the code is not the same
688 if (ncomp_ch_transporte == 1)
689 {
690 for (j=0; j<dimension; j++)
691 {
692 xm = 0.5 *(coord(scom,j)+xv(num3,j));
693 if (psc >= 0)
694 {
695 if (poly1==-1)
696 fluxsom(0) += gradient_elem(poly,0,j)*(coord(scom,j)-xm);
697 else
698 fluxsom(0) += (teta*gradient_elem(poly,0,j) + (1.- teta)*gradient_elem(poly1,0,j))*(coord(scom,j)-xm);
699 }
700 else
701 {
702 if (poly2==-1)
703 fluxsom(0) += gradient_elem(poly,0,j)*(coord(scom,j)-xm);
704 else
705 fluxsom(0) += (teta*gradient_elem(poly,0,j) + (1.- teta)*gradient_elem(poly2,0,j))*(coord(scom,j)-xm);
706 }
707 }
708 fluxsom(0) += flux(0);
709 fluxsom(0) *= psc;
710 }
711 else
712 {
713 for (comp0=0; comp0<ncomp_ch_transporte; comp0++)
714 {
715 fluxsom(comp0) = flux(comp0);
716 for (j=0; j<dimension; j++)
717 {
718 xm = 0.5 *(coord(scom,j)+xv(num3,j));
719 if (psc >= 0)
720 {
721 if (poly1==-1)
722 fluxsom(comp0) += gradient_elem(poly,comp0,j)*(coord(scom,j)-xm);
723 else
724 fluxsom(comp0) += (teta*gradient_elem(poly,comp0,j) + (1.-teta)*gradient_elem(poly1,comp0,j))*(coord(scom,j)-xm);
725 }
726 else
727 {
728 if (poly2==-1)
729 fluxsom(comp0) += gradient_elem(poly,comp0,j)*(coord(scom,j)-xm);
730 else
731 fluxsom(comp0) += (teta*gradient_elem(poly,comp0,j) + (1.-teta)*gradient_elem(poly2,comp0,j))*(coord(scom,j)-xm);
732 }
733 }
734 fluxsom(comp0) *= psc;
735 }
736 }
737
738 ////////////////////////////////////////////////////////////////////////////
739 // Process the center of gravity
740 ////////////////////////////////////////////////////////////////////////////
741
742 // XXX XXX XXX : Attention : we can not factorize more... the code is not the same
743 if (ncomp_ch_transporte == 1)
744 {
745 for (j=0; j<dimension; j++)
746 {
747 xm = 0.5 *(coord(scom,j)+xv(num3,j));
748 if (psc >= 0)
749 {
750 if (poly1==-1)
751 fluxg(0) += gradient_elem(poly,0,j)*(xg(poly,j)-xm);
752 else
753 fluxg(0) += (teta*gradient_elem(poly,0,j) + (1.- teta)*gradient_elem(poly1,0,j))*(xg(poly,j)-xm);
754 }
755 else
756 {
757 if (poly2==-1)
758 fluxg(0) += gradient_elem(poly,0,j)*(xg(poly,j)-xm);
759 else
760 fluxg(0) += (teta*gradient_elem(poly,0,j) + (1.- teta)*gradient_elem(poly2,0,j))*(xg(poly,j)-xm);
761 }
762 }
763 fluxg(0) += flux(0);
764 fluxg(0) *= psc;
765 }
766 else
767 {
768 for (comp0=0; comp0<ncomp_ch_transporte; comp0++)
769 {
770 fluxg(comp0) = flux(comp0);
771 for (j=0; j<dimension; j++)
772 {
773 xm = 0.5 *(coord(scom,j)+xv(num3,j));
774 if (psc >= 0)
775 {
776 if (poly1==-1)
777 fluxg(comp0) += gradient_elem(poly,comp0,j)*(xg(poly,j)-xm);
778 else
779 fluxg(comp0) += (teta*gradient_elem(poly,comp0,j) + (1.-teta)*gradient_elem(poly1,comp0,j))*(xg(poly,j)-xm);
780 }
781 else
782 {
783 if (poly2==-1)
784 fluxg(comp0) += gradient_elem(poly,comp0,j)*(xg(poly,j)-xm);
785 else
786 fluxg(comp0) += (teta*gradient_elem(poly,comp0,j) + (1.-teta)*gradient_elem(poly2,comp0,j))*(xg(poly,j)-xm);
787 }
788 }
789 fluxg(comp0) *= psc;
790 }
791 }
792
793 //////////////////////////////////////////////////////////////////////////////
794 // Integration of u.n.flux
795 /////////////////////////////////////////////////////////////////////////////
796 for (comp0=0; comp0<ncomp_ch_transporte; comp0++)
797 {
798 resu(num10,comp0) -= ( 0.5*(fluxsom(comp0)+fluxg(comp0)) );
799 resu(num20,comp0) += ( 0.5*(fluxsom(comp0)+fluxg(comp0)) );
800 }
801 }
802 }
803 }
804 } // end of the loop
805 int voisine;
806 nb_faces_perio = 0;
807 double diff1,diff2;
808
809 // Dimensioning the array of convective fluxes at the boundary
810 // of the computational domain
811 DoubleTab& flux_b = flux_bords_;
812 flux_b.resize(domaine_VEF.nb_faces_bord(),ncomp_ch_transporte);
813 flux_b = 0.;
814
815 // Loop over the boundaries to process the boundary conditions
816 // a convection term is included for Neumann_sortie_libre boundary conditions only
817
818 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
819 {
820 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
821
822 if (sub_type(Neumann_sortie_libre,la_cl.valeur()))
823 {
824 const Neumann_sortie_libre& la_sortie_libre = ref_cast(Neumann_sortie_libre,la_cl.valeur());
825 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
826 int num1 = le_bord.num_premiere_face();
827 int num2 = num1 + le_bord.nb_faces();
828 for (num_face=num1; num_face<num2; num_face++)
829 {
830 psc =0;
831 for (i=0; i<dimension; i++)
832 psc += la_vitesse.valeurs()(num_face,i)*face_normales(num_face,i)*porosite_face(num_face);
833 if (psc>0)
834 for (i=0; i<ncomp_ch_transporte; i++)
835 {
836 resu(num_face,i) -= psc*transporte(num_face,i);
837 flux_b(num_face,i) -= psc*transporte(num_face,i);
838 }
839 else
840 {
841 for (i=0; i<ncomp_ch_transporte; i++)
842 {
843 resu(num_face,i) -= psc*la_sortie_libre.val_ext(num_face-num1,i);
844 flux_b(num_face,i) -= psc*la_sortie_libre.val_ext(num_face-num1,i);
845 }
846 fluent_(num_face) -= psc;
847 }
848 }
849 }
850 else if (sub_type(Periodique,la_cl.valeur()))
851 {
852 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
853 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
854 int num1 = le_bord.num_premiere_face();
855 int num2 = num1 + le_bord.nb_faces();
856 IntVect fait(le_bord.nb_faces());
857 fait = 0;
858 for (num_face=num1; num_face<num2; num_face++)
859 {
860 if (fait[num_face-num1] == 0)
861 {
862 voisine = la_cl_perio.face_associee(num_face-num1) + num1;
863 for (int comp=0; comp<ncomp_ch_transporte; comp++)
864 {
865 diff1 = resu(num_face,comp)-tab(nb_faces_perio,comp);
866 diff2 = resu(voisine,comp)-tab(nb_faces_perio+voisine-num_face,comp);
867 resu(voisine,comp) += diff1;
868 resu(num_face,comp) += diff2;
869 flux_b(voisine,comp) += diff1;
870 flux_b(num_face,comp) += diff2;
871 }
872 fait[num_face-num1]= 1;
873 fait[voisine-num1] = 1;
874 }
875 nb_faces_perio++;
876 }
877 }
878 }
879 modifier_flux(*this);
880 return resu;
881}
Class Champ_Inc_base.
DoubleTab & valeurs() override
Returns the array of field values at the current time.
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
virtual void creer_tableau_elements(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
Creates a parallel array of values at elements.
Definition Domaine.cpp:850
int type_elem_Cl(int i) const
DoubleTab & normales_facettes_Cl()
class Domaine_Cl_dis_base Domaine_Cl_dis_base objects represent discretized boundary conditions
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
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
double xv(int num_face, int k) const
Definition Domaine_VF.h:76
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
double xp(int num_elem, int k) const
Definition Domaine_VF.h:77
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
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
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_VEF_base
void associer(const Domaine_dis_base &, const Domaine_Cl_dis_base &, const Champ_Inc_base &) override
const Champ_Inc_base & vitesse() const
class Op_Conv_kschemas_VEF
void associer(const Domaine_dis_base &, const Domaine_Cl_dis_base &, const Champ_Inc_base &) override
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
static bool is_parallel()
Definition Process.cpp:108
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
Base class for output streams.
Definition Sortie.h:52
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
int line_size() const
Definition TRUSTVect.tpp:67
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")