TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Op_Conv_Centre_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_Centre_old_VEF_Face.h>
17#include <Periodique.h>
18#include <Neumann_sortie_libre.h>
19
20Implemente_instanciable(Op_Conv_Centre_old_VEF_Face,"Op_Conv_Centre_old_VEF_P1NC",Op_Conv_VEF_base);
21// XD convection_centre_old convection_deriv centre_old NO_BRACE Only for VEF discretization.
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//
40// Functions of class Op_Conv_Centre_old_VEF_Face
41//
43 const Domaine_Cl_dis_base& domaine_cl_dis,
44 const Champ_Inc_base& ch_transporte)
45{
46 const Domaine_VEF& zvef = ref_cast(Domaine_VEF,domaine_dis);
47 const Domaine_Cl_VEF& zclvef = ref_cast(Domaine_Cl_VEF,domaine_cl_dis);
48 const Champ_Inc_base& le_ch_transporte = ref_cast(Champ_Inc_base,ch_transporte);
49
50 le_dom_vef = zvef;
51 la_zcl_vef = zclvef;
52 champ_transporte = le_ch_transporte;
53
54 fluent_.reset();
55 le_dom_vef->creer_tableau_faces(fluent_);
56}
57
58DoubleTab& Op_Conv_Centre_old_VEF_Face::ajouter(const DoubleTab& transporte,
59 DoubleTab& resu) const
60{
61 const Domaine_Cl_VEF& domaine_Cl_VEF = la_zcl_vef.valeur();
62 const Domaine_VEF& domaine_VEF = le_dom_vef.valeur();
63 // const Champ_Inc_base& le_transporte = champ_transporte.valeur();
64 const Champ_Inc_base& la_vitesse =vitesse_.valeur();
65
66 const IntTab& elem_faces = domaine_VEF.elem_faces();
67 const DoubleTab& face_normales = domaine_VEF.face_normales();
68 const auto& facette_normales = domaine_VEF.facette_normales();
69 // const DoubleVect& volumes_entrelaces = domaine_VEF.volumes_entrelaces();
70 const Domaine& domaine = domaine_VEF.domaine();
71 // const int nb_faces = domaine_VEF.nb_faces();
72 const int nfa7 = domaine_VEF.type_elem().nb_facette();
73 // const int nb_elem = domaine_VEF.nb_elem();
74 const int nb_elem_tot = domaine_VEF.nb_elem_tot();
75 const IntVect& rang_elem_non_std = domaine_VEF.rang_elem_non_std();
76
77
78 const DoubleTab& normales_facettes_Cl = domaine_Cl_VEF.normales_facettes_Cl();
79 // const DoubleVect& volumes_entrelaces_Cl = domaine_Cl_VEF.volumes_entrelaces_Cl();
80
81 const DoubleVect& porosite_face = equation().milieu().porosite_face();
82
83 int nfac = domaine.nb_faces_elem();
84 int nsom = domaine.nb_som_elem();
85 int nb_som_facette = domaine.type_elem()->nb_som_face();
86
87
88 // For the convection treatment, standard polyhedra (not "seeing" boundary conditions)
89 // are distinguished from non-standard polyhedra (having at least one boundary face).
90 // A standard polyhedron has n facets on which the convection scheme is applied.
91 // For a non-standard polyhedron with Dirichlet boundary conditions, part of its
92 // facets are carried by the boundary faces.
93 // In short, for a polyhedron the convection treatment depends on the type
94 // (triangle, tetrahedron ...) and the number of Dirichlet faces.
95
96 double psc;
97 double flux;
98 int poly,face_adj,fa7,i,j,comp0,n_bord;
99 int num_face, rang ,itypcl;
100 int num10, num20, num_som;
101
102 int ncomp_ch_transporte;
103 if (transporte.nb_dim() == 1)
104 ncomp_ch_transporte=1;
105 else
106 ncomp_ch_transporte= transporte.dimension(1);
107
108 // MODIF SB on 10/09/03
109 // For the following 3 elements, there are as many vertices as faces
110 // making up the geometric element.
111 // Problem with hexahedra: 8 vertices and 6 faces, so use of the array
112 // face[i] no longer works.
113 // The chosen method to avoid computing the velocity at vertices without
114 // shape functions is therefore not applicable;
115 // for the hexa we have no access to the face.
116 // The Face=>vertices array exists but not the inverse.
117 // Too costly and for now porosities are not extended to hexahedra.
118
119 int istetra=0;
120 const Elem_VEF_base& type_elemvef= domaine_VEF.type_elem();
121 Nom nom_elem=type_elemvef.que_suis_je();
122 if ((nom_elem=="Tetra_VEF")||(nom_elem=="Tri_VEF"))
123 istetra=1;
124
125 IntVect face(nfac);
126 DoubleVect vs(dimension);
127 DoubleVect vc(dimension);
128 DoubleTab vsom(nsom,dimension);
129 DoubleVect cc(dimension);
130
131 // declaration for the transported field
132
133 DoubleVect ts(ncomp_ch_transporte);
134 DoubleVect tc(ncomp_ch_transporte);
135 DoubleTab tsom(nsom,ncomp_ch_transporte);
136
137
138 // Reset to zero the array used for
139 // the stability time step computation
140 fluent_ = 0;
141
142 // Special treatment for periodic faces
143
144 int nb_faces_perio = 0;
145 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
146 {
147 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
148 if (sub_type(Periodique,la_cl.valeur()))
149 {
150 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
151 int num1 = le_bord.num_premiere_face();
152 int num2 = num1 + le_bord.nb_faces();
153 for (num_face=num1; num_face<num2; num_face++)
154 nb_faces_perio++;
155 }
156 }
157
158 DoubleTab tab;
159 if (ncomp_ch_transporte == 1)
160 tab.resize(nb_faces_perio);
161 else
162 tab.resize(nb_faces_perio,ncomp_ch_transporte);
163
164 nb_faces_perio=0;
165 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
166 {
167 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
168 if (sub_type(Periodique,la_cl.valeur()))
169 {
170 // const Periodique& la_cl_perio = ref_cast(Periodique, la_cl.valeur());
171 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
172 int num1 = le_bord.num_premiere_face();
173 int num2 = num1 + le_bord.nb_faces();
174 for (num_face=num1; num_face<num2; num_face++)
175 {
176 if (ncomp_ch_transporte == 1)
177 tab(nb_faces_perio) = resu(num_face);
178 else
179 for (int comp=0; comp<ncomp_ch_transporte; comp++)
180 tab(nb_faces_perio,comp) = resu(num_face,comp);
181 nb_faces_perio++;
182 }
183 }
184 }
185
186
187 // Non-standard polyhedra are arranged in 2 groups in Domaine_VEF:
188 // - boundary and joint polyhedra
189 // - boundary and non-joint polyhedra
190 // Polyhedra are processed following the order in which they appear
191 // in the domain
192
193 // loop over polyhedra
194 const IntTab& KEL=domaine_VEF.type_elem().KEL();
195 for (poly=0; poly<nb_elem_tot; poly++)
196 {
197
198 rang = rang_elem_non_std(poly);
199 if (rang==-1)
200 itypcl=0;
201 else
202 itypcl=domaine_Cl_VEF.type_elem_Cl(rang);
203
204 // compute the face indices of the polyhedron
205 for (face_adj=0; face_adj<nfac; face_adj++)
206 face[face_adj]= elem_faces(poly,face_adj);
207
208 for (j=0; j<dimension; j++)
209 {
210 vs[j] = la_vitesse.valeurs()(face[0],j)*porosite_face(face[0]);
211 for (i=1; i<nfac; i++)
212 vs[j]+= la_vitesse.valeurs()(face[i],j)*porosite_face(face[i]);
213 }
214 // int ncomp;
215 if (istetra==1)
216 {
217 for (j=0; j<nsom; j++)
218 {
219 for (int ncomp=0; ncomp<Objet_U::dimension; ncomp++)
220 vsom(j,ncomp) =vs[ncomp] - Objet_U::dimension*la_vitesse.valeurs()(face[j],ncomp)*porosite_face(face[j]);
221 }
222 }
223 else
224 {
225 // to be valid with hexahedra
226 // Use the shape functions implemented in class Champs_P1_impl or Champs_Q1_impl
227 //int ncomp;
228 for (j=0; j<nsom; j++)
229 {
230 num_som = domaine.sommet_elem(poly,j);
231 for (int ncomp=0; ncomp<dimension; ncomp++)
232 {
233 vsom(j,ncomp) = la_vitesse.valeur_a_sommet_compo(num_som,poly,ncomp);
234 }
235 }
236 }
237
238 // compute vc
239 domaine_VEF.type_elem().calcul_vc(face,vc,vs,vsom,vitesse(),
240 itypcl,porosite_face);
241
242 // compute the transported field at the polyhedron vertices, tsom
243 if(ncomp_ch_transporte == 1)
244 {
245 ts[0]=transporte(face[0]);
246 for (i=1; i<nfac; i++)
247 ts[0]+= transporte(face[i]);
248
249 for (i=0; i<nsom; i++)
250 tsom(i,0) = ts[0] - dimension*transporte(face[i],0);
251 }
252 else
253 {
254 for (j=0; j<ncomp_ch_transporte; j++)
255 {
256 ts[j] = transporte(face[0],j);
257 for (i=1; i<nfac; i++)
258 ts[j]+= transporte(face[i],j);
259 }
260 for (i=0; i<nsom; i++)
261 for (j=0; j<ncomp_ch_transporte; j++)
262 tsom(i,j) = ts[j] - dimension*transporte(face[i],j);
263 }
264
265 // compute the transported field at the centre of gravity, tc
266
267 for (j=0; j<ncomp_ch_transporte; j++)
268 tc[j] = ts[j]/nfac;
269
270
271 // Loop over the facets of the non-standard polyhedron:
272
273 for (fa7=0; fa7<nfa7; fa7++)
274 {
275 num10 = face[KEL(0,fa7)];
276 num20 = face[KEL(1,fa7)];
277 if (rang==-1)
278 for (i=0; i<dimension; i++)
279 cc[i] = facette_normales(poly,fa7,i);
280 else
281 for (i=0; i<dimension; i++)
282 cc[i] = normales_facettes_Cl(rang,fa7,i);
283
284 // Apply the convection scheme at each vertex of the facet
285
286 // Treat the vertex/vertices that are also vertices of the polyhedron
287
288 int isom;
289 for (i=0; i<nb_som_facette-1; i++)
290 {
291 isom = KEL(i+2,fa7);
292 psc =0;
293 for (j=0; j<dimension; j++)
294 psc+= vsom(isom,j)*cc[j];
295 psc /= nb_som_facette;
296
297 if(psc >= 0)
298 fluent_[num20] += psc;
299 else
300 fluent_[num10] -= psc;
301
302 // write the flux
303 if (ncomp_ch_transporte == 1)
304 {
305 flux = tsom(isom,0)*psc;
306 resu(num10) -= flux;
307 resu(num20) += flux;
308 }
309 else
310 for (comp0=0; comp0<ncomp_ch_transporte; comp0++)
311 {
312 flux = tsom(isom,comp0)*psc;
313 resu(num10, comp0) -= flux;
314 resu(num20, comp0) += flux;
315 }
316 }
317
318
319 // Treat the vertex coinciding with the centre of gravity of the polyhedron
320
321 psc=0;
322 for (j=0; j<dimension; j++)
323 psc += vc[j]*cc[j];
324 psc /= nb_som_facette;
325
326 if(psc >= 0)
327 fluent_[num20] += psc;
328 else
329 fluent_[num10] -= psc;
330
331 // write the flux
332
333 if (ncomp_ch_transporte == 1)
334 {
335 flux = tc[0]*psc;
336 resu(num10) -= flux;
337 resu(num20) += flux;
338 }
339 else
340 for (comp0=0; comp0<ncomp_ch_transporte; comp0++)
341 {
342 flux = tc[comp0]*psc;
343 resu(num10, comp0) -= flux;
344 resu(num20, comp0) += flux;
345 }
346 }
347
348 } // end of loop
349
350 int voisine;
351 nb_faces_perio = 0;
352 double diff1,diff2;
353
354 // Sizing the array of convective fluxes at the domain boundary
355 DoubleTab& flux_b = flux_bords_;
356 flux_b.resize(domaine_VEF.nb_faces_bord(),ncomp_ch_transporte);
357 flux_b = 0.;
358
359 // Loop over boundaries to handle boundary conditions
360 // a convection term is taken into account only for
361 // Neumann_sortie_libre boundary conditions
362
363 for (n_bord=0; n_bord<domaine_VEF.nb_front_Cl(); n_bord++)
364 {
365
366 const Cond_lim& la_cl = domaine_Cl_VEF.les_conditions_limites(n_bord);
367
368 if (sub_type(Neumann_sortie_libre,la_cl.valeur()))
369 {
370 const Neumann_sortie_libre& la_sortie_libre = ref_cast(Neumann_sortie_libre,la_cl.valeur());
371 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
372 int num1 = le_bord.num_premiere_face();
373 int num2 = num1 + le_bord.nb_faces();
374 for (num_face=num1; num_face<num2; num_face++)
375 {
376 psc =0;
377 for (i=0; i<dimension; i++)
378 psc += la_vitesse.valeurs()(num_face,i)*face_normales(num_face,i)*porosite_face(num_face);
379 if (psc>0)
380 if (ncomp_ch_transporte == 1)
381 {
382 resu(num_face) -= psc*transporte(num_face);
383 flux_b(num_face,0) -= psc*transporte(num_face);
384 }
385 else
386 for (i=0; i<ncomp_ch_transporte; i++)
387 {
388 resu(num_face,i) -= psc*transporte(num_face,i);
389 flux_b(num_face,i) -= psc*transporte(num_face,i);
390 }
391 else
392 {
393 if (ncomp_ch_transporte == 1)
394 {
395 resu(num_face) -= psc*la_sortie_libre.val_ext(num_face-num1);
396 flux_b(num_face,0) -= psc*la_sortie_libre.val_ext(num_face-num1);
397 }
398 else
399 for (i=0; i<ncomp_ch_transporte; i++)
400 {
401 resu(num_face,i) -= psc*la_sortie_libre.val_ext(num_face-num1,i);
402 flux_b(num_face,i) -= psc*la_sortie_libre.val_ext(num_face-num1,i);
403 }
404 fluent_[num_face] -= psc;
405 }
406 }
407 }
408 else if (sub_type(Periodique,la_cl.valeur()))
409 {
410 const Periodique& la_cl_perio = ref_cast(Periodique,la_cl.valeur());
411 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
412 int num1 = le_bord.num_premiere_face();
413 int num2 = num1 + le_bord.nb_faces();
414 IntVect fait(le_bord.nb_faces());
415 fait = 0;
416 for (num_face=num1; num_face<num2; num_face++)
417 {
418 if (fait[num_face-num1] == 0)
419 {
420 voisine = la_cl_perio.face_associee(num_face-num1) + num1;
421
422 if (ncomp_ch_transporte == 1)
423 {
424 diff1 = resu(num_face)-tab(nb_faces_perio);
425 diff2 = resu(voisine)-tab(nb_faces_perio+voisine-num_face);
426 resu(voisine) += diff1;
427 resu(num_face) += diff2;
428 flux_b(voisine,0) += diff1;
429 flux_b(num_face,0) += diff2;
430 }
431 else
432 for (int comp=0; comp<ncomp_ch_transporte; comp++)
433 {
434 diff1 = resu(num_face,comp)-tab(nb_faces_perio,comp);
435 diff2 = resu(voisine,comp)-tab(nb_faces_perio+voisine-num_face,comp);
436 resu(voisine,comp) += diff1;
437 resu(num_face,comp) += diff2;
438 flux_b(voisine,comp) += diff1;
439 flux_b(num_face,comp) += diff2;
440 }
441
442 fait[num_face-num1]= 1;
443 fait[voisine-num1] = 1;
444 }
445 nb_faces_perio++;
446 }
447 }
448 }
449 modifier_flux(*this);
450 return resu;
451
452}
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
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
virtual double face_normales(int face, int comp) const
Definition Domaine_VF.h:47
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 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_Centre_old_VEF_Face
DoubleTab & ajouter(const DoubleTab &, DoubleTab &) const override
void associer(const Domaine_dis_base &, const Domaine_Cl_dis_base &, const Champ_Inc_base &) 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