Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/elements/3node_triangle.c
3203 views
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: [email protected]
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_3node_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
******************************************************************************/
90
int elm_3node_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_3node_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
******************************************************************************/
132
int elm_3node_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, "3node_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_3node_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
******************************************************************************/
200
static double elm_3node_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_3node_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
******************************************************************************/
223
static double elm_3node_triangle_dndu_fvalue(double *F,double u,double v)
224
{
225
return -F[0] + F[1];
226
}
227
228
/*******************************************************************************
229
*
230
* Name: elm_3node_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
******************************************************************************/
246
static double elm_3node_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_3node_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
*******************************************************************************/
271
int elm_3node_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_3node_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
******************************************************************************/
345
int elm_3node_triangle_initialize()
346
{
347
static char *Name = "ELM_3NODE_TRIANGLE";
348
349
element_type_t ElementDef;
350
int elm_add_element_type();
351
352
ElementDef.ElementName = Name;
353
ElementDef.ElementCode = 303;
354
355
ElementDef.NumberOfNodes = 3;
356
357
ElementDef.NodeU = NodeU;
358
ElementDef.NodeV = NodeV;
359
ElementDef.NodeW = NULL;
360
361
ElementDef.PartialU = (double (*)())elm_3node_triangle_dndu_fvalue;
362
ElementDef.PartialV = (double (*)())elm_3node_triangle_dndv_fvalue;
363
ElementDef.PartialW = (double (*)())NULL;
364
365
ElementDef.FunctionValue = (double (*)())elm_3node_triangle_fvalue;
366
ElementDef.Triangulate = (int (*)())elm_3node_triangle_triangulate;
367
ElementDef.IsoLine = (int (*)())elm_3node_triangle_isoline;
368
ElementDef.PointInside = (int (*)())elm_3node_triangle_point_inside;
369
ElementDef.IsoSurface = (int (*)())NULL;
370
371
return elm_add_element_type( &ElementDef ) ;
372
}
373
374