1 /*****************************************************************************
2 *
3 * Elmer, A Finite Element Software for Multiphysical Problems
4 *
5 * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program (in file fem/GPL-2); if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 *****************************************************************************/
23
24 /*******************************************************************************
25 *
26 * Definition of three node triangle element.
27 *
28 *******************************************************************************
29 *
30 * Author: Juha Ruokolainen
31 *
32 * Address: CSC - IT Center for Science Ltd.
33 * Keilaranta 14, P.O. BOX 405
34 * 02101 Espoo, Finland
35 * Tel. +358 0 457 2723
36 * Telefax: +358 0 457 2302
37 * EMail: Juha.Ruokolainen@csc.fi
38 *
39 * Date: 20 Sep 1995
40 *
41 *
42 * Modification history:
43 *
44 * 28 Sep 1995, changed call to elm_triangle_normal to geo_triangle normal
45 * routine elm_... doesn't exist anymore
46 *
47 ******************************************************************************/
48
49 #include "../elmerpost.h"
50 #include <elements.h>
51
52 /*
53 * Three node triangular surface element
54 *
55 * 2 v=1
56 * / \
57 * / \
58 * / \
59 * 0-------1 u=1
60 *
61 */
62 static double N[3][3] =
63 {
64 { 1.0,-1.0,-1.0 },
65 { 0.0, 1.0, 0.0 },
66 { 0.0, 0.0, 1.0 }
67 };
68
69 static double NodeU[3] = { 0.0, 1.0, 0.0 };
70 static double NodeV[3] = { 0.0, 0.0, 1.0 };
71
72 /*******************************************************************************
73 *
74 * Name: elm_4node_triangle_triangulate( geometry_t *,element_t * )
75 *
76 * Purpose: Triangulate an element. The process also builds up an edge
77 * table and adds new nodes to node table. The triangulation
78 * and edge table is stored in geometry_t *geom-structure.
79 *
80 * Parameters:
81 *
82 * Input: (geometry_t *) pointer to structure holding triangulation
83 * (element_t *) element to triangulate
84 *
85 * Output: (geometry_t *) structure is modified
86 *
87 * Return value: FALSE if malloc() fails, TRUE otherwise
88 *
89 ******************************************************************************/
elm_4node_triangle_triangulate(geometry_t * geom,element_t * Elm,element_t * Parent)90 int elm_4node_triangle_triangulate( geometry_t *geom, element_t *Elm, element_t *Parent)
91 {
92 double u,v,w,s;
93
94 int i,j;
95
96 triangle_t triangle;
97
98 triangle.Element = Parent;
99 for( i=0; i<3; i++ )
100 {
101 triangle.v[i] = Elm->Topology[i];
102 triangle.Edge[i] = TRUE;
103 }
104 geo_triangle_normal( geom,&triangle );
105
106 return geo_add_triangle( geom, &triangle );
107 }
108
109 /*******************************************************************************
110 *
111 * Name: elm_4node_triangle_point_inside(
112 * double *nx,double *ny,double *nz,
113 * double px, double py, double pz,
114 * double *u,double *v,double *w )
115 *
116 * Purpose: Find if point (px,py,pz) is inside the element, and return
117 * element coordinates of the point.
118 *
119 * Parameters:
120 *
121 * Input: (double *) nx,ny,nz node coordinates
122 * (double) px,py,pz point to consider
123 *
124 * Output: (double *) u,v,w point in element coordinates if inside
125 *
126 * Return value: in/out status
127 *
128 * NOTES: the goal here can be hard for more involved element types. kind of
129 * trivial for this one... (TODO: this is for xy-plane tri only)
130 *
131 ******************************************************************************/
elm_4node_triangle_point_inside(double * nx,double * ny,double * nz,double px,double py,double pz,double * u,double * v,double * w)132 int elm_4node_triangle_point_inside
133 (
134 double *nx, double *ny, double *nz,
135 double px, double py, double pz, double *u,double *v,double *w
136 )
137 {
138 double A00,A01,A10,A11,B00,B01,B10,B11,detA;
139
140 if ( px > MAX(MAX( nx[0],nx[1] ),nx[2] ) ) return FALSE;
141 if ( px < MIN(MIN( nx[0],nx[1] ),nx[2] ) ) return FALSE;
142
143 if ( py > MAX(MAX( ny[0],ny[1] ),ny[2] ) ) return FALSE;
144 if ( py < MIN(MIN( ny[0],ny[1] ),ny[2] ) ) return FALSE;
145
146 #if 0
147 if ( pz > MAX(MAX( nz[0],nz[1] ),nz[2] ) ) return FALSE;
148 if ( pz < MIN(MIN( nz[0],nz[1] ),nz[2] ) ) return FALSE;
149 #endif
150
151 A00 = nx[1] - nx[0];
152 A01 = nx[2] - nx[0];
153 A10 = ny[1] - ny[0];
154 A11 = ny[2] - ny[0];
155
156 detA = A00*A11 - A01*A10;
157 if ( ABS(detA) < AEPS )
158 {
159 fprintf( stderr, "4node_triangle_inside: SINGULAR, HUH? \n" );
160 return FALSE;
161 }
162
163 detA = 1/detA;
164
165 B00 = A11*detA;
166 B10 = -A10*detA;
167 B01 = -A01*detA;
168 B11 = A00*detA;
169
170 px -= nx[0];
171 py -= ny[0];
172 *u = *v = *w = 0.0;
173
174 *u = B00*px + B01*py;
175 if ( *u < 0.0 || *u > 1.0 ) return FALSE;
176
177 *v = B10*px + B11*py;
178 if ( *v < 0.0 || *v > 1.0 ) return FALSE;
179
180 return (*u + *v) <= 1.0;
181 }
182
183 /*******************************************************************************
184 *
185 * Name: elm_4node_triangle_fvalue( double *,double,double )
186 *
187 * Purpose: return value of a quantity given on nodes at point (u,v)
188 *
189 *
190 * Parameters:
191 *
192 * Input: (double *) quantity values at nodes
193 * (double u,double v) point where value is evaluated
194 *
195 * Output: none
196 *
197 * Return value: quantity value
198 *
199 ******************************************************************************/
elm_4node_triangle_fvalue(double * F,double u,double v)200 static double elm_4node_triangle_fvalue(double *F,double u,double v)
201 {
202 return F[0]*(1-u-v) + F[1]*u + F[2]*v;
203 }
204
205 /*******************************************************************************
206 *
207 * Name: elm_4node_triangle_dndu_fvalue( double *,double,double )
208 *
209 * Purpose: return value of a first partial derivate in (u) of a
210 * quantity given on nodes at point (u,v)
211 *
212 *
213 * Parameters:
214 *
215 * Input: (double *) quantity values at nodes
216 * (double u,double v) point where value is evaluated
217 *
218 * Output: none
219 *
220 * Return value: quantity value
221 *
222 ******************************************************************************/
elm_4node_triangle_dndu_fvalue(double * F,double u,double v)223 static double elm_4node_triangle_dndu_fvalue(double *F,double u,double v)
224 {
225 return -F[0] + F[1];
226 }
227
228 /*******************************************************************************
229 *
230 * Name: elm_4node_triangle_dndv_fvalue( double *,double,double )
231 *
232 * Purpose: return value of a first partial derivate in (v) of a
233 * quantity given on nodes at point (u,v)
234 *
235 *
236 * Parameters:
237 *
238 * Input: (double *) quantity values at nodes
239 * (double u,double v) point where value is evaluated
240 *
241 * Output: none
242 *
243 * Return value: quantity value
244 *
245 ******************************************************************************/
elm_4node_triangle_dndv_fvalue(double * F,double u,double v)246 static double elm_4node_triangle_dndv_fvalue(double *F,double u,double v)
247 {
248 return -F[0] + F[2];
249 }
250
251 #define FEPS 1.0E-9
252
253 /*******************************************************************************
254 *
255 * Name: elm_4node_triangle_isoline
256 *
257 * Purpose: Extract a iso line from triangle with given threshold
258 *
259 * Parameters:
260 *
261 * Input: (double) K, contour threshold
262 * (double *) F, contour quantity
263 * (double *) C, color quantity
264 * (double *) X,Y,Z vertex coords.
265 *
266 * Output: (line_t *) place to store the line
267 *
268 * Return value: number of lines generated (0 or 1)
269 *
270 *******************************************************************************/
elm_4node_triangle_isoline(double K,double * F,double * C,double * X,double * Y,double * Z,line_t * Line)271 int elm_4node_triangle_isoline
272 (
273 double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line
274 )
275 {
276 double F0=F[0],F1=F[1],F2=F[2],t;
277 int i,n=0;
278
279 int S0 = (F0 > K);
280 int S1 = (F1 > K);
281 int S2 = (F2 > K);
282 int S = S0 + S1 + S2;
283
284 if ( S==0 || S==3 ) return 0;
285
286 if (S0 ^ S1)
287 {
288 if ( ABS(F1-F0) < FEPS ) return 0;
289 t = (K-F0)/(F1-F0);
290
291 Line->x[n] = t*(X[1] - X[0]) + X[0];
292 Line->y[n] = t*(Y[1] - Y[0]) + Y[0];
293 Line->z[n] = t*(Z[1] - Z[0]) + Z[0];
294 Line->f[n] = K;
295 if ( C ) Line->c[n] = t*(C[1] - C[0]) + C[0];
296 n++;
297 }
298
299 if (S0 ^ S2)
300 {
301 if ( ABS(F2-F0) < FEPS ) return 0;
302 t = (K-F0)/(F2-F0);
303
304 Line->x[n] = t*(X[2] - X[0]) + X[0];
305 Line->y[n] = t*(Y[2] - Y[0]) + Y[0];
306 Line->z[n] = t*(Z[2] - Z[0]) + Z[0];
307 Line->f[n] = K;
308 if ( C ) Line->c[n] = t*(C[2] - C[0]) + C[0];
309 n++;
310 }
311
312 if (S1 ^ S2)
313 {
314 if ( ABS(F2-F1) < FEPS ) return 0;
315 t = (K-F1)/(F2-F1);
316
317 Line->x[n] = t*(X[2] - X[1]) + X[1];
318 Line->y[n] = t*(Y[2] - Y[1]) + Y[1];
319 Line->z[n] = t*(Z[2] - Z[1]) + Z[1];
320 Line->f[n] = K;
321 if ( C ) Line->c[n] = t*(C[2] - C[1]) + C[1];
322 n++;
323 }
324
325 return (n>=2);
326 }
327
328
329 /*******************************************************************************
330 *
331 * Name: elm_4node_triangle_initialize()
332 *
333 * Purpose: Register the element type
334 *
335 * Parameters:
336 *
337 * Input: (char *) description of the element
338 * (int) numeric code for the element
339 *
340 * Output: Global list of element types is modified
341 *
342 * Return value: malloc() success
343 *
344 ******************************************************************************/
elm_4node_triangle_initialize()345 int elm_4node_triangle_initialize()
346 {
347 static char *Name = "ELM_4NODE_TRIANGLE";
348
349 element_type_t ElementDef;
350
351 ElementDef.ElementName = Name;
352 ElementDef.ElementCode = 304;
353
354 ElementDef.NumberOfNodes = 4;
355
356 ElementDef.NodeU = NodeU;
357 ElementDef.NodeV = NodeV;
358 ElementDef.NodeW = NULL;
359
360 ElementDef.PartialU = (double (*)())elm_4node_triangle_dndu_fvalue;
361 ElementDef.PartialV = (double (*)())elm_4node_triangle_dndv_fvalue;
362 ElementDef.PartialW = (double (*)())NULL;
363
364 ElementDef.FunctionValue = (double (*)())elm_4node_triangle_fvalue;
365 ElementDef.Triangulate = (int (*)())elm_4node_triangle_triangulate;
366 ElementDef.IsoLine = (int (*)())elm_4node_triangle_isoline;
367 ElementDef.PointInside = (int (*)())elm_4node_triangle_point_inside;
368 ElementDef.IsoSurface = (int (*)())NULL;
369
370 return elm_add_element_type( &ElementDef ) ;
371 }
372