TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Domaine_VDF.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 <Domaine_VDF.h>
17#include <Domaine_Cl_VDF.h>
18#include <Rectangle.h>
19#include <Hexaedre.h>
20#include <Faces_VDF.h>
21#include <Aretes.h>
22#include <Periodique.h>
23#include <Dirichlet_entree_fluide_leaves.h>
24#include <Neumann_sortie_libre.h>
25#include <EcrFicCollecte.h>
26#include <math.h>
27#include <TRUSTTrav.h>
28
29Implemente_instanciable(Domaine_VDF,"Domaine_VDF",Domaine_VF);
30
31//#define SORT_POUR_DEBOG
32
34{
36 os << "orientation_" << orientation_ << finl;
37 os << "nb_faces_X_" << nb_faces_X_ << finl;
38 os << "nb_faces_Y_" << nb_faces_Y_ << finl;
39 os << "nb_faces_Z_" << nb_faces_Z_ << finl;
40 os << "nb_aretes_" << nb_aretes_ << finl;
41 os << "nb_aretes_joint_" << nb_aretes_joint_ << finl;
42 os << "nb_aretes_coin_" << nb_aretes_coin_ << finl;
43 os << "nb_aretes_bord_" << nb_aretes_bord_ << finl;
44 os << "nb_aretes_mixtes_" << nb_aretes_mixtes_ << finl;
45 os << "nb_aretes_internes_" << nb_aretes_internes_ << finl;
46 Qdm_.ecrit(os << "Qdm : ");
47 os << h_x_ << " " << h_y_ << " " << h_z_ << finl;
48 return os;
49}
50
52{
54 is >> orientation_;
55 is >> nb_faces_X_;
56 is >> nb_faces_Y_;
57 is >> nb_faces_Z_;
58 is >> nb_aretes_;
59 is >> nb_aretes_joint_;
60 is >> nb_aretes_coin_;
61 is >> nb_aretes_bord_;
62 is >> nb_aretes_mixtes_;
63 is >> nb_aretes_internes_;
64 Qdm_.lit(is);
65 is >> h_x_ >> h_y_ >> h_z_;
66 return is;
67}
68/*! @brief Returns a newly allocated Faces_VDF object.
69 *
70 * @return Pointer to the newly created Faces_VDF instance.
71 */
73{
74 Faces_VDF* les_faces_vdf=new(Faces_VDF);
75 return les_faces_vdf;
76}
77
78/*! Override to do nothing. Not necessary for VDF.
79 */
83
84/*! @brief Override. Compute sorting key so that internal faces are sorted by their orientation first (X, Y, Z)
85 */
86void Domaine_VDF::compute_sort_key(Faces& les_faces, IntTab& sort_key)
87{
88 // Compute the orientation of real faces
89 Faces_VDF& les_faces_vdf=ref_cast(Faces_VDF, les_faces);
90 les_faces_vdf.calculer_orientation(orientation_, nb_faces_X_, nb_faces_Y_, nb_faces_Z_);
91
92 const int nb_faces_front = domaine().nb_faces_frontiere();
93
94 // Build an integer key for sorting the faces:
95 // orientation * nb_faces + face_index
96 // Sorting by ascending order of this key sorts by orientation
97 // while preserving the original order of faces with the same orientation
98 const int nb_faces = les_faces_vdf.nb_faces();
99
100 nb_faces_std_ = 0;
101 sort_key.resize(nb_faces, 2);
102 // Do not sort the boundary faces, which remain at the beginning:
103 for (int i = 0; i < nb_faces_front; i++)
104 {
105 sort_key(i, 0) = i;
106 sort_key(i, 1) = i;
107 }
108
109 for (int i=nb_faces_front; i < nb_faces; i++)
110 {
111 const int ori = orientation_[i];
112 sort_key(i, 0) = ori * nb_faces + i;
113 sort_key(i, 1) = i;
114 }
115 nb_faces_std_ = nb_faces - nb_faces_front; // not as funny as in VEF ... :-)
116}
117
118/*! @brief Override to also renumber orientation_ member.
119 */
120void Domaine_VDF::renumber_faces(Faces& les_faces, IntTab& sort_key)
121{
122 Domaine_VF::renumber_faces(les_faces, sort_key);
123
124 const int nb_faces_front = domaine().nb_faces_frontiere();
125 const int nb_faces = les_faces.nb_faces();
126
127 IntVect old_orien(orientation_);
128 for (int i=nb_faces_front; i < nb_faces; i++)
129 {
130 const int idx = sort_key(i, 1);
131 orientation_[i] = old_orien[idx];
132 }
133}
134
135
136/*! @brief Calls Domaine_VF::discretiser(), computes element gravity centers,
137 *
138 * @brief fills element/face connectivities, reorders face/element connectivities
139 * so that el1 is on the left and el2 on the right,
140 * computes volumetric and surface porosities,
141 * generates edges, and computes mesh steps.
142 *
143 */
145{
147
148 Domaine& domaine_geom=domaine();
149
150 // Check the consistency between the geometric element and the discretization
151
152 const Elem_geom_base& elem_geom = domaine_geom.type_elem().valeur();
153
154 if (dimension == 2)
155 {
156 if (!sub_type(Rectangle,elem_geom))
157 {
158 Cerr << " The geometric element type " << elem_geom.que_suis_je() << " is incorrect" << finl;
159 Cerr << " Only the Rectangle and Rectangle_Axi types are compatible with VDF discretization in dimension 2" << finl;
160 exit();
161 }
162 }
163 else if (dimension == 3)
164 {
165 if (!sub_type(Hexaedre,elem_geom))
166 {
167 Cerr << " The geometric element type " << elem_geom.que_suis_je() << " is incorrect" << finl;
168 Cerr << " Only the Hexaedre and Hexaedre_Axi types are compatible with VDF discretization in dimension 3" << finl;
169 exit();
170 }
171 }
172 // Compute the orientation of virtual faces
173 // Note BM: for compatibility with version 1.5, orientation_
174 // has no virtual space.
175 MD_Vector md_nul;
176 creer_tableau_faces(orientation_);
177 orientation_.echange_espace_virtuel();
178 orientation_.set_md_vector(md_nul); // Detach the parallel structure
179
180 // Apply the VDF convention on face_voisin:
181 // The element face_voisin(i,0) must have an "ori" coordinate smaller than the face
182 // and the element face_voisin(i,1) must have a larger coordinate.
183 {
184 const int nbr_faces_tot = face_voisins_.dimension_tot(0);
185 for (int i_face = 0; i_face < nbr_faces_tot; i_face++)
186 {
187 const int elem0 = face_voisins_(i_face, 0);
188 const int elem1 = face_voisins_(i_face, 1);
189 const int ori = orientation_[i_face];
190 const double x_face = xv(i_face, ori);
191 double delta = 0.;
192 // Element 0 must have an "ori" coordinate smaller than the face
193 // and element 1 must have a larger coordinate.
194 if (elem0 >= 0)
195 {
196 delta = x_face - xp(elem0, ori);
197 }
198 else
199 {
200 assert(elem1 >= 0); // Otherwise, critical error: neighboring elements not filled in
201 delta = xp(elem1, ori) - x_face;
202 }
203 if (delta < 0)
204 {
205 // Swap the two elements
206 face_voisins_(i_face, 0) = elem1;
207 face_voisins_(i_face, 1) = elem0;
208 }
209 }
210 }
211
213 genere_aretes();
214 calcul_h();
215 remplir_face_normales();
216 Cerr << "The Domaine_VDF object has been filled successfully " << finl;
217
218}
219
220void Domaine_VDF::remplir_face_normales()
221{
222 // Fill the face_normales_ array;
223 // Note: the face_voisins array is not exactly a distributed array. A face does not have its two neighbors in the
224 // same order on all processors that own the face.
225 // Therefore the face normal can change direction from one processor to another, including for joint faces.
226 face_normales_ = xv_; // already has // structure
227 face_normales_ = 0.;
228
229 for (int f = 0; f < nb_faces_tot(); f++)
230 {
231 int ori = orientation(f);
232 face_normales_(f,ori) = face_surfaces(f);
233 }
234}
235
236/*! @brief Fills the staggered volumes (volumes entrelaces).
237 *
238 */
240{
241 Cerr << "Computing staggered volumes" << finl;
245
246 const int nb_faces_front = premiere_face_int();
247 const int nbf = nb_faces();
248 for (int num_face = 0; num_face<nbf; num_face++)
249 {
250 const double f = (num_face < nb_faces_front) ? 2. : 1.;
251 for (int dir = 0; dir < 2; dir ++)
252 {
253 int elem = face_voisins_(num_face, dir);
254 if (elem != -1)
255 {
256 if ((axi) && (orientation_[num_face]==0))
257 volumes_entrelaces_dir_(num_face, dir) = f * 0.5 * xv_(num_face, 0) * volumes(elem) / xp(elem, 0);
258 else if ((bidim_axi) && (orientation_[num_face]==0))
259 volumes_entrelaces_dir_(num_face, dir) = volume_entrelace_axi(std::fabs(xv(num_face, 0)), std::fabs(xp(elem, 0)), dim_elem(elem, 1));
260 else
261 volumes_entrelaces_dir_(num_face, dir) = f * 0.5 * volumes(elem);
262
263 volumes_entrelaces_[num_face] += volumes_entrelaces_dir_(num_face, dir);
264 }
265 }
266 }
267 volumes_entrelaces_.echange_espace_virtuel();
268 volumes_entrelaces_dir_.echange_espace_virtuel();
269}
270
271static inline int face_vois(const Domaine_VDF& zvdf, const Domaine& domaine, int face, int i)
272{
273 int elem=zvdf.face_voisins(face,i);
274 if(elem==-1)
275 {
276 face=domaine.face_bords_interne_conjuguee(face);
277 if(face!=-1)
278 {
279 elem=zvdf.face_voisins(face,i);
280 assert(elem!=-1);
281 }
282 }
283 return elem;
284}
285
286/*! @brief Generates the edge connectivity arrays.
287 *
288 */
289void Domaine_VDF::genere_aretes()
290{
291 Cerr << "Generating edges" << finl;
292
293 Domaine& mon_dom=domaine();
294 // int nb_poly = le_dom.nb_elem();
295 int nb_poly_tot = mon_dom.nb_elem_tot();
296 // Estimate with upper bound on the number of edges: nb_aretes_plus
297 nb_aretes_=-1; // cf Aretes::affecter
298 int nb_aretes_plus=-1;
299 if (dimension == 2)
300 nb_aretes_plus = mon_dom.nb_som();
301 else if (dimension == 3)
302 nb_aretes_plus = mon_dom.nb_som()*3;
303 Cerr << "Creating edges " << finl;
304 Aretes les_aretes(nb_aretes_plus);
305
306 // Loop over all elements:
307 int el1, el2, el3, el4;
308 int face12, face13, face34, face24;
309
310 int nb_dir;
311 if(dimension==2) nb_dir=1;
312 else nb_dir=3;
313 IntVect gauche(nb_dir);
314 gauche(0)=0;
315 if(dimension==3)
316 {
317 gauche(1)=0;
318 gauche(2)=1;
319 }
320 IntVect droite(nb_dir);
321 droite(0)=dimension;
322 if(dimension==3)
323 {
324 droite(1)=dimension;
325 droite(2)=dimension+1;
326 }
327 IntVect haut(nb_dir);
328 haut(0)=dimension+1;
329 if(dimension==3)
330 {
331 haut(1)=dimension+2;
332 haut(2)=dimension+2;
333 }
334 IntVect bas(nb_dir);
335 bas(0)=1;
336 if(dimension==3)
337 {
338 bas(1)=2;
339 bas(2)=2;
340 }
341
342 int coin=-1;
343 int bord=0;
344 int mixte=1;
345 int interne=2;
346 // Detection of plates (2 boundary faces overlap):
347 IntVect est_une_plaque(nb_faces());
348 creer_tableau_faces(est_une_plaque);
349 est_une_plaque=0;
350 // Loop over boundary faces
351 ArrOfDouble P1(3), P2(3);
352 P1=0;
353 P2=0;
354 double eps = 10.0*Objet_U::precision_geom;
355 for (int face=0; face<premiere_face_int(); face++)
356 {
357 int ori = orientation(face);
358 for (int i = 0; i < dimension; i++)
359 {
360 P1[i] = xv(face, i) + (ori == i ? eps : 0);
361 P2[i] = xv(face, i) - (ori == i ? eps : 0);
362 }
363 int elem1 = domaine().chercher_elements(P1[0], P1[1], P1[2]);
364 int elem2 = domaine().chercher_elements(P2[0], P2[1], P2[2]);
365 if (elem1 >= 0 && elem2 >= 0 && elem1 != elem2)
366 {
367 // Find 2 points P1 and P2 in cells so:
368 est_une_plaque(face) = 1;
369 //Journal() << "We detect an internal boundary on face " << face << " between elements " << elem1 << " and " << elem2 << finl;
370 }
371 }
372 est_une_plaque.echange_espace_virtuel();
373
374 for(int dir=0; dir<nb_dir; dir++)
375 for (el1=0; el1<nb_poly_tot; el1++)
376 {
377 // Generate the edge at the top-right of el1
378 face12=elem_faces(el1,droite(dir));
379 face13=elem_faces(el1,haut(dir));
380
381 el2=face_vois(*this, mon_dom, face12, 1);
382
383 if(el2>-1)
384 face24=elem_faces(el2,haut(dir));
385 else
386 face24=-1;
387
388 el3=face_vois(*this, mon_dom, face13, 1);
389
390 if(el3>-1)
391 face34=elem_faces(el3,droite(dir));
392 else
393 face34=-1;
394
395 if( (el2>-1) && (el3>-1))
396 el4=face_vois(*this, mon_dom, face24, 1);
397 else if((el2>-1))
398 el4=face_vois(*this, mon_dom, face24, 1);
399 else if((el3>-1))
400 el4=face_vois(*this, mon_dom, face34, 1);
401 else
402 el4=-1;
403
404 if ( (el2==-1) && (el4>=0) )
405 face24=elem_faces(el4,bas(dir));
406 if ( (el3==-1) && (el4>=0) )
407 face34=elem_faces(el4,gauche(dir));
408
409 const int nb_f = nb_faces();
410 if (el2 > -1 && el3 > -1 && el4 > -1) // internal edge
411 les_aretes.affecter(nb_aretes_, dir, interne, nb_f, face13, face24, face12, face34, est_une_plaque);
412 else if ( (el3 > -1 && el4 > -1) ||
413 (el2 > -1 && el4 > -1) ||
414 (el2 > -1 && el3 > -1) ) // mixed edge
415 les_aretes.affecter(nb_aretes_, dir, mixte, nb_f, face13, face24, face12, face34, est_une_plaque);
416 else if (el2 > -1) // boundary edge
417 les_aretes.affecter(nb_aretes_, dir, bord, nb_f, face13, face24, face12, 1, est_une_plaque);
418 else if (el3 > -1) // boundary edge
419 les_aretes.affecter(nb_aretes_, dir, bord, nb_f, face12, face34, face13, 1, est_une_plaque);
420 else // corner edge
421 les_aretes.affecter(nb_aretes_, dir, coin, nb_f, face13, face24, face12, face34, est_une_plaque);
422 //Cerr << "elements_haut_droit " << el1 << " " << el2 << " " << el3 << " " << el4 << finl;
423 //Journal() << "Provisoire faces arete: " << face12 << " " << face13 << " " << face24 << " " << face34 << finl;
424
425 // For corners or boundaries:
426 face13 = elem_faces(el1, bas(dir));
427 el3 = face_vois(*this, mon_dom, face13, 0);
428 if (el3 < 0) // Generate the edge at the bottom-right of el1
429 // if the cell below el1 does not exist
430 {
431 if (el2 >= 0)
432 {
433 face24 = elem_faces(el2, bas(dir));
434 el4 = face_vois(*this, mon_dom, face24, 0);
435 if (el4 < 0) // boundary edge
436 les_aretes.affecter(nb_aretes_, dir, bord, nb_f, face13, face24, face12, -1, est_une_plaque);
437 else // mixed edge
438 {
439 face34 = elem_faces(el4, gauche(dir));
440 if (face_vois(*this, mon_dom, face34, 0) == -1)
441 les_aretes.affecter(nb_aretes_, dir, mixte, nb_f, face13, face24, face34, face12, est_une_plaque);
442 }
443 }
444 else // corner edge
445 les_aretes.affecter(nb_aretes_, dir, coin, nb_f, face13, -1, -1, face12, est_une_plaque);
446 //Cerr << "elements_bas_droit " << el1 << " " << el2 << " " << el3 << " " << el4 << finl;
447 }
448
449
450 face13 = elem_faces(el1, gauche(dir));
451 el3 = face_vois(*this, mon_dom, face13, 0);
452 if (el3 < 0) // Generate the edge at the top-left of el1
453 // if the cell to the top-left of el1 does not exist
454 {
455 face12 = elem_faces(el1, haut(dir));
456 el2 = face_vois(*this, mon_dom, face12, 1);
457 if (el2 >= 0)
458 {
459 face24 = elem_faces(el2, gauche(dir));
460 el4 = face_vois(*this, mon_dom, face24, 0);
461 if (el4 < 0) // boundary edge
462 les_aretes.affecter(nb_aretes_, dir, bord, nb_f, face13, face24, face12, -1, est_une_plaque);
463 }
464 else // corner edge
465 les_aretes.affecter(nb_aretes_, dir, coin, nb_f, -1, face12, -1, face13, est_une_plaque);
466 //Cerr << "elements_haut_gauche " << el1 << " " << el2 << " " << el3 << " " << el4 << finl;
467 }
468
469 // Generate the edge at the bottom-left of el1
470 face12 = elem_faces(el1, gauche(dir));
471 el2 = face_vois(*this, mon_dom, face12, 0);
472 face13 = elem_faces(el1, bas(dir));
473 el3 = face_vois(*this, mon_dom, face13, 0);
474 if ((el2 < 0) && (el3 < 0)) // corner edge
475 {
476 les_aretes.affecter(nb_aretes_, dir, coin, nb_f, face13, -1, face12, -1, est_une_plaque);
477 //Cerr << "elements_bas_gauche " << el1 << " " << el2 << " " << el3 << " " << el4 << finl;
478 }
479 }
480 nb_aretes_++;
481 les_aretes.dimensionner(nb_aretes_);
482 // Cerr << "Tri des aretes " << finl;
483 les_aretes.trier(nb_aretes_coin_,
484 nb_aretes_bord_,
485 nb_aretes_mixtes_,
486 nb_aretes_internes_);
487#ifdef SORT_POUR_DEBOG
488
489 les_aretes.trier_pour_debog(nb_aretes_coin_,
490 nb_aretes_bord_,
491 nb_aretes_mixtes_,
492 nb_aretes_internes_,xv());
493#endif
494 nb_aretes_joint_=0;
495 assert(nb_aretes_==nb_aretes_coin_+nb_aretes_bord_+nb_aretes_mixtes_
496 +nb_aretes_internes_+nb_aretes_joint_);
497 Qdm_.ref(les_aretes.faces());
498 /*
499 // Loop to verify where the internal walls are
500 for (int i=0; i<Qdm_.dimension(0); i++)
501 {
502 int nb_plaques = 0;
503 for (int j = 0; j < Qdm_.dimension(1); j++)
504 nb_plaques += Qdm_(i, j) >= 0 ? est_une_plaque(Qdm_(i, j)) : 0;
505 if (nb_plaques > 0)
506 Journal() << "Provisoire arete " << i << " a " << nb_plaques << " paroi internes." << finl;
507 }
508 Journal() << "Aretes coin = " << nb_aretes_coin_ << finl;
509 Journal() << "Aretes bord = " << nb_aretes_bord_ << finl;
510 Journal() << "Aretes mixte = " << nb_aretes_mixtes_ << finl;
511 Journal() << "Aretes interne= " << nb_aretes_internes_ << finl;
512 Journal() << "Aretes joint = " << nb_aretes_joint_ << finl;
513 */
514 //Cerr << "Qdm : " << Qdm_ << finl;
515}
516
517/*! @brief Computes the mesh step sizes h_x_, h_y_, h_z_.
518 *
519 */
520void Domaine_VDF::calcul_h()
521{
522 Domaine& domaine_geom=domaine();
523 IntVect numfa(domaine_geom.nb_faces_elem());
524 const double deux_pi = M_PI * 2.0;
525 const int D = dimension;
526
527 for (int e = 0; e < domaine_geom.nb_elem(); e++)
528 {
529 for (int j = 0; j < domaine_geom.nb_faces_elem(); j++)
530 numfa[j] = elem_faces(e, j);
531
532 h_x_ = std::min(h_x_, xv_(numfa[D], 0) - xv_(numfa[0], 0));
533 double hy_loc;
534 if (axi)
535 {
536 double d_teta = xv_(numfa[D + 1], 1) - xv_(numfa[1], 1);
537 if (d_teta < 0) d_teta += deux_pi;
538 hy_loc = d_teta * xv_(numfa[1], 0);
539 }
540 else hy_loc = xv_(numfa[D + 1], 1) - xv_(numfa[1], 1);
541 h_y_ = std::min(h_y_, hy_loc);
542 if (dimension == 3) h_z_ = std::min(h_z_, xv_(numfa[5], 2) - xv_(numfa[2], 2));
543 }
544 h_x_ = mp_min(h_x_);
545 h_y_ = mp_min(h_y_);
546 h_z_ = mp_min(h_z_);
547}
548
550{
551 // Cerr << "Domaine_VDF::Modifier_pour_Cl" << finl;
553
554 int fac3;
555 int nb_cond_lim=conds_lim.size();
556 IntTab aretes_coin_traitees(nb_aretes_coin());
557 aretes_coin_traitees = -1;
558
559 for (int num_cond_lim=0; num_cond_lim<nb_cond_lim; num_cond_lim++)
560 {
561 // for cl ...
562 //Journal() << "On traite la cl num : " << num_cond_lim << finl;
563 const Cond_lim_base& cl = conds_lim[num_cond_lim].valeur();
564 if (sub_type(Periodique, cl))
565 {
566 // if cl perio
567
568 // Modification of the Qdm_ array for periodic edge types
569
570 const Domaine_Cl_VDF& domaine_Cl_VDF = ref_cast(Domaine_Cl_VDF,cl.domaine_Cl_dis());
571
572 int ndeb_arete = premiere_arete_bord();
573 int fac1,fac2,sign,num_face,elem1,n_type;
574 for (int n_arete=ndeb_arete; n_arete<ndeb_arete+nb_aretes_bord(); n_arete++)
575 {
576 // for n_arete
577 n_type=domaine_Cl_VDF.type_arete_bord(n_arete-ndeb_arete);
578
579 if (n_type == TypeAreteBordVDF::PERIO_PERIO) // periodic edge type
580 {
581 //if arete perio
582 fac1 = Qdm_(n_arete,0);
583 fac2 = Qdm_(n_arete,1);
584 fac3 = Qdm_(n_arete,2);
585 sign = Qdm_(n_arete,3);
586
587 const Front_VF& la_frontiere_dis = ref_cast(Front_VF,cl.frontiere_dis());
588 int ndeb = la_frontiere_dis.num_premiere_face();
589 int nfin = ndeb + la_frontiere_dis.nb_faces();
590 if ( ( ( ndeb <= fac1) && (fac1 < nfin) ) ||
591 ( ( ndeb <= fac2) && (fac2 < nfin) )
592 )
593 {
594 if (sign == 1)
595 elem1 = face_voisins(fac1,1);
596 else
597 elem1 = face_voisins(fac1,0);
598 num_face = dimension+orientation_[fac3];
599
600 if (sign == -1)
601 {
602 Qdm_(n_arete,3) = fac3;
603 Qdm_(n_arete,2) = elem_faces(elem1,num_face);
604 }
605 else
606 Qdm_(n_arete,3) = elem_faces(elem1,num_face);
607 }
608 }
609 }
610 // handle corner edges
611 int ndeb_arete_coin = premiere_arete_coin();
612 Cerr << "Modifying Qdm for corner edges num_cond_lim=" << num_cond_lim << finl;
613 int fac4;
614
615 for (int n_arete=ndeb_arete_coin; n_arete<ndeb_arete_coin+nb_aretes_coin(); n_arete++)
616 {
617 if (aretes_coin_traitees[n_arete] != 1)
618 {
619 fac1 = Qdm_(n_arete,0);
620 fac2 = Qdm_(n_arete,1);
621 fac3 = Qdm_(n_arete,2);
622 fac4 = Qdm_(n_arete,3);
623
624 // Retrieve face indices that are not equal to -1
625 IntVect f(2);
626 f = -2;
627 int i=0;
628 if (fac1 != -1)
629 {
630 f(i) = fac1;
631 i++;
632 }
633 if (fac2 != -1)
634 {
635 f(i) = fac2;
636 i++;
637 }
638 if (fac3 != -1)
639 {
640 f(i) = fac3;
641 i++;
642 }
643 if (fac4 != -1)
644 {
645 f(i) = fac4;
646 i++;
647 }
648
649 // Check whether the face is a periodic face
650
651 const Front_VF& la_frontiere_dis = ref_cast(Front_VF,cl.frontiere_dis());
652 int ndeb = la_frontiere_dis.num_premiere_face();
653 int nfin = ndeb + la_frontiere_dis.nb_faces();
654 int elem, fac,dim0,dim1,indic_f0=-100,indic_f1=-100;
655
656 n_type=domaine_Cl_VDF.type_arete_coin(n_arete-ndeb_arete_coin);
657 dim1 = orientation_[f(1)];
658 dim0 = orientation_[f(0)];
659
660 for (int j=0; j<2; j++)
661 for (int k=0; k<2; k++)
662 if ((face_voisins(f(0),j) == face_voisins(f(1),k)) && (face_voisins(f(0),j)!=-1) )
663 {
664 indic_f0 = j;
665 indic_f1 = k;
666 }
667
668 if ((n_type == TypeAreteCoinVDF::PERIO_PAROI) || (n_type == TypeAreteCoinVDF::PERIO_FLUIDE))// perio-wall corner edge
669 {
670 if ((f(0) >= ndeb)&&(f(0) < nfin))
671 {
672 Qdm_(n_arete,2)=f(0);
673 Qdm_(n_arete,indic_f0)=f(1);
674
675 elem = face_voisins(f(0),1-indic_f0);
676 fac = elem_faces(elem,dim1+(1-indic_f1)*dimension);
677 Qdm_(n_arete,1-indic_f0)=fac;
678
679 Qdm_(n_arete,3)=1-2*indic_f1;
680
681 // Cerr << "n_arete=" << n_arete << " OK!!" << finl;
682 aretes_coin_traitees[n_arete] = 1;
683 }
684 else
685 {
686 if ((f(1) >= ndeb)&&(f(1) < nfin))
687 {
688 Qdm_(n_arete,2)=f(1);
689 Qdm_(n_arete,indic_f1)=f(0);
690
691 elem = face_voisins(f(1),1-indic_f1);
692 fac = elem_faces(elem,dim0+(1-indic_f0)*dimension);
693 Qdm_(n_arete,1-indic_f1)=fac;
694
695 Qdm_(n_arete,3)=1-2*indic_f0;
696
697 // Cerr << "n_arete=" << n_arete << " OK!!" << finl;
698 aretes_coin_traitees[n_arete] = 1;
699 }
700 else
701 {
702 // Cerr<<"Attention cas non traite lors du remplissage du tableau Qdm"<<finl;
703 // exit();
704 ;
705 }
706 }
707 }
708 else if (n_type == TypeAreteCoinVDF::PERIO_PERIO) // perio-perio corner edge
709 {
710 if ((f(0) >= ndeb)&&(f(0) < nfin))
711 {
712 Qdm_(n_arete,2+indic_f1)=f(0);
713 Qdm_(n_arete,indic_f0)=f(1);
714
715 elem = face_voisins(f(0),1-indic_f0);
716 fac = elem_faces(elem,dim1+(1-indic_f1)*dimension);
717 Qdm_(n_arete,1-indic_f0)=fac;
718
719 elem = face_voisins(f(1),1-indic_f1);
720 fac = elem_faces(elem,dim0+(1-indic_f0)*dimension);
721 Qdm_(n_arete,3-indic_f1)=fac;
722
723 // Cerr << "n_arete=" << n_arete << " OK!!" << finl;
724 aretes_coin_traitees[n_arete] = 1;
725 }
726 else
727 {
728 if ((f(1) >= ndeb)&&(f(1) < nfin))
729 {
730 Qdm_(n_arete,2+indic_f0)=f(1);
731 Qdm_(n_arete,indic_f1)=f(0);
732
733 elem = face_voisins(f(1),1-indic_f1);
734 fac = elem_faces(elem,dim0+(1-indic_f0)*dimension);
735 Qdm_(n_arete,1-indic_f1)=fac;
736
737 elem = face_voisins(f(0),1-indic_f0);
738 fac = elem_faces(elem,dim1+(1-indic_f1)*dimension);
739 Qdm_(n_arete,3-indic_f0)=fac;
740
741 // Cerr << "n_arete=" << n_arete << " OK!!" << finl;
742 aretes_coin_traitees[n_arete] = 1;
743 }
744 }
745 }
746
747 else
748 {
749 Cerr << "Warning: cases involving other corner edge types " << finl;
750 Cerr << "than perio-perio or perio-wall are not handled!!" << finl;
751 }
752 }
753 }
754 }
755
756 // Modif OC 01/2005 to handle wall/fluid corner types
757 else if (sub_type(Dirichlet_entree_fluide, cl) || sub_type(Neumann_sortie_libre, cl) )
758 {
759 // if cl of wall type
760
761 const Domaine_Cl_VDF& domaine_Cl_VDF = ref_cast(Domaine_Cl_VDF,cl.domaine_Cl_dis());
762
763 int fac1,fac2,n_type;
764 int ndeb_arete_coin = premiere_arete_coin();
765 Cerr << "Modifying Qdm for corner edges touching a wall num_cond_lim=" << num_cond_lim << finl;
766 int fac4;
767
768 for (int n_arete=ndeb_arete_coin; n_arete<ndeb_arete_coin+nb_aretes_coin(); n_arete++)
769 {
770 if (aretes_coin_traitees[n_arete] != 1)
771 {
772 fac1 = Qdm_(n_arete,0);
773 fac2 = Qdm_(n_arete,1);
774 fac3 = Qdm_(n_arete,2);
775 fac4 = Qdm_(n_arete,3);
776
777 // Retrieve face indices that are not equal to -1
778 IntVect f(2);
779 f = -2;
780 int i=0;
781 if (fac1 != -1)
782 {
783 f(i) = fac1;
784 i++;
785 }
786 if (fac2 != -1)
787 {
788 f(i) = fac2;
789 i++;
790 }
791 if (fac3 != -1)
792 {
793 f(i) = fac3;
794 i++;
795 }
796 if (fac4 != -1)
797 {
798 f(i) = fac4;
799 i++;
800 }
801
802 // Check whether the face is a wall-type face
803
804 const Front_VF& la_frontiere_dis = ref_cast(Front_VF,cl.frontiere_dis());
805 int ndeb = la_frontiere_dis.num_premiere_face();
806 int nfin = ndeb + la_frontiere_dis.nb_faces();
807 int indic_f0=-100,indic_f1=-100;
808
809 n_type=domaine_Cl_VDF.type_arete_coin(n_arete-ndeb_arete_coin);
810
811 for (int j=0; j<2; j++)
812 for (int k=0; k<2; k++)
813 if ((face_voisins(f(0),j) == face_voisins(f(1),k)) && (face_voisins(f(0),j)!=-1) )
814 {
815 indic_f0 = j;
816 indic_f1 = k;
817 }
818
819 if ((n_type == TypeAreteCoinVDF::PAROI_FLUIDE) || (n_type == TypeAreteCoinVDF::FLUIDE_PAROI) || (n_type == TypeAreteCoinVDF::FLUIDE_FLUIDE))// wall-fluid corner edge
820 {
821 if ((f(0) >= ndeb)&&(f(0) < nfin))
822 {
823 Qdm_(n_arete,0)=f(1);
824 Qdm_(n_arete,1)=f(1);
825 Qdm_(n_arete,2)=f(0);
826 Qdm_(n_arete,3)=1-2*indic_f1;
827 aretes_coin_traitees[n_arete] = 1;
828 }
829 else
830 {
831 if ((f(1) >= ndeb)&&(f(1) < nfin))
832 {
833 Qdm_(n_arete,0)=f(0);
834 Qdm_(n_arete,1)=f(0);
835 Qdm_(n_arete,2)=f(1);
836 Qdm_(n_arete,3)=1-2*indic_f0;
837 aretes_coin_traitees[n_arete] = 1;
838 }
839 else
840 {
841 // Cerr<<"Attention cas non traite lors du remplissage du tableau Qdm"<<finl;
842 // exit();
843 ;
844 }
845 }
846 }
847 }
848 }
849 }
850
851 // Cerr << "Qdm : " << Qdm_ << finl;
852 // Cerr << "aretes_coin_traitees : " << aretes_coin_traitees << finl;
853 }
854 //Journal() << "domain after modification for Cl : " << *this << finl;
855
856
857 // PQ : 10/10/05 : periodic faces have a double contribution;
858 // the call to marquer_faces_double_contrib is done in this method
859 // in order to have access to conds_lim.
860
861
863}
864
865/*! @brief Fills the face_voisins_fictifs_ array. Does NOT create fictitious elements.
866 *
867 * @param zcldisbase The discretized boundary condition domain.
868 */
869
871{
872 Cerr << "Domaine_VDF::creer_elements_fictifs() called" << finl;
873 const Domaine_Cl_VDF& zclvdf = ref_cast(Domaine_Cl_VDF,zcldisbase);
874 if (face_voisins_fictifs_.size() == 0)
875 {
878 int compteur = nb_elem_tot();
879 int face,ndeb,nfin;
880
881 for (int n_bord=0; n_bord<nb_front_Cl(); n_bord++)
882 {
883 const Cond_lim& la_cl = zclvdf.les_conditions_limites(n_bord);
884 const Front_VF& le_bord = ref_cast(Front_VF,la_cl->frontiere_dis());
885 if ( (sub_type(Dirichlet_entree_fluide,la_cl.valeur())) ||
886 (sub_type(Neumann_sortie_libre,la_cl.valeur())) )
887 {
888 ndeb = le_bord.num_premiere_face();
889 nfin = ndeb + le_bord.nb_faces();
890 for (face=ndeb; face<nfin; face++)
891 if (face_voisins(face,0) != -1)
892 face_voisins_fictifs_(face,1) = compteur++;
893 else
894 face_voisins_fictifs_(face,0) = compteur++ ;
895 }
896 }
897 }
898 Cerr << "size "<<face_voisins_fictifs_.size()-nb_elem()<<finl;
899}
900
901// Fills the dist array with the normal distances to the boundary
902// for the boundary faces of name nom_bord.
903// The dist array is resized by this method.
904DoubleVect& Domaine_VDF::dist_norm_bord(DoubleVect& dist, const Nom& nom_bord) const
905{
906 if (axi)
907 {
908 for (int n_bord=0; n_bord<les_bords_.size(); n_bord++)
909 {
910 const Front_VF& fr_vf = front_VF(n_bord);
911 if (fr_vf.le_nom() == nom_bord)
912 {
913 dist.resize(fr_vf.nb_faces());
914 int ndeb = fr_vf.num_premiere_face();
915 for (int face=ndeb; face<ndeb+fr_vf.nb_faces(); face++)
916 dist(face-ndeb) = dist_norm_bord_axi(face);
917 }
918 }
919 }
920 else
921 {
922 for (int n_bord=0; n_bord<les_bords_.size(); n_bord++)
923 {
924 const Front_VF& fr_vf = front_VF(n_bord);
925 if (fr_vf.le_nom() == nom_bord)
926 {
927 dist.resize(fr_vf.nb_faces());
928 int ndeb = fr_vf.num_premiere_face();
929 for (int face=ndeb; face<ndeb+fr_vf.nb_faces(); face++)
930 dist(face-ndeb) = dist_norm_bord(face);
931 }
932 }
933 }
934 return dist;
935}
936
938{
939 IntTrav p_e(0, 2);
941 for (int e = 0; e < nb_elem() ; e++) p_e(e, 0) = Process::me(), p_e(e, 1) = e;
943 for (int e = nb_elem() ; e < nb_elem_tot() ; e++) virt_e_map[ {{ p_e(e, 0), p_e(e, 1) }}] = e;
944}
class Cond_lim_base Base class for the hierarchy of classes that represent the different boundary con...
Domaine_Cl_dis_base & domaine_Cl_dis()
Returns the domain of discretized boundary conditions to which the object belongs.
virtual Frontiere_dis_base & frontiere_dis()
Returns the discretized boundary to which the boundary conditions apply.
class Cond_lim Generic class used to represent any class
Definition Cond_lim.h:31
class Conds_lim This class represents a vector of boundary conditions.
Definition Conds_lim.h:32
Dirichlet_entree_fluide This class represents a boundary condition imposing a quantity.
int_t nb_elem_tot() const
Definition Domaine.h:132
SmallArrOfTID_t & chercher_elements(const DoubleTab &pos, SmallArrOfTID_t &elem, int reel=0) const
Searches for the elements containing the points whose coordinates are specified.
Definition Domaine.cpp:404
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_t nb_faces_frontiere() const
Returns the number of boundary faces of the domain (sum of boundaries, connections,...
Definition Domaine.h:488
int_t nb_elem() const
Definition Domaine.h:131
int nb_faces_elem(int=0) const
Returns the number of faces of type i of the geometric elements that make up the domain.
Definition Domaine.h:484
int_t nb_som() const
Returns the number of vertices of the domain.
Definition Domaine.h:121
class Domaine_Cl_VDF
int type_arete_bord(int num_arete) const
const int & type_arete_coin(int num_arete) const
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_VDF
Definition Domaine_VDF.h:61
int nb_aretes_coin() const
void compute_sort_key(Faces &, IntTab &sort_key) override
Override. Compute sorting key so that internal faces are sorted by their orientation first (X,...
double dist_norm_bord_axi(int num_face) const
Returns the normal distance for a boundary face (cylindrical coordinates).
IntVect & orientation()
inline double Domaine_VDF::porosite_face(int i) const {
Faces * creer_faces() override
Returns a newly allocated Faces_VDF object.
void prepare_elem_non_std(Faces &) override
double dim_elem(int, int) const
std::map< std::array< int, 2 >, int > virt_e_map
void creer_elements_fictifs(const Domaine_Cl_dis_base &) override
Fills the face_voisins_fictifs_ array. Does NOT create fictitious elements.
int premiere_arete_bord() const
void discretiser() override
Calls Domaine_VF::discretiser(), computes element gravity centers,.
int premiere_arete_coin() const
int nb_aretes_bord() const
void modifier_pour_Cl(const Conds_lim &cl) override
void init_virt_e_map() const
void renumber_faces(Faces &les_faces, IntTab &sort_key) override
Override to also renumber orientation_ member.
void calculer_volumes_entrelaces()
Fills the staggered volumes (volumes entrelaces).
double dist_norm_bord(int num_face) const override
Returns the normal distance for a boundary face (Cartesian coordinates).
class Domaine_VF
Definition Domaine_VF.h:44
virtual const DoubleVect & face_surfaces() const
Definition Domaine_VF.h:51
int nb_faces() const
Returns the total number of faces.
Definition Domaine_VF.h:471
DoubleVect volumes_entrelaces_
Definition Domaine_VF.h:210
double volume_entrelace_axi(double r_face, double r_elem, double axis_length) const
Definition Domaine_VF.h:702
int nb_faces_tot() const
Returns the total number of faces.
Definition Domaine_VF.h:481
void creer_tableau_faces(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
DoubleTab xv_
Definition Domaine_VF.h:219
int nb_faces_std_
Definition Domaine_VF.h:251
void discretiser() override
Generates the faces and builds the boundaries.
void modifier_pour_Cl(const Conds_lim &) override
DoubleTab & xv()
Definition Domaine_VF.h:93
IntTab & elem_faces()
Returns the element/face connectivity array.
Definition Domaine_VF.h:550
IntTab face_voisins_
Definition Domaine_VF.h:216
DoubleVect & volumes()
Definition Domaine_VF.h:119
virtual void renumber_faces(Faces &les_faces, IntTab &sort_key)
Re-index faces according to the new order given by 'sort_key'.
DoubleTab face_normales_
Definition Domaine_VF.h:212
IntTab face_voisins_fictifs_
Definition Domaine_VF.h:217
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
DoubleTab volumes_entrelaces_dir_
Definition Domaine_VF.h:211
DoubleTab & xp()
Definition Domaine_VF.h:95
int nb_faces_bord() const
Returns the number of faces on which boundary conditions are applied:
Definition Domaine_VF.h:512
const Front_VF & front_VF(int i) const
Definition Domaine_VF.h:112
IntTab & face_voisins() override
Returns the face-element connectivity array; see above.
Definition Domaine_VF.h:426
void marquer_faces_double_contrib(const Conds_lim &)
int nb_elem_tot() const
int nb_front_Cl() const
const Domaine & domaine() const
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
int_t nb_faces() const
Definition Faces.h:66
void calculer_orientation(IntVect &, int &, int &, int &)
Definition Faces_VDF.cpp:38
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
const Nom & le_nom() const override
Returns the name of the geometric boundary.
: This class is an OWN_PTR but the pointed object is shared among multiple
Definition MD_Vector.h:48
Neumann_sortie_libre This class represents an open boundary without imposed velocity.
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
static double precision_geom
Definition Objet_U.h:81
static int bidim_axi
Definition Objet_U.h:97
static int axi
Definition Objet_U.h:96
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
class Periodique This class represents a periodic boundary condition.
Definition Periodique.h:31
static double mp_min(double)
Definition Process.cpp:391
static int me()
Returns the rank of the local processor in the current communication group. See Comm_Group::rank() an...
Definition Process.cpp:122
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
void resize(_SIZE_, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTVect.tpp:91
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")