Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/elements/10node_tetra.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 10 node tetra 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: 4 Oct 1995
40
*
41
******************************************************************************/
42
43
#include "../elmerpost.h"
44
#include "elements.h"
45
46
47
/*
48
* 10 node tetra volume element.
49
*
50
*/
51
52
static double A[10][10],N[10][10];
53
54
static double NodeU[] = { 0.0, 1.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.5, 0.0 };
55
static double NodeV[] = { 0.0, 0.0, 1.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.5 };
56
static double NodeW[] = { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5 };
57
58
/*******************************************************************************
59
*
60
* Name: elm_10node_tetra_triangulate
61
*
62
* Purpose: Triangulate an element. The process also builds up an edge
63
* table and adds new nodes to node table. The triangulation
64
* and edge table is stored in geometry_t *geom-structure.
65
*
66
* Parameters:
67
*
68
* Input: (geometry_t *) pointer to structure holding triangulation
69
* (element_t *) element to triangulate
70
*
71
* Output: (geometry_t *) structure is modified
72
*
73
* Return value: FALSE if malloc() fails, TRUE otherwise
74
*
75
******************************************************************************/
76
static int elm_10node_tetra_triangulate( geometry_t *geom,element_t *tetra )
77
{
78
element_t triangle;
79
int i,j;
80
81
if ( GlobalOptions.VolumeSides )
82
{
83
int topo[7];
84
85
triangle.DisplayFlag = TRUE;
86
triangle.Topology = topo;
87
for( i=0; i<MAX_GROUP_IDS; i++ ) triangle.GroupIds[i] = tetra->GroupIds[i];
88
89
for( i=0; i<4; i++ )
90
{
91
int elm_6node_triangle_triangulate();
92
for( j=0; j<6; j++ )
93
{
94
triangle.Topology[j] = tetra->Topology[ElmTetraFace[i][j]];
95
}
96
if ( !elm_6node_triangle_triangulate( geom, &triangle, tetra ) ) return FALSE;
97
}
98
} else {
99
int geo_add_edge();
100
if ( !geo_add_edge( geom, tetra->Topology[0],tetra->Topology[4],tetra ) ) return FALSE;
101
if ( !geo_add_edge( geom, tetra->Topology[4],tetra->Topology[1],tetra ) ) return FALSE;
102
if ( !geo_add_edge( geom, tetra->Topology[1],tetra->Topology[5],tetra ) ) return FALSE;
103
if ( !geo_add_edge( geom, tetra->Topology[5],tetra->Topology[2],tetra ) ) return FALSE;
104
if ( !geo_add_edge( geom, tetra->Topology[2],tetra->Topology[6],tetra ) ) return FALSE;
105
if ( !geo_add_edge( geom, tetra->Topology[6],tetra->Topology[0],tetra ) ) return FALSE;
106
if ( !geo_add_edge( geom, tetra->Topology[0],tetra->Topology[7],tetra ) ) return FALSE;
107
if ( !geo_add_edge( geom, tetra->Topology[7],tetra->Topology[3],tetra ) ) return FALSE;
108
if ( !geo_add_edge( geom, tetra->Topology[1],tetra->Topology[8],tetra ) ) return FALSE;
109
if ( !geo_add_edge( geom, tetra->Topology[8],tetra->Topology[3],tetra ) ) return FALSE;
110
if ( !geo_add_edge( geom, tetra->Topology[2],tetra->Topology[9],tetra ) ) return FALSE;
111
if ( !geo_add_edge( geom, tetra->Topology[9],tetra->Topology[3],tetra ) ) return FALSE;
112
}
113
114
return TRUE;
115
}
116
117
/*******************************************************************************
118
*
119
* Name: elm_10node_tetra_point_inside
120
* (
121
* double *nx,double *ny,double *nz,
122
* double px,double py,double pz,
123
* double *u, double *v, double *w
124
* )
125
*
126
* Purpose: Find if point (px,py,pz) is inside the element, and return
127
* element coordinates of the point.
128
*
129
* Parameters:
130
*
131
* Input: (double *) nx,ny,nz n coordinates
132
* (double) px,py,pz point to consider
133
*
134
* Output: (double *) u,v,w point in element coordinates if inside
135
*
136
* Return value: in/out status
137
*
138
* NOTES: the goal here can be hard for more involved element types.
139
* TODO: SUBDIVISION...
140
*
141
******************************************************************************/
142
int elm_10node_tetra_point_inside
143
(
144
double *nx, double *ny, double *nz,
145
double px, double py, double pz, double *u,double *v,double *w
146
)
147
{
148
int elm_4node_tetra_point_inside();
149
return elm_4node_tetra_point_inside( nx,ny,nz,px,py,pz,u,v,w );
150
}
151
152
/*******************************************************************************
153
*
154
* Name: elm_10node_tetra_isosurface
155
*
156
* Purpose: Extract isosurfaces for element
157
*
158
* Parameters:
159
*
160
* Input: (double ) K: contour threshold
161
* (double *) F: contour quantity values at nodes
162
* (double *) C: color quantity values at nodes
163
* (double *) X,Y,Z: node coordinates
164
* (double *) U,V,W: normal vector at nodes
165
*
166
* Output: (polygon_t *)Polygon, output triangles (0,1 or 2) triangles
167
*
168
* Return value: How many triangles we've got..., TODO: SUBDIVISION
169
*
170
******************************************************************************/
171
int elm_10node_tetra_isosurface
172
(
173
double K,double *F,double *C, double *X,double *Y,double *Z,
174
double *U,double *V,double *W, polygon_t *Polygon
175
)
176
{
177
int elm_4node_tetra_isosurface();
178
return elm_4node_tetra_isosurface( K,F,C,X,Y,Z,U,V,W,Polygon );
179
}
180
181
/*******************************************************************************
182
*
183
* Name: elm_10node_tetra_shape_functions
184
*
185
* Purpose: Initialize element shape function array. Internal only.
186
*
187
* Parameters:
188
*
189
* Input: Global (filewise) variables NodeU,NodeV,NodeW
190
*
191
* Output: Global (filewise) variable N[4][4], will contain
192
* shape function coefficients
193
*
194
* Return value: void
195
*
196
******************************************************************************/
197
static void elm_10node_tetra_shape_functions()
198
{
199
double u,v,w;
200
int i,j;
201
202
for( i=0; i<10; i++ )
203
{
204
u = NodeU[i];
205
v = NodeV[i];
206
w = NodeW[i];
207
208
A[i][0] = 1;
209
A[i][1] = u;
210
A[i][2] = v;
211
A[i][3] = w;
212
A[i][4] = u*u;
213
A[i][5] = v*v;
214
A[i][6] = w*w;
215
A[i][7] = u*v;
216
A[i][8] = u*w;
217
A[i][9] = v*w;
218
}
219
220
lu_mtrinv( (double *)A,10 );
221
222
for( i=0; i<10; i++ )
223
for( j=0; j<10; j++ ) N[i][j] = A[j][i];
224
}
225
226
/*******************************************************************************
227
*
228
* Name: elm_10node_tetra_fvalue
229
*
230
* Purpose: return value of a quantity given on nodes at point (u,v)
231
* Use trough (element_type_t *) structure.
232
*
233
* Parameters:
234
*
235
* Input: (double *) quantity values at nodes
236
* (double u,double v) point where values are evaluated
237
*
238
* Output: none
239
*
240
* Return value: quantity value
241
*
242
******************************************************************************/
243
static double elm_10node_tetra_fvalue(double *F,double u,double v,double w)
244
{
245
double R=0.0,uu=u*u,vv=v*v,ww=w*w,uv=u*v,uw=u*w,vw=v*w;
246
int i;
247
248
for( i=0; i<10; i++ )
249
{
250
R += F[i]*( N[i][0] +
251
N[i][1]*u +
252
N[i][2]*v +
253
N[i][3]*w +
254
N[i][4]*uu +
255
N[i][5]*vv +
256
N[i][6]*ww +
257
N[i][7]*uv +
258
N[i][8]*uw +
259
N[i][9]*vw );
260
}
261
262
return R;
263
}
264
265
/*******************************************************************************
266
*
267
* Name: elm_10node_tetra_dndu_fvalue
268
*
269
* Purpose: return value of a first partial derivate in (v) of a
270
* quantity given on nodes at point (u,v).
271
* Use trough (element_type_t *) structure.
272
*
273
*
274
* Parameters:
275
*
276
* Input: (double *) quantity values at nodes
277
* (double u,double v,double w) point where values are evaluated
278
*
279
* Output: none
280
*
281
* Return value: quantity value
282
*
283
******************************************************************************/
284
static double elm_10node_tetra_dndu_fvalue(double *F,double u,double v,double w)
285
{
286
double R=0.0,u2=2*u;
287
int i;
288
289
for( i=0; i<10; i++ )
290
{
291
R += F[i]*( N[i][1]+
292
N[i][4]*u2 +
293
N[i][7]*v +
294
N[i][8]*w );
295
}
296
297
return R;
298
}
299
300
/*******************************************************************************
301
*
302
* Name: elm_10node_tetra_dndv_fvalue
303
*
304
* Purpose: return value of a first partial derivate in (v) of a
305
* quantity given on nodes at point (u,v,w).
306
* Use trough (element_type_t *) structure.
307
*
308
*
309
* Parameters:
310
*
311
* Input: (double *) quantity values at nodes
312
* (double u,double v,double w) point where values are evaluated
313
*
314
* Output: none
315
*
316
* Return value: quantity value
317
*
318
******************************************************************************/
319
static double elm_10node_tetra_dndv_fvalue(double *F,double u,double v,double w)
320
{
321
double R=0.0,v2=2*v;
322
int i;
323
324
for( i=0; i<10; i++ )
325
{
326
R += F[i]*( N[i][2] +
327
N[i][5]*v2 +
328
N[i][7]*u +
329
N[i][9]*w );
330
}
331
332
return R;
333
}
334
335
/*******************************************************************************
336
*
337
* Name: elm_10node_tetra_dndw_fvalue
338
*
339
* Purpose: return value of a first partial derivate in (w) of a
340
* quantity given on nodes at point (u,v,w)
341
* Use trough (element_type_t *) structure.
342
*
343
*
344
* Parameters:
345
*
346
* Input: (double *) quantity values at nodes
347
* (double u,double v,double w) point where values are evaluated
348
*
349
* Output: none
350
*
351
* Return value: quantity value
352
*
353
******************************************************************************/
354
static double elm_10node_tetra_dndw_fvalue(double *F,double u,double v,double w)
355
{
356
double R=0.0,w2=2*w;
357
int i;
358
359
for( i=0; i<10; i++ )
360
{
361
R += F[i]*( N[i][3] +
362
N[i][6]*w2 +
363
N[i][8]*u +
364
N[i][9]*v );
365
}
366
367
return R;
368
}
369
370
/*******************************************************************************
371
*
372
* Name: elm_10node_tetra_isoline
373
*
374
* Purpose: Extract a iso line from triangle with given threshold
375
*
376
* Parameters:
377
*
378
* Input: (double) K, contour threshold
379
* (double *) F, contour quantity
380
* (double *) C, color quantity
381
* (double *) X,Y,Z vertex coords.
382
*
383
* Output: (line_t *) place to store the line
384
*
385
* Return value: number of lines generated (0,...,24)
386
*
387
******************************************************************************/
388
static int elm_10node_tetra_isoline
389
(
390
double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line
391
)
392
{
393
double f[6],c[6],x[6],y[6],z[6];
394
395
int i, j, k, n=0, above=0;
396
397
for( i=0; i<10; i++ ) above += F[i]>K;
398
if ( above == 0 || above == 10 ) return 0;
399
400
for( i=0; i<4; i++ )
401
{
402
int elm_6node_triangle_isoline();
403
for( j=0; j<6; j++ )
404
{
405
k = ElmTetraFace[i][j];
406
f[j] = F[k];
407
c[j] = C[k];
408
x[j] = X[k];
409
y[j] = Y[k];
410
z[j] = Z[k];
411
}
412
n += elm_6node_triangle_isoline( K,f,c,x,y,z,&Line[n] );
413
}
414
415
return n;
416
}
417
418
419
/******************************************************************************
420
*
421
* Name: elm_10node_tetra_initialize
422
*
423
* Purpose: Register the element type
424
*
425
* Parameters:
426
*
427
* Input: (char *) description of the element
428
* (int) numeric code for the element
429
*
430
* Output: Global list of element types is modified
431
*
432
* Return value: malloc() success
433
*
434
******************************************************************************/
435
int elm_10node_tetra_initialize()
436
{
437
static char *Name = "ELM_10NODE_TETRA";
438
439
element_type_t ElementDef;
440
441
int elm_add_element_type();
442
443
elm_10node_tetra_shape_functions();
444
445
ElementDef.ElementName = Name;
446
ElementDef.ElementCode = 510;
447
448
ElementDef.NumberOfNodes = 10;
449
450
ElementDef.NodeU = NodeU;
451
ElementDef.NodeV = NodeV;
452
ElementDef.NodeW = NodeW;
453
454
ElementDef.PartialU = (double (*)())elm_10node_tetra_dndu_fvalue;
455
ElementDef.PartialV = (double (*)())elm_10node_tetra_dndv_fvalue;
456
ElementDef.PartialW = (double (*)())elm_10node_tetra_dndw_fvalue;
457
458
ElementDef.FunctionValue = (double (*)())elm_10node_tetra_fvalue;
459
ElementDef.Triangulate = (int (*)())elm_10node_tetra_triangulate;
460
ElementDef.PointInside = (int (*)())elm_10node_tetra_point_inside;
461
ElementDef.IsoLine = (int (*)())elm_10node_tetra_isoline;
462
ElementDef.IsoSurface = (int (*)())elm_10node_tetra_isosurface;
463
464
return elm_add_element_type( &ElementDef );
465
}
466
467