TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Tetraedre.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 <Tetraedre.h>
17#include <Domaine.h>
18#include <Linear_algebra_tools_impl.h>
19#include <algorithm>
20using std::swap;
21
22Implemente_instanciable_32_64(Tetraedre_32_64,"Tetraedre",Elem_geom_base_32_64<_T_>);
23
24static int faces_sommets_tetra[4][3] =
25{
26 { 1, 2, 3 },
27 { 2, 3, 0 },
28 { 3, 0, 1 },
29 { 0, 1, 2 }
30};
31
32template <typename _SIZE_>
34{
35 return s;
36}
37
38template <typename _SIZE_>
40{
41 return s;
42}
43
44
45/*! @brief Renvoie le nom LML d'un tetraedre = "TETRA4".
46 *
47 * @return (Nom&) toujours egal a "TETRA4"
48 */
49template <typename _SIZE_>
51{
52 static Nom nom="TETRA4";
53 return nom;
54}
55
56
57namespace
58{
59/*! @brief tests if 2 points are on the same side of a plane defined by three points
60*
61* Takes the coordinates of all points involved as arguments (5 points, so 15 arguments)
62* The order is X, Y, Z coord of a point, then next point
63*
64* The first nine arguments are for the points defining the plane (X/Y/Z 0 to 2)
65*
66* The next 6 describe the point for which we want to test they are on the same side (X3/Y3/Z3 and Mx/My/Mz)
67*
68* The use case is testing if a point M is inside a tetrahedra.
69* To do that, call this function 4 times in a row while cycling the first 4 points,
70* which must correspond to the 4 vertexes of the tetrahedra,
71* as done in function Tetraedre_32_64<_SIZE_>::contient
72* (hence the names of the arguments, which may be confusing for a different use case)
73*
74*
75*
76* @return (int) 1 si le point de coordonnees specifiees appartient a l'element ielem 0 sinon
77*/
78inline bool is_on_same_side_of_plane(const double& X0, const double& Y0, const double& Z0,
79 const double& X1, const double& Y1, const double& Z1,
80 const double& X2, const double& Y2, const double& Z2,
81 const double& X3, const double& Y3, const double& Z3,
82 const double& Mx, const double& My, const double& Mz
83 )
84{
85
86 // computes the normal vector of the plane
87 double xn = (Y1 - Y0) * (Z2 - Z0) - (Z1 - Z0) * (Y2 - Y0);
88 double yn = (Z1 - Z0) * (X2 - X0) - (X1 - X0) * (Z2 - Z0);
89 double zn = (X1 - X0) * (Y2 - Y0) - (Y1 - Y0) * (X2 - X0);
90
91 // computes the scalar product between normal vector and a vector from the plane to each of the points we want to test
92 double prod1 = xn * (X3 - X0) + yn * (Y3 - Y0) + zn * (Z3 - Z0);
93 double prod2 = xn * (Mx - X0) + yn * (My - Y0) + zn * (Mz - Z0);
94
95 // if scalar products have the same sign, the points are on the same sides
96 // we allow a slight tolerance for points very close to the plane
97 if (prod1 * prod2 < 0 && std::fabs(prod2)>std::fabs(prod1)*Objet_U::precision_geom)
98 {
99 return false;
100 }
101 else
102 {
103 return true;
104 }
105}
106}
107
108/*! @brief Renvoie 1 si l'element ielem du domaine associe a l'element geometrique contient le point
109 * de coordonnees specifiees par le parametre "pos". Renvoie 0 sinon.
110 *
111 * @param (DoubleVect& pos) coordonnees du point que l'on cherche a localiser
112 * @param (int ielem) le numero de l'element du domaine dans lequel on cherche le point.
113 * @return (int) 1 si le point de coordonnees specifiees appartient a l'element ielem 0 sinon
114 */
115template <typename _SIZE_>
116int Tetraedre_32_64<_SIZE_>::contient(const ArrOfDouble& pos, int_t ielem) const
117{
118 // 29/01/2010 Optimisation CPU de la methode (50% plus rapide) par PL
119 assert(pos.size_array()==3);
120 const Domaine_t& domaine=mon_dom.valeur();
121 const DoubleTab_t& coord=domaine.coord_sommets();
122
123 int_t som0 = domaine.sommet_elem(ielem,0);
124 int_t som1 = domaine.sommet_elem(ielem,1);
125 int_t som2 = domaine.sommet_elem(ielem,2);
126 int_t som3 = domaine.sommet_elem(ielem,3);
127 double X0 = coord(som0,0);
128 double Y0 = coord(som0,1);
129 double Z0 = coord(som0,2);
130 double X1 = coord(som1,0);
131 double Y1 = coord(som1,1);
132 double Z1 = coord(som1,2);
133 double X2 = coord(som2,0);
134 double Y2 = coord(som2,1);
135 double Z2 = coord(som2,2);
136 double X3 = coord(som3,0);
137 double Y3 = coord(som3,1);
138 double Z3 = coord(som3,2);
139
140 // Here we used to test if the point was one of the vertexes of the tetra using est_egal
141 // probably not worth it, happened in 0.03% of test cases according to gcov
142 // must mean we rarely lookup for a point of the mesh using this function
143
144
145 // However, it might be worth to check a simpler distance to center of tetra first
146 // Using some bound at which we are certain the point is outside (one that is easier to compute than circumradius preferably, don't know if that exists)
147 // depending on usage of this function, may avoid testing on each face in a lot of cases
148
149 // Now we do the real work
150 // For a point to be inside a tetra, for each face made of three of the 4 vertexes
151 // the point must be on the same side as the fourth vertex
152 // We test that with the function is_on_same_side_of_plane defined in this file
153
154
155 // test som3 and pos are on same side
156 if (not is_on_same_side_of_plane(X0, Y0, Z0, X1, Y1, Z1, X2, Y2, Z2, X3, Y3, Z3, pos[0], pos[1], pos[2]))
157 {
158 return false;
159 }
160
161 // test som2 and pos are on same side
162 if (not is_on_same_side_of_plane(X3, Y3, Z3, X0, Y0, Z0, X1, Y1, Z1, X2, Y2, Z2, pos[0], pos[1], pos[2]))
163 {
164 return false;
165 }
166
167 // test som1 and pos are on same side
168 if (not is_on_same_side_of_plane(X2, Y2, Z2, X3, Y3, Z3, X0, Y0, Z0, X1, Y1, Z1, pos[0], pos[1], pos[2]))
169 {
170 return false;
171 }
172
173 // test som0 and pos are on same side
174 if (not is_on_same_side_of_plane(X1, Y1, Z1, X2, Y2, Z2, X3, Y3, Z3, X0, Y0, Z0, pos[0], pos[1], pos[2]))
175 {
176 return false;
177 }
178
179 return true;
180
181}
182
183
184/*! @brief Renvoie 1 si les sommets specifies par le parametre "pos" sont les sommets de l'element "element" du domaine associe a
185 *
186 * l'element geometrique.
187 *
188 * @param (IntVect& pos) les numeros des sommets a comparer avec ceux de l'elements "element"
189 * @param (int element) le numero de l'element du domaine dont on veut comparer les sommets
190 * @return (int) 1 si les sommets passes en parametre sont ceux de l'element specifie, 0 sinon
191 */
192template <typename _SIZE_>
194{
195 const Domaine_t& domaine=mon_dom.valeur();
196 if((domaine.sommet_elem(element,0)==som[0])&&
197 (domaine.sommet_elem(element,1)==som[1])&&
198 (domaine.sommet_elem(element,1)==som[2])&&
199 (domaine.sommet_elem(element,1)==som[3]))
200 return 1;
201 else
202 return 0;
203}
204
205/*! @brief Calcule les volumes des elements du domaine associe.
206 *
207 * @param (DoubleVect& volumes) le vecteur contenant les valeurs des des volumes des elements du domaine
208 */
209template <typename _SIZE_>
211{
212 const Domaine_t& domaine=mon_dom.valeur();
213
214 int_t size_tot = domaine.nb_elem_tot();
215 assert(tab_volumes.size_totale()==size_tot);
216 ConstView<_SIZE_,2> les_Polys = domaine.les_elems().view_ro();
217 CDoubleTabView coord = domaine.coord_sommets().view_ro();
218 auto volumes = tab_volumes.view_wo();
219 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), size_tot, KOKKOS_LAMBDA(const int_t num_poly)
220 {
221 int_t s0 = les_Polys(num_poly, 0);
222 int_t s1 = les_Polys(num_poly, 1);
223 int_t s2 = les_Polys(num_poly, 2);
224 int_t s3 = les_Polys(num_poly, 3);
225 double x0 = coord(s0, 0), y0 = coord(s0, 1), z0 = coord(s0, 2);
226 double x1 = coord(s1, 0), y1 = coord(s1, 1), z1 = coord(s1, 2);
227 double x2 = coord(s2, 0), y2 = coord(s2, 1), z2 = coord(s2, 2);
228 double x3 = coord(s3, 0), y3 = coord(s3, 1), z3 = coord(s3, 2);
229 volumes(num_poly) = Kokkos::fabs((x1-x0)*((y2-y0)*(z3-z0)-(y3-y0)*(z2-z0))-
230 (x2-x0)*((y1-y0)*(z3-z0)-(y3-y0)*(z1-z0))+
231 (x3-x0)*((y1-y0)*(z2-z0)-(y2-y0)*(z1-z0)))/6;
232 });
233 end_gpu_timer(__KERNEL_NAME__);
234}
235
236
237/*! @brief Calcule les normales aux faces des elements du domaine associe.
238 *
239 * @param (IntTab& face_sommets) les numeros des sommets des faces dans la liste des sommets du domaine associe
240 * @param (DoubleTab& face_normales)
241 */
242template <typename _SIZE_>
243void Tetraedre_32_64<_SIZE_>::calculer_normales(const IntTab_t& Face_sommets, DoubleTab_t& face_normales) const
244{
245 const Domaine_t& domaine_geom = mon_dom.valeur();
246 const DoubleTab_t& les_coords = domaine_geom.coord_sommets();
247 int_t nbfaces = Face_sommets.dimension(0);
248 for (int_t numface=0; numface<nbfaces; numface++)
249 {
250
251 int_t n0 = Face_sommets(numface,0);
252 int_t n1 = Face_sommets(numface,1);
253 int_t n2 = Face_sommets(numface,2);
254
255 double x1 = les_coords(n0,0) - les_coords(n1,0);
256 double y1 = les_coords(n0,1) - les_coords(n1,1);
257 double z1 = les_coords(n0,2) - les_coords(n1,2);
258
259 double x2 = les_coords(n2,0) - les_coords(n1,0);
260 double y2 = les_coords(n2,1) - les_coords(n1,1);
261 double z2 = les_coords(n2,2) - les_coords(n1,2);
262
263 face_normales(numface,0) = (y1*z2 - y2*z1)/2;
264 face_normales(numface,1) = (-x1*z2 + x2*z1)/2;
265 face_normales(numface,2) = (x1*y2 - x2*y1)/2;
266 }
267}
268
269/*! @brief voir ElemGeomBase::get_tab_faces_sommets_locaux
270 */
271template <typename _SIZE_>
273{
274 // un tetraedre a quatre faces de trois sommets
275 faces_som_local.resize(4,3);
276 for (int i=0; i<4; i++)
277 for (int j=0; j<3; j++)
278 faces_som_local(i,j) = faces_sommets_tetra[i][j];
279 return 1;
280}
281
282template <typename _SIZE_>
284{
285 // un tetraedre a six aretes de deux sommets
286 tab.resize(6, 2);
287 int count = 0;
288 // Une arete entre chaque couple de sommet du tetra: n * (n-1) / 2 aretes avec n=4
289 for (int i = 0; i < 3; i++)
290 {
291 for (int j = i + 1; j < 4; j++)
292 {
293 tab(count, 0) = i;
294 tab(count, 1) = j;
295 count++;
296 }
297 }
298 assert(count == 6);
299}
300
301
302///*! Calcul de la coordonnee baryrentrique dans un tetra correspondant a une coordonnee
303// * cartesienne "point". Attention, si "point" est en dehors du tetra, une ou plusieurs
304// * coordonnees barycentriques seront negatives !
305// * polys est le tableau des tetraedres (indices de sommets),
306// * coords est le tableau des coordonnees des sommets,
307// * le_poly est le numero du tetraetre point la coordonnees du point a transformer
308// *
309// * On stocke le resultat dans coord_bary (poids des trois premiers sommets,
310// * le quatrieme etant implicitement 1 moins la somme des trois autres)
311// * Si epsilon est non nul, la valeur de retour est l'incertitude sur les coordonnees
312// * barycentriques, pour une incertitude epsilon sur les coordonnees carthesiennes.
313// * (calcul en norme Linfini, c'est a dire le max des erreurs sur chaque composantes)
314// */
315//template <typename _SIZE_>
316//double Tetraedre_32_64<_SIZE_>::coord_bary(const IntTab& polys, const DoubleTab& coords,
317// const Vecteur3& point, int le_poly, Vecteur3& coord_bary, double epsilon)
318//{
319// Matrice33 m;
320// Vecteur3 origine;
321// matrice_base_tetraedre(polys, coords, le_poly, m, origine);
322// Matrice33 inverse_m;
323// Matrice33::inverse(m, inverse_m);
324// Vecteur3 v(point-origine);
325// Matrice33::produit(inverse_m, v, coord_bary);
326//
327// double resu;
328// if (epsilon > 0.)
329// {
330// // Une erreur epsilon sur la coordonnee "point" entraine une erreur sur coord_bary:
331// double norm = inverse_m.norme_Linfini();
332// resu = norm * epsilon;
333// }
334// else
335// {
336// resu = 0.;
337// }
338// return resu;
339//}
340
341
342template class Tetraedre_32_64<int>;
343#if INT_is_64_ == 2
344template class Tetraedre_32_64<trustIdType>;
345#endif
346
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
Classe Elem_geom_base Cette classe est la classe de base pour la definition d'elements.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
static double precision_geom
Definition Objet_U.h:86
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Classe de base des flux de sortie.
Definition Sortie.h:52
_SIZE_ size_array() const
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
Classe Tetraedre Cette classe represente l'element geometrique Tetraedre.
Definition Tetraedre.h:31
void calculer_volumes(DoubleVect_t &vols) const override
Calcule les volumes des elements du domaine associe.
int contient(const ArrOfDouble &pos, int_t elem) const override
Renvoie 1 si l'element ielem du domaine associe a l'element geometrique contient le point de coordonn...
Domaine_32_64< _SIZE_ > Domaine_t
Definition Tetraedre.h:41
int get_tab_faces_sommets_locaux(IntTab &faces_som_local) const override
voir ElemGeomBase::get_tab_faces_sommets_locaux
IntTab_T< _SIZE_ > IntTab_t
Definition Tetraedre.h:37
void get_tab_aretes_sommets_locaux(IntTab &aretes_som_local) const override
idem que Elem_geom_base::get_tab_faces_sommets_locaux mais pour les aretes: aretes_som_local.
const Nom & nom_lml() const override
Renvoie le nom LML d'un tetraedre = "TETRA4".
Definition Tetraedre.cpp:50
DoubleTab_T< _SIZE_ > DoubleTab_t
Definition Tetraedre.h:40
SmallArrOfTID_T< _SIZE_ > SmallArrOfTID_t
Definition Tetraedre.h:38
DoubleVect_T< _SIZE_ > DoubleVect_t
Definition Tetraedre.h:39
void calculer_normales(const IntTab_t &faces_sommets, DoubleTab_t &face_normales) const override
Calcule les normales aux faces des elements du domaine associe.