TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Faces.cpp
1/****************************************************************************
2* Copyright (c) 2025, 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 <Faces.h>
17#include <DomaineAxi1d.h>
18#include <communications.h>
19#include <Linear_algebra_tools_impl.h>
20#include <TRUSTLists.h>
21
22Implemente_instanciable_32_64(Faces_32_64,"Faces",Objet_U);
23
24/*! @brief Writes the faces to an output stream.
25 *
26 * The following are written:
27 * - the face type
28 * - the vertices
29 * - the neighbors
30 * Only the type Type_Face::vide_0D is written if the number of faces is zero.
31 *
32 * @param s An output stream.
33 * @return The modified output stream.
34 */
35template <typename _SIZE_>
37{
38 if(nb_faces()==0)
39 s << "vide_0D" << finl;
40 else
41 {
42 s << (type(type_face_)) << finl;
43 s << sommets;
44 s << faces_voisins;
45 }
46 return s ;
47}
48
49/*! @brief Writes the faces to an output stream (binary format).
50 *
51 * The following are written:
52 * - the face type
53 * - the vertices
54 * - the neighbors
55 * Only the type Type_Face::vide_0D is written if the number of faces is zero.
56 *
57 * @param s An output stream.
58 * @return The modified output stream.
59 */
60template <typename _SIZE_>
62{
63 if(nb_faces()==0)
64 s << "vide_0D" << finl;
65 else
66 {
67 s << (type(type_face_)) << finl;
68 sommets.ecrit(s);
69 faces_voisins.ecrit(s);
70 }
71 return s ;
72}
73
74/*! @brief Reads the specifications of a face object from an input stream.
75 *
76 * The following are read:
77 * - the face type
78 * - the vertices
79 * - the neighbors
80 * Creates a Faces_32_64 object with 0 faces if the type is "vide_0D".
81 *
82 * @param s An input stream.
83 * @return The modified input stream.
84 */
85template <typename _SIZE_>
87{
88 Motcle typ;
89 s >> typ;
90 typer(typ);
91 if (typ != "vide_0D")
92 {
93 // Vertices and neighbors are only written if the type is not empty:
94 s >> sommets;
95 s >> faces_voisins;
96 }
97 else
98 {
99 // to avoid a crash in the subsequent code that assumes nb_dim()==2 and line_size_ > 0
100 sommets.resize(0,1);
101 faces_voisins.resize(0,2);
102 }
103 return s;
104}
105
106
107/*! @brief Reads the specifications of a face object from an input stream (binary format).
108 *
109 * The following are read:
110 * - the face type
111 * - the vertices
112 * - the neighbors
113 * Vertices are reordered after reading. Does nothing if the type read is "vide_0D".
114 *
115 * @param s An input stream.
116 * @return The modified input stream.
117 */
118template <typename _SIZE_>
120{
121 Motcle typ;
122 s >> typ;
123 if(typ!="vide_0D")
124 {
125 typer(typ);
126 sommets.lit(s);
127 faces_voisins.lit(s);
128 reordonner();
129 }
130 else
131 {
132 typer(typ);
133 sommets.resize(0,0);
134 faces_voisins.resize(0,2);
135 }
136 return s ;
137}
138
139
140/*! @brief Returns the index of the smallest vertex (in terms of vertex numbering) of a face.
141 *
142 * @param (int face) the index of the face for which the smallest vertex is sought
143 * @param (int nb_som) the number of vertices per face
144 * @return (int) the index of the smallest vertex of the specified face
145 */
146template <typename _SIZE_>
147typename Faces_32_64<_SIZE_>::int_t Faces_32_64<_SIZE_>::ppsf(int_t face, int nb_som) const
148{
149 int_t som = sommet(face,0);
150 for(int imin=1; imin < nb_som; imin++)
151 som=std::min(som,sommet(face,imin));
152 return som;
153}
154
155/*! @brief Compares 2 faces from 2 face sets f1 and f2 and returns true if they are equal, false otherwise.
156 *
157 * @param (int f1) the index of the face in the first face set represented by *this
158 * @param (Faces& faces2) the second face set
159 * @param (int f2) the index of the face in the second face set
160 * @param (int nb_som) the number of vertices per face
161 * @return (bool) true if the 2 faces are the same, false otherwise
162 */
163template <typename _SIZE_>
164bool Faces_32_64<_SIZE_>::same_face(int_t f1, const Faces_32_64& faces2, int_t f2, int nb_som) const
165{
166 // [ABN] ??? I don't understand this ugliness - should compare std::set<>?
167 bool ok=true;
168 for(int i=0; i<nb_som && ok ; i++)
169 {
170 bool nok=true;
171 for(int j=0; j<nb_som && nok ; j++)
172 {
173 if(sommet(f1, i) == faces2.sommet(f2, j))
174 nok=false; // same vertices
175 }
176 if(nok) ok=false; // vertex not found => not the same face
177 }
178 return ok;
179}
180
181/*! @brief Returns a Type_Face object representing the type with the specified name.
182 *
183 * Recognized type names are:
184 * "vide_0D"
185 * "point_1D"
186 * "point_1D_axi"
187 * "segment_2D"
188 * "triangle_3D"
189 * "quadrangle_3D"
190 * "segment_2D_axi"
191 * "quadrangle_3D_axi"
192 * "quadrilatere_2D_axi"
193 *
194 * @param (Motcle& mot) the keyword representing a face type
195 * @return (Type_Face) the face type corresponding to the parameter
196 * @throws unrecognized face type
197 */
198template <typename _SIZE_>
199Type_Face Faces_32_64<_SIZE_>::type(const Motcle& mot) const
200{
201 Motcles les_mots(10);
202 {
203 les_mots[0]="vide_0D";
204 les_mots[1]="point_1D";
205 les_mots[2]="point_1D_axi";
206 les_mots[3]="segment_2D";
207 les_mots[4]="triangle_3D";
208 les_mots[5]="quadrangle_3D";
209 les_mots[6]="segment_2D_axi";
210 les_mots[7]="quadrangle_3D_axi";
211 les_mots[8]="quadrilatere_2D_axi";
212 les_mots[9]="polygone_3d";
213 }
214 int rang=les_mots.search(mot);
215 switch(rang)
216 {
217 case 0 :
218 return Type_Face::vide_0D;
219 case 1 :
220 return Type_Face::point_1D;
221 case 2 :
222 return Type_Face::point_1D_axi;
223 case 3 :
224 return Type_Face::segment_2D;
225 case 4 :
226 return Type_Face::triangle_3D;
227 case 5 :
228 return Type_Face::quadrangle_3D;
229 case 6 :
230 return Type_Face::segment_2D_axi;
231 case 7 :
232 return Type_Face::quadrangle_3D_axi;
233 case 8 :
234 return Type_Face::quadrilatere_2D_axi;
235 case 9 :
236 return Type_Face::polygone_3D;
237 default :
238 {
239 Cerr << "In the area number " << Process::me() << " " << mot << " is not a type of face." << finl;
240 Cerr << "Check your splitting." << finl;
241 // If mot is empty, an attempt is being made to re-read Domains created with a version prior to 1.5.1
242 if (mot=="")
243 {
244 Cerr << "Your splitting seems to have been done with a TRUST version 1.5 or earlier. Since" << finl;
245 Cerr << "the 1.5.1, the files format of .Zones containing the splitting of your mesh has evolved." << finl;
246 Cerr << "You must therefore rebuild the splitting of your mesh with TRUST version 1.5.1 or newer." <<
247 finl;
248 }
249 exit();
250 }
251 }
252 // for the compiler:
253 return Type_Face::point_1D;
254}
255
256/*! @brief Returns the name associated with a face type.
257 *
258 * (inverse of Type_Face Faces_32_64<_SIZE_>::type(const Motcle& ) const)
259 *
260 * @param (Type_Face& typ) a face type
261 * @return (Motcle&) the name corresponding to the specified type
262 * @throws unrecognized face type
263 */
264template <typename _SIZE_>
265Motcle& Faces_32_64<_SIZE_>::type(const Type_Face& typ) const
266{
267 static Motcle mot;
268 switch(typ)
269 {
270 case Type_Face::vide_0D :
271 mot="vide_0D";
272 break;
273 case Type_Face::point_1D :
274 mot="point_1D";
275 break;
276 case Type_Face::point_1D_axi :
277 mot="point_1D_axi";
278 break;
279 case Type_Face::segment_2D :
280 mot="segment_2D";
281 break;
282 case Type_Face::segment_2D_axi :
283 mot="segment_2D_axi";
284 break;
285 case Type_Face::triangle_3D :
286 mot="triangle_3D";
287 break;
288 case Type_Face::quadrangle_3D :
289 mot="quadrangle_3D";
290 break;
291 case Type_Face::quadrangle_3D_axi :
292 mot="quadrangle_3D_axi";
293 break;
294 case Type_Face::quadrilatere_2D_axi :
295 mot="quadrilatere_2D_axi";
296 break;
297 case Type_Face::polygone_3D:
298 mot="polygone_3D";
299 break;
300 default :
301 {
302 Cerr << "Error TRUST in Motcle& Faces_32_64<_SIZE_>::type(const Type_Face& typ)" << finl;
303 exit();
304 }
305 }
306 return mot;
307}
308
309/*! @brief Adds faces.
310 *
311 * Adding faces is equivalent to adding vertices.
312 *
313 * @param (IntTab& sommet) the array of vertices to add
314 * @throws the specified vertices do not have the correct dimension (1D,2D,3D)
315 */
316template <typename _SIZE_>
318{
319 assert(sommets.dimension(1)==tab_sommet.dimension(1));
320 int_t oldsz=sommets.dimension(0);
321 int_t addsz=tab_sommet.dimension(0);
322 dimensionner(oldsz+addsz);
323 for(int_t i=0; i<addsz; i++)
324 for(int j=0; j<tab_sommet.dimension(1); j++)
325 sommets(oldsz+i,j)=tab_sommet(i,j);
326}
327
328/*! @brief (Re-)sizes the faces. The neighbors are resized accordingly.
329 *
330 * Implicitly added vertices are initialized to -1.
331 *
332 * @param (int i) the new number of faces
333 * @return (int) the new number of faces
334 */
335template <typename _SIZE_>
337{
338 int_t oldsz=nb_faces();
339 int nombre_som_faces=nb_som_faces();
340 if (sommets.size()!=0) sommets.detach_vect(); // Fixed bug: To have the possibility of merging borders after discretization
341 sommets.resize(i,nombre_som_faces);
342 faces_voisins.resize(i, 2);
343 for(int_t j=oldsz; j<i; j++)
344 {
345 for(int k=0; k<nombre_som_faces; k++)
346 sommets(j,k)=-1;
347 faces_voisins(j,0)=faces_voisins(j,1)=-1;
348 }
349 return i;
350}
351
352/*! @brief Initializes the neighbors of joint faces to -1.
353 *
354 * @param (int nb_faces_joint) the number of faces representing Joints
355 */
356template <typename _SIZE_>
358{
359 for(int_t i=0; i<nb_faces_joint; i++)
360 // faces_voisins(i,0)=faces_voisins(i,1)=-2;
361 faces_voisins(i,0)=faces_voisins(i,1)=-1;
362}
363
364/*! @brief Initializes the vertices of joint faces to -1.
365 *
366 * @param (int nb_faces_joint) the number of faces representing Joints
367 */
368template <typename _SIZE_>
370{
371 for(int_t i=0; i<nb_faces_joint; i++)
372 for(int k=0; k<nb_som_faces(); k++)
373 // sommets(i,k)=-2;
374 sommets(i,k)=-1;
375}
376
377/*! @brief Sets the type of the faces.
378 *
379 * @param (Motcle& typ) the type to assign to the faces
380 */
381template <typename _SIZE_>
383{
384 typer(type(typ));
385}
386
387/*! @brief Sets the type of the faces.
388 *
389 * @param (Type_Face& typ) the type to assign to the faces
390 * @throws unknown face type
391 */
392template <typename _SIZE_>
393void Faces_32_64<_SIZE_>::typer(const Type_Face& typ)
394{
395 type_face_ = typ;
396 // int axi_ = 0;
397 int max_dim = 3;
398 switch(typ)
399 {
400 case Type_Face::vide_0D :
401 nb_som_face=0;
402 break;
403 case Type_Face::point_1D :
404 case Type_Face::point_1D_axi :
405 nb_som_face=1;
406 break;
407 case Type_Face::segment_2D :
408 nb_som_face=2;
409 break;
410 case Type_Face::segment_2D_axi :
411 nb_som_face=2; //axi_=1;
412 break;
413 case Type_Face::triangle_3D :
414 nb_som_face=3;
415 break;
416 case Type_Face::quadrangle_3D :
417 nb_som_face=4;
418 break;
419 case Type_Face::quadrangle_3D_axi :
420 nb_som_face=4; //axi_=1;
421 break;
422 case Type_Face::quadrilatere_2D_axi :
423 nb_som_face=2; //axi_=1;
424 break;
425 case Type_Face::polygone_3D:
426 nb_som_face=-1; // will be set later
427 break;
428 default :
429 {
430 Cerr << "Error TRUST in Faces_32_64<_SIZE_>::typer(const Motcle& typ)" << finl;
431 exit();
432 }
433 }
434 /* TroisDto2D marche pas
435 if (axi_==1 && bidim_axi!=1 && axi!=1)
436 {
437 Cerr << "The mesh contains faces that show that is a revolution mesh." << finl;
438 Cerr << "Add Bidim_axi or Axi in your data file." << finl;
439 exit();
440 } */
441 if (dimension<std::min(max_dim,nb_som_face))
442 {
443 Cerr << "You are in dimension " << dimension << finl;
444 Cerr << "and the mesh contains faces with " << nb_som_face << " nodes." << finl;
445 Cerr << "and this seems to be a mesh of dimension " << std::min(max_dim,nb_som_face) << " ..." << finl;
446 exit();
447 }
448}
449
450
451/*! @brief Completes the specified face: updates its neighbors.
452 *
453 * @param (int face) the index of the face to complete
454 * @param (int num_elem) the index of the neighboring element of the face
455 * @throws face already complete
456 */
457template <typename _SIZE_>
459{
460 if ( voisin(face,0) == -1)
461 voisin(face, 0) = num_elem;
462 else if( voisin(face,1) == -1)
463 voisin(face, 1) = num_elem;
464 else
465 {
466 Cerr << finl;
467 Cerr << "Problem for the face number " << face << " and the cell " << num_elem << finl;
468 Cerr << "Indeed, the face already belongs to the cells " << voisin(face, 0) << " and " << voisin(face, 1) << finl;
469 Cerr << "The nodes of this face are:" << finl;
470 for (int i=0; i<nb_som_face; i++)
471 Cerr << "Node " << sommet(face,i) << finl;
472 Cerr << "Check your mesh. Perhaps some cells " << finl;
473 Cerr << "are defined 2 times." << finl;
474 exit();
475 }
476}
477
478/*! @brief Computes the surface area of the faces.
479 *
480 * @param (DoubleVect& surfaces) the vector containing the surface area of each face.
481 * @throws unrecognized face type
482 * @throws surface area computation not implemented for this face type
483 * @throws erroneous surface computation (surface <= 0)
484 * @throws face type not consistent with the space dimension
485 */
486template <typename _SIZE_>
488{
489 surfaces.resize(nb_faces_tot());
490 const Domaine_t& dom=domaine();
491 // Check that in cylindrical coordinates, r is positive (with numerical tolerance)
492 if (axi || bidim_axi)
493 {
494 const int_t nb_som = dom.les_sommets().dimension(0);
495 // Radius scale to set a robust tolerance
496 double rmax = 0.;
497 for (int_t i = 0; i < nb_som; i++)
498 rmax = std::max(rmax, std::fabs(dom.coord(i,0)));
499 const double tol = std::max(Objet_U::precision_geom * std::max(1.0, rmax), 1e-300);
500 for (int_t i = 0; i < nb_som; i++)
501 {
502 const double r = dom.coord(i,0);
503 if (r < -tol)
504 {
505 Cerr << "In axisymmetric, the coordinates of the mesh according to radius" << finl;
506 Cerr << "ie along X, cannot be negative beyond tolerance." << finl;
507 Cerr << "The revolution axis must be at x=0." << finl;
508 Cerr << "we got x = " << r << " (tolerance = " << tol << ")" << finl;
509 exit();
510 }
511 }
512 }
513 switch(type_face_)
514 {
515 case Type_Face::segment_2D :
516 {
517 assert(dimension==2);
518 for (int_t face = 0; face < nb_faces_tot(); face++)
519 {
520 const double x0 = dom.coord(sommet(face,0), 0);
521 const double y0 = dom.coord(sommet(face,0), 1);
522 const double x1 = dom.coord(sommet(face,1), 0);
523 const double y1 = dom.coord(sommet(face,1), 1);
524 const double dx = x0 - x1;
525 const double dy = y0 - y1;
526 const double L = std::sqrt(dx*dx + dy*dy);
527
529 {
530 // pure 2D Cartesian: surface = length
531 surfaces(face) = L;
532 if(surfaces(face) == 0.)
533 {
534 Cerr << "area("<<face<<")=0 ! Check your mesh." << finl;
535 exit();
536 }
537 }
538 else
539 {
540 // RZ (bidim_axi): surface of the torus generated by the segment
541 // S = Δθ * r_bar * L, with r_bar = (r0 + r1)/2 and r ≡ x
542 const double r0 = x0;
543 const double r1 = x1;
544 const double rbar = 0.5 * (r0 + r1);
545 surfaces(face) = 2.0 * M_PI * L * rbar;
546 }
547 }
548 break;
549 }
550 case Type_Face::quadrilatere_2D_axi :
551 {
552 assert(dimension==2);
553 for (int_t face = 0; face < nb_faces_tot(); face++)
554 {
555 const double r0 = dom.coord(sommet(face,0), 0);
556 const double z0 = dom.coord(sommet(face,0), 1);
557 const double r1 = dom.coord(sommet(face,1), 0);
558 const double z1 = dom.coord(sommet(face,1), 1);
559 const double dr = r1 - r0;
560 const double dz = z1 - z0;
561 const double L = std::sqrt(dr*dr + dz*dz); // segment length
562 const double rbar = 0.5*(r0 + r1); // linear average of r(s) over the segment
563 surfaces(face) = 2.0 * M_PI * rbar * L; // S = Δθ ∫_Γ r ds = Δθ * r̄ * L
564 }
565 break;
566 }
567
568 case Type_Face::segment_2D_axi :
569 {
570 assert(dimension==2);
571 double r0,r1,teta0,teta1,d_teta;
572 for(int_t face=0; face <nb_faces_tot(); face++)
573 {
574 r0 = dom.coord(sommet(face ,0), 0);
575 r1 = dom.coord(sommet(face ,1), 0);
576 if ( est_egal(r0,r1) ) // surface = r0*abs(teta1-teta0)
577 {
578 teta0 = dom.coord(sommet(face ,0), 1);
579 teta1 = dom.coord(sommet(face ,1), 1);
580 d_teta = std::fabs(teta1-teta0);
581 if(d_teta > M_PI) d_teta=2.*M_PI-d_teta;
582 surfaces(face)=r0*d_teta;
583 }
584 else // surface = r1-r2
585 surfaces(face)=std::fabs(r1-r0);
586 }
587 break;
588 }
589 case Type_Face::triangle_3D :
590 {
591 assert(dimension==3);
592
593 double delta0, delta1, delta2;
594 double longueur0, longueur1;
595 double prod,sa;
596
597 for(int_t face=0; face <nb_faces_tot(); face++)
598 {
599 prod=0;
600 delta0=(dom.coord(sommet(face ,1), 0) - dom.coord(sommet(face ,0), 0));
601 delta1=(dom.coord(sommet(face ,1), 1) - dom.coord(sommet(face ,0), 1));
602 delta2=(dom.coord(sommet(face ,1), 2) - dom.coord(sommet(face ,0), 2));
603 longueur0=(delta0*delta0+delta1*delta1+delta2*delta2);
604 sa=delta0;
605 delta0=(dom.coord(sommet(face ,2), 0) - dom.coord(sommet(face ,0), 0));
606 prod=sa*delta0;
607 sa=delta1;
608 delta1=(dom.coord(sommet(face ,2), 1) - dom.coord(sommet(face ,0), 1));
609 prod+=sa*delta1;
610 sa=delta2;
611 delta2=(dom.coord(sommet(face ,2), 2) - dom.coord(sommet(face ,0), 2));
612 prod+=sa*delta2;
613 longueur1=(delta0*delta0+delta1*delta1+delta2*delta2);
614 surfaces(face)=0.5*(sqrt(longueur0*longueur1-prod*prod));
615 if(surfaces(face)==0.)
616 {
617 Cerr << "area("<<face<<")=0 ! Check your mesh." << finl;
618 exit();
619 }
620 }
621 break;
622 }
623 case Type_Face::quadrangle_3D :
624 {
625 // Based on Hexa_VEF::normale():
626 for(int_t face=0; face <nb_faces_tot(); face++)
627 {
628 int_t n0 = sommet(face, 0),
629 n1 = sommet(face, 1),
630 n2 = sommet(face, 2),
631 n3 = sommet(face, 3);
632 // NB: In a prism, there are also triangles as faces... Therefore:
633 if (n3<0) n3 = n2;
634
635 double x1 = dom.coord(n0, 0) - dom.coord(n1, 0);
636 double y1 = dom.coord(n0, 1) - dom.coord(n1, 1);
637 double z1 = dom.coord(n0, 2) - dom.coord(n1, 2);
638
639 double x2 = dom.coord(n3, 0) - dom.coord(n1, 0);
640 double y2 = dom.coord(n3, 1) - dom.coord(n1, 1);
641 double z2 = dom.coord(n3, 2) - dom.coord(n1, 2);
642
643 double nx = (y1*z2 - y2*z1)/2;
644 double ny = (-x1*z2 + x2*z1)/2;
645 double nz = (x1*y2 - x2*y1)/2;
646
647 x1 = dom.coord(n0,0) - dom.coord(n2,0);
648 y1 = dom.coord(n0,1) - dom.coord(n2,1);
649 z1 = dom.coord(n0,2) - dom.coord(n2,2);
650
651 x2 = dom.coord(n3,0) - dom.coord(n2,0);
652 y2 = dom.coord(n3,1) - dom.coord(n2,1);
653 z2 = dom.coord(n3,2) - dom.coord(n2,2);
654
655 nx -= (y1*z2 - y2*z1)/2;
656 ny -= (-x1*z2 + x2*z1)/2;
657 nz -= (x1*y2 - x2*y1)/2;
658
659 surfaces(face)=sqrt(nx*nx+ny*ny+nz*nz);
660 }
661 break;
662 }
663 case Type_Face::quadrangle_3D_axi :
664 {
665 assert(dimension==3);
666 double r0,r1,teta0,teta1,teta2,z0,z2,d_teta,delta_r;
667 for(int_t face=0; face <nb_faces_tot(); face++)
668 {
669 r0 = dom.coord(sommet(face ,0), 0);
670 r1 = dom.coord(sommet(face ,1), 0);
671 delta_r = std::fabs(r1 - r0);
672 if ( est_egal(r0,r1) )
673 {
674 teta0 = dom.coord(sommet(face ,0), 1);
675 teta1 = dom.coord(sommet(face ,1), 1);
676 z0 = dom.coord(sommet(face ,0), 2);
677 z2 = dom.coord(sommet(face ,2), 2);
678 d_teta = std::fabs(teta1-teta0);
679 if(d_teta > M_PI) d_teta=2.*M_PI-d_teta;
680 surfaces(face)=r0*d_teta*std::fabs(z2-z0);
681 }
682 else
683 {
684 teta0 = dom.coord(sommet(face ,0), 1);
685 teta2 = dom.coord(sommet(face ,2), 1);
686 if (teta0 == teta2)
687 {
688 z0 = dom.coord(sommet(face ,0), 2);
689 z2 = dom.coord(sommet(face ,2), 2);
690 surfaces(face) = delta_r*std::fabs(z2-z0);
691 }
692 else
693 {
694 d_teta=std::fabs(teta2-teta0);
695 if(d_teta > M_PI) d_teta=2.*M_PI-d_teta;
696 surfaces(face) = 0.5*(r0+r1)*d_teta*delta_r;
697 }
698 }
699 }
700 break;
701 }
702 case Type_Face::point_1D:
703 case Type_Face::vide_0D :
704 {
705 for(int_t face=0; face <nb_faces_tot(); face++)
706 surfaces(face) = 1.0;
707
708 break;
709 }
710 case Type_Face::point_1D_axi:
711 {
712 assert(dimension==3);
713
714 const DomaineAxi1d_t& domax = ref_cast(DomaineAxi1d_t,dom);
715
716 for(int_t face=0; face <nb_faces_tot(); face++)
717 {
718 int_t elem = voisin(face,0)==-1 ? voisin(face,1) : voisin(face,0);
719
720 double x0 = domax.origine_repere(elem,0);
721 double y0 = domax.origine_repere(elem,1);
722 double x = dom.coord(sommet(face ,0), 0);
723 double y = dom.coord(sommet(face ,0), 1);
724
725 double r = sqrt((x-x0)*(x-x0)+(y-y0)*(y-y0));
726 surfaces(face) = 2.*M_PI*r;
727 }
728 break;
729 }
730 case Type_Face::polygone_3D:
731 {
732 const DoubleTab_t& coord=dom.coord_sommets();
733 int nmax=les_sommets().dimension_int(1);
734 for(int_t face=0; face <nb_faces_tot(); face++)
735 {
736 double n0=0,n1=0,n2=0;
737 int n=nmax-1;
738 while (n >= 0 && sommet(face,n)==-1) n--;
739 for (int i0=0; i0<=n; i0++)
740 {
741
742 int ip1_0=0;
743 if (i0<n) ip1_0=i0+1;
744 int_t i=sommet(face,i0);
745 int_t ip1=sommet(face,ip1_0);
746 n0+=coord(i,1)*coord(ip1,2)-coord(i,2)*coord(ip1,1);
747 n1+=coord(i,2)*coord(ip1,0)-coord(i,0)*coord(ip1,2);
748 n2+=coord(i,0)*coord(ip1,1)-coord(i,1)*coord(ip1,0);
749 }
750 surfaces(face)=sqrt(n0*n0+n1*n1+n2*n2)/2.;
751 }
752 break;
753 }
754 default :
755 {
756 Cerr << "Error TRUST in type of Faces_32_64 not recognized " << finl;
757 exit();
758 }
759 }
760}
761
762
763/*! @brief Computes the centers of gravity of each face.
764 *
765 * @param (DoubleTab& xv) array containing the coordinates of the centers of gravity of each face. xv(i,j) contains the j-th coordinate of the center of gravity of the i-th face. The array xv is resized and assigned the parallel descriptor of the vertex array before being filled.
766 */
767template <typename _SIZE_>
769{
770 // The array xv is sized in ::calculer_centres_gravite
771 const Domaine_t& dom=domaine();
772 const DoubleTab_t& coord=dom.coord_sommets();
773 Faces_32_64::Calculer_centres_gravite(xv, type_face_, coord, sommets);
774}
775
776
777template <typename _SIZE_>
778void Faces_32_64<_SIZE_>::Calculer_centres_gravite(DoubleTab_t& xv, Type_Face type_face_, const DoubleTab_t& coord, const IntTab_t& sommet)
779{
780 int_t nb_faces_tot = sommet.dimension_tot(0);
781 int dim = coord.dimension_int(1);
782 xv.resize(nb_faces_tot, dim);
783 // Copy the parallel descriptor of the vertex array:
784 xv.set_md_vector(sommet.get_md_vector());
785
786 if(nb_faces_tot!=0)
787 {
788 int nb_som_faces=sommet.dimension_int(1);
789 double inv=1./nb_som_faces;
790 xv = 0;
791 if(Objet_U::axi)
792 {
793 switch(type_face_)
794 {
795 case Type_Face::segment_2D_axi :
796 {
797 for (int_t face=0; face<nb_faces_tot; face++)
798 {
799 for(int som=0; som < nb_som_faces; som++)
800 xv(face, 0)+=coord(sommet(face ,som), 0);
801 double teta_0=coord(sommet(face ,0), 1);
802 double teta_1=coord(sommet(face ,1), 1);
803 double teta_min=std::min(teta_1, teta_0);
804 double teta_max=std::max(teta_1, teta_0);
805 double d_teta=teta_max-teta_min;
806 if( (teta_min==0.) && (d_teta>M_PI) )
807 {
808 teta_min+=2.*M_PI;
809 }
810 {
811 xv(face, 1)+=(teta_min+teta_max);
812 }
813 }
814 break;
815 }
816 case Type_Face::quadrangle_3D_axi :
817 {
818 for (int_t face=0; face<nb_faces_tot; face++)
819 {
820 for(int som=0; som < nb_som_faces; som++)
821 xv(face, 0)+=coord(sommet(face ,som), 0);
822 for(int som=0; som < nb_som_faces; som++)
823 xv(face, 2)+=coord(sommet(face ,som), 2);
824 double teta_0=coord(sommet(face ,0), 1);
825 double teta_1=coord(sommet(face ,1), 1);
826 double teta_2=coord(sommet(face ,2), 1);
827 double teta_3=coord(sommet(face ,3), 1);
828 double teta_min=std::min(teta_1, teta_0);
829 teta_min=std::min(teta_min, teta_2);
830 teta_min=std::min(teta_min, teta_3);
831 double teta_max=std::max(teta_1, teta_0);
832 teta_max=std::max(teta_min, teta_2);
833 teta_max=std::max(teta_min, teta_3);
834 double d_teta=teta_max-teta_min;
835 if( (teta_min==0.) && (d_teta>M_PI) )
836 {
837 if(teta_0==0.) teta_0+=2.*M_PI;
838 if(teta_1==0.) teta_1+=2.*M_PI;
839 if(teta_2==0.) teta_2+=2.*M_PI;
840 if(teta_3==0.) teta_3+=2.*M_PI;
841 }
842 {
843 xv(face, 1)+=(teta_0+teta_1+teta_2+teta_3) ;
844 }
845 }
846 break;
847 }
848 default:
849 {
850 Cerr << "Face type number " << (int)type_face_ << " not provided in Faces_32_64<_SIZE_>::calculer_centres_gravite" << finl;
851 break;
852 }
853 }
854 xv*=inv;
855 }
856 else
857 {
858 for (int_t face=0; face<nb_faces_tot; face++)
859 {
860 int nb_som=nb_som_faces;
861 while (sommet(face,nb_som-1)==-1) nb_som--;
862
863 inv=1./nb_som;
864 for(int k=0; k<dim; k++)
865 for(int som=0; som < nb_som; som++)
866 xv(face, k)+=coord(sommet(face ,som), k);
867 for(int k=0; k<dim; k++)
868 xv(face, k)*=inv;
869 }
870 }
871 }
872}
873
874/*! @brief Reorders the faces.
875 *
876 * (only quadrangles are reordered)
877 *
878 * @throws unrecognized face type
879 */
880template <typename _SIZE_>
882{
883 //Cerr << "Faces_32_64<_SIZE_>::reordonner()" << finl;
884 switch(type_face_)
885 {
886 case Type_Face::point_1D :
887 case Type_Face::point_1D_axi :
888 {
889 break;
890 }
891 case Type_Face::segment_2D :
892 {
893 // one can have boundary faces from a triangular mesh in 3D
894 assert(dimension>=2);
895 break;
896 }
897 case Type_Face::quadrilatere_2D_axi :
898 {
899 assert(dimension==2);
900 const Domaine_t& dom=domaine();
901 SmallArrOfTID_t S(2);
902 SmallArrOfTID_t NS(2);
903 int i;
904 const int_t nombre_faces=nb_faces();
905 for(int_t face=0; face < nombre_faces; face++)
906 {
907 NS=-1;
908 for(i=0; i<2; i++)
909 S[i] = sommet(face, i);
910 assert( S[0] >=0 );
911 assert( S[1] >=0 );
912 if (dom.coord(S[0], 0) > dom.coord(S[1], 0))
913 {
914 NS[0]=S[1];
915 NS[1]=S[0];
916 }
917 else
918 {
919 NS[0]=S[0];
920 NS[1]=S[1];
921 }
922
923 for(i=0; i<2; i++)
924 {
925 assert(NS[i]!=-1);
926 sommet(face, i)=NS[i];
927 }
928 }
929 break;
930 }
931 case Type_Face::segment_2D_axi :
932 {
933 assert(dimension==2);
934 break;
935 }
936 case Type_Face::triangle_3D :
937 {
938 assert(dimension==3);
939 break;
940 }
941 case Type_Face::quadrangle_3D :
942 {
943 assert(dimension==3);
944 const Domaine_t& dom=domaine();
945 SmallArrOfTID_t S(4);
946 SmallArrOfTID_t NS(4);
947 int i;
948 double xmin, ymin, zmin;
949 double xmax, ymax, zmax;
950 const int_t nombre_faces=nb_faces();
951 for(int_t face=0; face < nombre_faces; face++)
952 {
953 NS=-1;
954 for(i=0; i<4; i++)
955 {
956 S[i] = sommet(face, i);
957 assert( S[i] >=0 );
958 }
959 if (1)
960 {
961 // adapted from Hexaedre_VEF::reordonne
962 const DoubleTab_t& coord=dom.les_sommets();
963 int_t s0=S[0], s1=S[1], s2=S[2], s3=S[3];
964 double x03=coord(s3,0)-coord(s0,0);
965 double y03=coord(s3,1)-coord(s0,1);
966 double z03=coord(s3,2)-coord(s0,2);
967 double x02=coord(s2,0)-coord(s0,0);
968 double y02=coord(s2,1)-coord(s0,1);
969 double z02=coord(s2,2)-coord(s0,2);
970
971 double x01=coord(s1,0)-coord(s0,0);
972 double y01=coord(s1,1)-coord(s0,1);
973 double z01=coord(s1,2)-coord(s0,2);
974
975 Vecteur3 OA(x01,y01,z01);
976 Vecteur3 OB(x03,y03,z03);
977 Vecteur3 OC(x02,y02,z02);
978
979 Vecteur3 nplan, nmedian;
980 // rectangle C B
981 // O A
982 // compute n = OA ^ OC
983 Vecteur3::produit_vectoriel(OA,OC,nplan);
984 // compute the normal nmedian of the plane (OB,n)
985 Vecteur3::produit_vectoriel(OB,nplan,nmedian);
986
987 // check that points A and C are on opposite sides of the plane
988 double psC=Vecteur3::produit_scalaire(nmedian,OA);
989 double psA=Vecteur3::produit_scalaire(nmedian,OC);
990
991 if (psA*psC>0)
992 {
993 // swap vertices 2 and 3
994 sommet(face,2)=S[3];
995 sommet(face,3)=S[2];
996 Cerr << "Permutation of local nodes 2 and 3 on the face " <<face<<finl;
997
998 }
999 }
1000 else
1001 {
1002
1003 xmin=std::min(dom.coord(S[0], 0), dom.coord(S[1], 0));
1004 xmin=std::min(xmin, dom.coord(S[2], 0));
1005 xmax=std::max(dom.coord(S[0], 0), dom.coord(S[1], 0));
1006 xmax=std::max(xmax, dom.coord(S[2], 0));
1007 ymin=std::min(dom.coord(S[0], 1), dom.coord(S[1], 1));
1008 ymin=std::min(ymin, dom.coord(S[2], 1));
1009 ymax=std::max(dom.coord(S[0], 1), dom.coord(S[1], 1));
1010 ymax=std::max(ymax, dom.coord(S[2], 1));
1011 zmin=std::min(dom.coord(S[0], 2), dom.coord(S[1], 2));
1012 zmin=std::min(zmin, dom.coord(S[2], 2));
1013 zmax=std::max(dom.coord(S[0], 2), dom.coord(S[1], 2));
1014 zmax=std::max(zmax, dom.coord(S[2], 2));
1015
1016 if(est_egal(zmin, zmax))
1017 {
1018 for(i=0; i<4; i++)
1019 if ( est_egal(dom.coord(S[i], 0),xmin) && est_egal(dom.coord(S[i], 1),ymin))
1020 NS[0]=S[i];
1021 for(i=0; i<4; i++)
1022 if ( !est_egal(dom.coord(S[i], 0),xmin) && est_egal(dom.coord(S[i], 1),ymin))
1023 NS[1]=S[i];
1024 for(i=0; i<4; i++)
1025 if ( est_egal(dom.coord(S[i], 0),xmin) && !est_egal(dom.coord(S[i], 1),ymin))
1026 NS[2]=S[i];
1027 for(i=0; i<4; i++)
1028 if ( !est_egal(dom.coord(S[i], 0),xmin) && !est_egal(dom.coord(S[i], 1),ymin))
1029 NS[3]=S[i];
1030 }
1031 if(est_egal(ymin, ymax))
1032 {
1033 for(i=0; i<4; i++)
1034 if ( est_egal(dom.coord(S[i], 0),xmin) && est_egal(dom.coord(S[i], 2),zmin))
1035 NS[0]=S[i];
1036 for(i=0; i<4; i++)
1037 if ( !est_egal(dom.coord(S[i], 0),xmin) && est_egal(dom.coord(S[i], 2),zmin))
1038 NS[1]=S[i];
1039 for(i=0; i<4; i++)
1040 if ( est_egal(dom.coord(S[i], 0),xmin) && !est_egal(dom.coord(S[i], 2),zmin))
1041 NS[2]=S[i];
1042 for(i=0; i<4; i++)
1043 if ( !est_egal(dom.coord(S[i], 0),xmin) && !est_egal(dom.coord(S[i], 2),zmin))
1044 NS[3]=S[i];
1045 }
1046 if(est_egal(xmin, xmax))
1047 {
1048 for(i=0; i<4; i++)
1049 if ( est_egal(dom.coord(S[i], 1),ymin) && est_egal(dom.coord(S[i], 2),zmin))
1050 NS[0]=S[i];
1051 for(i=0; i<4; i++)
1052 if ( !est_egal(dom.coord(S[i], 1),ymin) && est_egal(dom.coord(S[i], 2),zmin))
1053 NS[1]=S[i];
1054 for(i=0; i<4; i++)
1055 if ( est_egal(dom.coord(S[i], 1),ymin) && !est_egal(dom.coord(S[i], 2),zmin))
1056 NS[2]=S[i];
1057 for(i=0; i<4; i++)
1058 if ( !est_egal(dom.coord(S[i], 1),ymin) && !est_egal(dom.coord(S[i], 2),zmin))
1059 NS[3]=S[i];
1060 }
1061
1062 for(i=0; i<4; i++)
1063 {
1064 assert(NS[i]!=-1);
1065 sommet(face, i)=NS[i];
1066 }
1067 }
1068 }
1069 break;
1070 }
1071 case Type_Face::quadrangle_3D_axi :
1072 {
1073 assert(dimension==3);
1074 break;
1075 }
1076 case Type_Face::polygone_3D:
1077 assert(dimension==3);
1078 break;
1079 default :
1080 {
1081 Cerr << "Error TRUST in type of Faces_32_64 not recognized " << finl;
1082 exit();
1083 }
1084 }
1085}
1086
1087/*! @brief Compares the Faces_32_64 object passed as parameter with this Faces_32_64 object.
1088 *
1089 * @param (Faces_32_64& faces) the faces to compare against
1090 * @param (IntVect& renum) the renumbering vector - renum has size 1 and contains -1 if the number of faces differs; otherwise has as many elements as faces and renum(i) = the index of face i from the parameter faces in the current object
1091 * @return (IntVect&)
1092 */
1093template <typename _SIZE_>
1095{
1096 const Domaine_t& domaine = this->domaine();
1097 const Domaine_t& son_domaine=faces.domaine();
1098 if ( (nb_faces() != faces.nb_faces()) || ( type_face_ != faces.type_face_) )
1099 {
1100 renum.resize(1);
1101 renum=-1;
1102 return renum;
1103 }
1104 if(domaine.le_nom() == son_domaine.le_nom())
1105 {
1106 // just compare the vertex indices:
1107 TRUSTLists<_SIZE_> listes;
1108 int_t premier=0;
1109 int_t numerol, face;
1110 int numeroli;
1111 int ok;
1112 int_t rang;
1113 for(face=0; face<nb_faces(); face++)
1114 {
1115 numerol=this->ppsf(face, nb_som_face);
1116 assert(numerol < std::numeric_limits<int>::max());
1117 numeroli = (int)numerol;
1118 listes[numeroli].add(premier++);
1119 }
1120 for(face=0; face<nb_faces(); face++)
1121 {
1122 numerol=faces.ppsf(face, nb_som_face);
1123 assert(numerol < std::numeric_limits<int>::max());
1124 numeroli = (int)numerol;
1125 TRUSTList_Curseur<_SIZE_> curseur(listes[numeroli]);
1126 ok=1;
1127 while (curseur && ok)
1128 {
1129 rang=curseur.valeur();
1130 ok=!faces.same_face(face, *this, rang, nb_som_face);
1131 if(!ok)
1132 {
1133 // "face==rang"
1134 renum(face)=rang;
1135 }
1136 else
1137 ++curseur;
1138 }
1139 if(!curseur)
1140 {
1141 renum.resize(1);
1142 renum=-1;
1143 return renum;
1144 }
1145 }
1146 }
1147 else
1148 {
1149 // we need to compare the vertex coordinates:
1150 }
1151 return renum;
1152}
1153
1154
1155template class Faces_32_64<int>;
1156#if INT_is_64_ == 2
1157template class Faces_32_64<trustIdType>;
1158#endif
const DoubleTab_t & origine_repere()
DoubleTab_t & les_sommets()
Definition Domaine.h:113
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
double coord(int_t i, int j) const
Definition Domaine.h:110
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
Class Faces Faces describes a set of faces by their type (point, segment, triangle or quadrangle),...
Definition Faces.h:50
int_t nb_faces_tot() const
Returns the total number of Faces i (real and virtual) on the current processor.
Definition Faces.h:68
SmallArrOfTID_T< _SIZE_ > SmallArrOfTID_t
Definition Faces.h:58
void typer(const Motcle &)
Sets the type of the faces.
Definition Faces.cpp:382
void initialiser_sommets_faces_joint(int_t nb_faces_joints)
Initializes the vertices of joint faces to -1.
Definition Faces.cpp:369
void calculer_surfaces(DoubleVect_t &surf) const
Computes the surface area of the faces.
Definition Faces.cpp:487
DoubleVect_T< _SIZE_ > DoubleVect_t
Definition Faces.h:59
void reordonner()
Reorders the faces.
Definition Faces.cpp:881
Type_Face type(const Motcle &) const
Returns a Type_Face object representing the type with the specified name.
Definition Faces.cpp:199
const Domaine_t & domaine() const
Definition Faces.h:95
int_t nb_faces() const
Definition Faces.h:66
IntVect_t & compare(const Faces_32_64 &other_fac, IntVect_t &renum)
Compares the Faces_32_64 object passed as parameter with this Faces_32_64 object.
Definition Faces.cpp:1094
void completer(int_t face, int_t num_elem)
Completes the specified face: updates its neighbors.
Definition Faces.cpp:458
Entree & lit(Entree &)
Reads the specifications of a face object from an input stream (binary format).
Definition Faces.cpp:119
void calculer_centres_gravite(DoubleTab_t &xv) const
Computes the centers of gravity of each face.
Definition Faces.cpp:768
int_t dimensionner(int_t)
(Re-)sizes the faces. The neighbors are resized accordingly.
Definition Faces.cpp:336
_SIZE_ int_t
Definition Faces.h:55
Sortie & ecrit(Sortie &) const
Writes the faces to an output stream (binary format).
Definition Faces.cpp:61
IntTab_T< _SIZE_ > IntTab_t
Definition Faces.h:57
Domaine_32_64< _SIZE_ > Domaine_t
Definition Faces.h:61
int_t voisin(int_t, int) const
Returns the number of the i-th neighbor of face.
Definition Faces.h:165
IntVect_T< _SIZE_ > IntVect_t
Definition Faces.h:56
void initialiser_faces_joint(int_t nb_faces_joints)
Initializes the neighbors of joint faces to -1.
Definition Faces.cpp:357
DomaineAxi1d_32_64< _SIZE_ > DomaineAxi1d_t
Definition Faces.h:62
const IntTab_t & les_sommets() const
Returns the array of vertices of all faces.
Definition Faces.h:74
void ajouter(const IntTab_t &)
Adds faces.
Definition Faces.cpp:317
int_t sommet(int_t, int) const
Returns the number of the j-th vertex of the i-th face.
Definition Faces.h:130
DoubleTab_T< _SIZE_ > DoubleTab_t
Definition Faces.h:60
static void Calculer_centres_gravite(DoubleTab_t &xv, Type_Face type_face_, const DoubleTab_t &coord, const IntTab_t &sommet)
Definition Faces.cpp:778
int nb_som_faces() const
Returns the number of vertices per face.
Definition Faces.h:149
A character string (Nom) in uppercase.
Definition Motcle.h:26
An array of Motcle objects.
Definition Motcle.h:63
int search(const Motcle &t) const
Definition Motcle.cpp:319
Base class for TRUST objects (Objet_U).
Definition Objet_U.h:68
friend class Entree
Definition Objet_U.h:71
static int dimension
Definition Objet_U.h:94
friend class Sortie
Definition Objet_U.h:70
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
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
: List_Curseur de reels int/double precision
Definition TRUSTList.h:103
_TYPE_ valeur() const
Definition TRUSTList.h:115
: An array of lists of type IntList
Definition TRUSTLists.h:32
void set_md_vector(const MD_Vector &) override
Definition TRUSTTab.tpp:673
int dimension_int(int d) const
Definition TRUSTTab.tpp:152
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
void resize(_SIZE_, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTVect.tpp:91
static double produit_scalaire(const Vecteur3 &x, const Vecteur3 &y)
static void produit_vectoriel(const Vecteur3 &x, const Vecteur3 &y, Vecteur3 &resu)