TrioCFD 1.9.9_beta
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 Returns the LML name of a tetrahedron = "TETRA4".
46 *
47 * @return Always equal to "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 1 if the point belongs to the tetrahedron, 0 otherwise.
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 Returns 1 if element "ielem" of the domain associated with this geometric element contains the point with coordinates "pos". Returns 0 otherwise.
109 *
110 * @param pos Coordinates of the point to locate.
111 * @param ielem Index of the domain element in which to search for the point.
112 * @return 1 if the point belongs to element "ielem", 0 otherwise.
113 */
114template <typename _SIZE_>
115int Tetraedre_32_64<_SIZE_>::contient(const ArrOfDouble& pos, int_t ielem) const
116{
117 // 29/01/2010 CPU optimisation of this method (50% faster) by PL
118 assert(pos.size_array()==3);
119 const Domaine_t& domaine=mon_dom.valeur();
120 const DoubleTab_t& coord=domaine.coord_sommets();
121
122 int_t som0 = domaine.sommet_elem(ielem,0);
123 int_t som1 = domaine.sommet_elem(ielem,1);
124 int_t som2 = domaine.sommet_elem(ielem,2);
125 int_t som3 = domaine.sommet_elem(ielem,3);
126 double X0 = coord(som0,0);
127 double Y0 = coord(som0,1);
128 double Z0 = coord(som0,2);
129 double X1 = coord(som1,0);
130 double Y1 = coord(som1,1);
131 double Z1 = coord(som1,2);
132 double X2 = coord(som2,0);
133 double Y2 = coord(som2,1);
134 double Z2 = coord(som2,2);
135 double X3 = coord(som3,0);
136 double Y3 = coord(som3,1);
137 double Z3 = coord(som3,2);
138
139 // Here we used to test if the point was one of the vertexes of the tetra using est_egal
140 // probably not worth it, happened in 0.03% of test cases according to gcov
141 // must mean we rarely lookup for a point of the mesh using this function
142
143
144 // However, it might be worth to check a simpler distance to center of tetra first
145 // 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)
146 // depending on usage of this function, may avoid testing on each face in a lot of cases
147
148 // Now we do the real work
149 // For a point to be inside a tetra, for each face made of three of the 4 vertexes
150 // the point must be on the same side as the fourth vertex
151 // We test that with the function is_on_same_side_of_plane defined in this file
152
153
154 // test som3 and pos are on same side
155 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]))
156 {
157 return false;
158 }
159
160 // test som2 and pos are on same side
161 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]))
162 {
163 return false;
164 }
165
166 // test som1 and pos are on same side
167 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]))
168 {
169 return false;
170 }
171
172 // test som0 and pos are on same side
173 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]))
174 {
175 return false;
176 }
177
178 return true;
179
180}
181
182
183/*! @brief Returns 1 if the vertices specified by "som" are the vertices of element "element"
184 *
185 * in the domain associated with this geometric element. Returns 0 otherwise.
186 *
187 * @param som Vertex indices to compare with those of element "element".
188 * @param element Index of the domain element whose vertices are to be compared.
189 * @return 1 if the specified vertices are those of the given element, 0 otherwise.
190 */
191template <typename _SIZE_>
193{
194 const Domaine_t& domaine=mon_dom.valeur();
195 if((domaine.sommet_elem(element,0)==som[0])&&
196 (domaine.sommet_elem(element,1)==som[1])&&
197 (domaine.sommet_elem(element,1)==som[2])&&
198 (domaine.sommet_elem(element,1)==som[3]))
199 return 1;
200 else
201 return 0;
202}
203
204/*! @brief Computes the volumes of the elements of the associated domain.
205 *
206 * @param tab_volumes Vector to fill with the volumes of domain elements.
207 */
208template <typename _SIZE_>
210{
211 const Domaine_t& domaine=mon_dom.valeur();
212
213 int_t size_tot = domaine.nb_elem_tot();
214 assert(tab_volumes.size_totale()==size_tot);
215 ConstView<_SIZE_,2> les_Polys = domaine.les_elems().view_ro();
216 CDoubleTabView coord = domaine.coord_sommets().view_ro();
217 auto volumes = tab_volumes.view_wo();
218 Kokkos::parallel_for(start_gpu_timer(__KERNEL_NAME__), size_tot, KOKKOS_LAMBDA(const int_t num_poly)
219 {
220 int_t s0 = les_Polys(num_poly, 0);
221 int_t s1 = les_Polys(num_poly, 1);
222 int_t s2 = les_Polys(num_poly, 2);
223 int_t s3 = les_Polys(num_poly, 3);
224 double x0 = coord(s0, 0), y0 = coord(s0, 1), z0 = coord(s0, 2);
225 double x1 = coord(s1, 0), y1 = coord(s1, 1), z1 = coord(s1, 2);
226 double x2 = coord(s2, 0), y2 = coord(s2, 1), z2 = coord(s2, 2);
227 double x3 = coord(s3, 0), y3 = coord(s3, 1), z3 = coord(s3, 2);
228 volumes(num_poly) = Kokkos::fabs((x1-x0)*((y2-y0)*(z3-z0)-(y3-y0)*(z2-z0))-
229 (x2-x0)*((y1-y0)*(z3-z0)-(y3-y0)*(z1-z0))+
230 (x3-x0)*((y1-y0)*(z2-z0)-(y2-y0)*(z1-z0)))/6;
231 });
232 end_gpu_timer(__KERNEL_NAME__);
233}
234
235
236/*! @brief Computes the face normals of the elements of the associated domain.
237 *
238 * @param Face_sommets Vertex indices of the faces in the domain vertex list.
239 * @param face_normales Output array to fill with face normals.
240 */
241template <typename _SIZE_>
242void Tetraedre_32_64<_SIZE_>::calculer_normales(const IntTab_t& Face_sommets, DoubleTab_t& face_normales) const
243{
244 const Domaine_t& domaine_geom = mon_dom.valeur();
245 const DoubleTab_t& les_coords = domaine_geom.coord_sommets();
246 int_t nbfaces = Face_sommets.dimension(0);
247 for (int_t numface=0; numface<nbfaces; numface++)
248 {
249
250 int_t n0 = Face_sommets(numface,0);
251 int_t n1 = Face_sommets(numface,1);
252 int_t n2 = Face_sommets(numface,2);
253
254 double x1 = les_coords(n0,0) - les_coords(n1,0);
255 double y1 = les_coords(n0,1) - les_coords(n1,1);
256 double z1 = les_coords(n0,2) - les_coords(n1,2);
257
258 double x2 = les_coords(n2,0) - les_coords(n1,0);
259 double y2 = les_coords(n2,1) - les_coords(n1,1);
260 double z2 = les_coords(n2,2) - les_coords(n1,2);
261
262 face_normales(numface,0) = (y1*z2 - y2*z1)/2;
263 face_normales(numface,1) = (-x1*z2 + x2*z1)/2;
264 face_normales(numface,2) = (x1*y2 - x2*y1)/2;
265 }
266}
267
268/*! @brief See ElemGeomBase::get_tab_faces_sommets_locaux.
269 */
270template <typename _SIZE_>
272{
273 // a tetrahedron has four faces of three vertices each
274 faces_som_local.resize(4,3);
275 for (int i=0; i<4; i++)
276 for (int j=0; j<3; j++)
277 faces_som_local(i,j) = faces_sommets_tetra[i][j];
278 return 1;
279}
280
281template <typename _SIZE_>
283{
284 // a tetrahedron has six edges of two vertices each
285 tab.resize(6, 2);
286 int count = 0;
287 // one edge between each pair of tetra vertices: n * (n-1) / 2 edges with n=4
288 for (int i = 0; i < 3; i++)
289 {
290 for (int j = i + 1; j < 4; j++)
291 {
292 tab(count, 0) = i;
293 tab(count, 1) = j;
294 count++;
295 }
296 }
297 assert(count == 6);
298}
299
300
301///*! Computes the barycentric coordinate in a tetrahedron corresponding to a
302// * Cartesian coordinate "point". Note: if "point" is outside the tetra, one or more
303// * barycentric coordinates will be negative.
304// * polys is the tetrahedron connectivity table (vertex indices),
305// * coords is the vertex coordinate table,
306// * le_poly is the tetrahedron index whose barycentric coordinates are to be computed.
307// *
308// * The result is stored in coord_bary (weights of the first three vertices,
309// * the fourth being implicitly 1 minus the sum of the other three).
310// * If epsilon is non-zero, the return value is the uncertainty on the barycentric
311// * coordinates for an uncertainty epsilon on the Cartesian coordinates.
312// * (computed in Linfini norm, i.e. the max error over each component)
313// */
314//template <typename _SIZE_>
315//double Tetraedre_32_64<_SIZE_>::coord_bary(const IntTab& polys, const DoubleTab& coords,
316// const Vecteur3& point, int le_poly, Vecteur3& coord_bary, double epsilon)
317//{
318// Matrice33 m;
319// Vecteur3 origine;
320// matrice_base_tetraedre(polys, coords, le_poly, m, origine);
321// Matrice33 inverse_m;
322// Matrice33::inverse(m, inverse_m);
323// Vecteur3 v(point-origine);
324// Matrice33::produit(inverse_m, v, coord_bary);
325//
326// double resu;
327// if (epsilon > 0.)
328// {
329// // An error epsilon on the "point" coordinate results in an error on coord_bary:
330// double norm = inverse_m.norme_Linfini();
331// resu = norm * epsilon;
332// }
333// else
334// {
335// resu = 0.;
336// }
337// return resu;
338//}
339
340
341template class Tetraedre_32_64<int>;
342#if INT_is_64_ == 2
343template class Tetraedre_32_64<trustIdType>;
344#endif
345
const DoubleTab_t & coord_sommets() const
Definition Domaine.h:112
Class Elem_geom_base This class is the base class for the definition of elements.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
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
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
Base class for output streams.
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
Tetraedre class — represents the tetrahedral geometric element.
Definition Tetraedre.h:31
void calculer_volumes(DoubleVect_t &vols) const override
Computes the volumes of the elements of the associated domain.
int contient(const ArrOfDouble &pos, int_t elem) const override
Returns 1 if element "ielem" of the domain associated with this geometric element contains the point ...
Domaine_32_64< _SIZE_ > Domaine_t
Definition Tetraedre.h:41
int get_tab_faces_sommets_locaux(IntTab &faces_som_local) const override
See 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
Same as Elem_geom_base::get_tab_faces_sommets_locaux but for edges: aretes_som_local.
const Nom & nom_lml() const override
Returns the LML name of a tetrahedron = "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
Computes the face normals of the elements of the associated domain.