Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/elements/8node_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 4 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
* Four node tetra volume element.
48
*
49
* 3
50
* /|\
51
* / | \
52
* / | \
53
* / | \
54
* / 2 \
55
* / / \ \
56
* / / \ \ w v
57
* / / \ \ | /
58
* // \ \ |/
59
* 0-----------------1 ----u
60
*
61
*
62
*/
63
64
static double A[4][4],N[4][4];
65
66
static double NodeU[] = { 0.0, 1.0, 0.0, 0.0 };
67
static double NodeV[] = { 0.0, 0.0, 1.0, 0.0 };
68
static double NodeW[] = { 0.0, 0.0, 0.0, 1.0 };
69
70
71
/*******************************************************************************
72
*
73
* Name: elm_8node_tetra_triangulate
74
*
75
* Purpose: Triangulate an element. The process also builds up an edge
76
* table and adds new nodes to node table. The triangulation
77
* and edge table is stored in geometry_t *geom-structure.
78
*
79
* Parameters:
80
*
81
* Input: (geometry_t *) pointer to structure holding triangulation
82
* (element_t *) element to triangulate
83
*
84
* Output: (geometry_t *) structure is modified
85
*
86
* Return value: FALSE if malloc() fails, TRUE otherwise
87
*
88
******************************************************************************/
89
static int elm_8node_tetra_triangulate( geometry_t *geom,element_t *tetra )
90
{
91
element_t triangle;
92
int i,j;
93
94
int geo_add_edge();
95
int elm_3node_triangle_triangulate();
96
97
98
if ( GlobalOptions.VolumeSides )
99
{
100
int topo[4];
101
102
triangle.DisplayFlag = TRUE;
103
triangle.Topology = topo;
104
for( i=0; i<MAX_GROUP_IDS; i++ ) triangle.GroupIds[i] = tetra->GroupIds[i];
105
106
for( i=0; i<4; i++ )
107
{
108
for( j=0; j<3; j++ )
109
{
110
triangle.Topology[j] = tetra->Topology[ElmTetraFace[i][j]];
111
}
112
if ( !elm_3node_triangle_triangulate( geom, &triangle, tetra ) ) return FALSE;
113
}
114
} else {
115
if ( !geo_add_edge( geom, tetra->Topology[0],tetra->Topology[1],tetra ) ) return FALSE;
116
if ( !geo_add_edge( geom, tetra->Topology[0],tetra->Topology[2],tetra ) ) return FALSE;
117
if ( !geo_add_edge( geom, tetra->Topology[1],tetra->Topology[2],tetra ) ) return FALSE;
118
if ( !geo_add_edge( geom, tetra->Topology[0],tetra->Topology[3],tetra ) ) return FALSE;
119
if ( !geo_add_edge( geom, tetra->Topology[1],tetra->Topology[3],tetra ) ) return FALSE;
120
if ( !geo_add_edge( geom, tetra->Topology[2],tetra->Topology[3],tetra ) ) return FALSE;
121
}
122
123
return TRUE;
124
}
125
126
/*******************************************************************************
127
*
128
* Name: elm_8node_tetra_point_inside
129
* (
130
* double *nx,double *ny,double *nz,
131
* double px, double py, double pz,
132
* double *u,double *v,double *w
133
* )
134
*
135
* Purpose: Find if point (px,py,pz) is inside the element, and return
136
* element coordinates of the point.
137
*
138
* Parameters:
139
*
140
* Input: (double *) nx,ny,nz n coordinates
141
* (double) px,py,pz point to consider
142
*
143
* Output: (double *) u,v,w point in element coordinates if inside
144
*
145
* Return value: in/out status
146
*
147
* NOTES: the goal here can be hard for more involved element types. kind of
148
* trivial for this one...
149
*
150
******************************************************************************/
151
int elm_8node_tetra_point_inside
152
(
153
double *nx, double *ny, double *nz,
154
double px, double py, double pz, double *u,double *v,double *w
155
)
156
{
157
double B00,B01,B02,B10,B11,B12,B20,B21,B22;
158
double A00,A01,A02,A10,A11,A12,A20,A21,A22,detA;
159
160
if ( px > MAX(MAX(MAX(nx[0],nx[1]),nx[2]),nx[3])) return FALSE;
161
if ( py > MAX(MAX(MAX(ny[0],ny[1]),ny[2]),ny[3])) return FALSE;
162
if ( pz > MAX(MAX(MAX(nz[0],nz[1]),nz[2]),nz[3])) return FALSE;
163
164
if ( px < MIN(MIN(MIN(nx[0],nx[1]),nx[2]),nx[3])) return FALSE;
165
if ( py < MIN(MIN(MIN(ny[0],ny[1]),ny[2]),ny[3])) return FALSE;
166
if ( pz < MIN(MIN(MIN(nz[0],nz[1]),nz[2]),nz[3])) return FALSE;
167
168
A00 = nx[1] - nx[0];
169
A01 = nx[2] - nx[0];
170
A02 = nx[3] - nx[0];
171
172
A10 = ny[1] - ny[0];
173
A11 = ny[2] - ny[0];
174
A12 = ny[3] - ny[0];
175
176
A20 = nz[1] - nz[0];
177
A21 = nz[2] - nz[0];
178
A22 = nz[3] - nz[0];
179
180
detA = A00*(A11*A22 - A12*A21);
181
detA += A01*(A12*A20 - A10*A22);
182
detA += A02*(A10*A21 - A11*A20);
183
if ( ABS(detA) < AEPS )
184
{
185
fprintf( stderr, "8node_tetra_inside: SINGULAR (huh?).\n" );
186
return FALSE;
187
}
188
189
detA = 1 / detA;
190
191
B00 = (A11*A22 - A12*A21)*detA;
192
B10 = (A12*A20 - A10*A22)*detA;
193
B20 = (A10*A21 - A11*A20)*detA;
194
195
B01 = (A21*A02 - A01*A22)*detA;
196
B11 = (A00*A22 - A20*A02)*detA;
197
B21 = (A01*A20 - A00*A21)*detA;
198
199
B02 = (A01*A12 - A11*A02)*detA;
200
B12 = (A10*A02 - A00*A12)*detA;
201
B22 = (A00*A11 - A10*A01)*detA;
202
203
px -= nx[0];
204
py -= ny[0];
205
pz -= nz[0];
206
207
*u = B00*px + B01*py + B02*pz;
208
if ( *u < 0.0 || *u > 1.0 ) return FALSE;
209
210
*v = B10*px + B11*py + B12*pz;
211
if ( *v < 0.0 || *v > 1.0 ) return FALSE;
212
213
*w = B20*px + B21*py + B22*pz;
214
if ( *w < 0.0 || *w > 1.0 ) return FALSE;
215
216
return (*u+*v+*w) <= 1.0;
217
}
218
219
220
/*******************************************************************************
221
*
222
* Name: elm_8node_tetra_isoline
223
*
224
* Purpose: Extract a isoline from triangle with given threshold
225
*
226
* Parameters:
227
*
228
* Input: (double) K, contour threshold
229
* (double *) F, contour quantity
230
* (double *) C, color quantity
231
* (double *) X,Y,Z vertex coords.
232
*
233
* Output: (line_t *) place to store the line
234
*
235
* Return value: number of lines generated (0,...,4)
236
*
237
******************************************************************************/
238
static int elm_8node_tetra_isoline
239
(
240
double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line
241
)
242
{
243
double f[3],c[3],x[3],y[3],z[3];
244
245
int i, j, k, n=0, above=0;
246
247
int elm_3node_triangle_isoline();
248
249
for( i=0; i<4; i++ ) above += F[i]>K;
250
if ( above == 0 || above == 4 ) return 0;
251
252
for( i=0; i<4; i++ )
253
{
254
for( j=0; j<3; j++ )
255
{
256
k = ElmTetraFace[i][j];
257
f[j] = F[k];
258
c[j] = C[k];
259
x[j] = X[k];
260
y[j] = Y[k];
261
z[j] = Z[k];
262
}
263
n += elm_3node_triangle_isoline( K,f,c,x,y,z,&Line[n] );
264
}
265
266
return n;
267
}
268
269
270
/*******************************************************************************
271
*
272
* Name: elm_8node_tetra_isosurface
273
*
274
* Purpose: Extract isosurfaces for element
275
*
276
* Parameters:
277
*
278
* Input: (double ) K: contour threshold
279
* (double *) F: contour quantity values at nodes
280
* (double *) C: color quantity values at nodes
281
* (double *) X,Y,Z: node coordinates
282
* (double *) U,V,W: normal vector at nodes
283
*
284
* Output: (polygon_t *)Polygon, output triangles (0,1 or 2) triangles
285
*
286
* Return value: How many triangles we've got...
287
*
288
******************************************************************************/
289
int elm_8node_tetra_isosurface
290
(
291
double K,double *F,double *C, double *X,double *Y,double *Z,
292
double *U,double *V,double *W, polygon_t *Polygon
293
)
294
{
295
double t,tx[4],ty[4],tz[4],tu[4],tv[4],tw[4],tf[4],tc[4];
296
double ax,ay,az,bx,by,bz,nx,ny,nz;
297
298
int S0 = F[0] > K;
299
int S1 = F[1] > K;
300
int S2 = F[2] > K;
301
int S3 = F[3] > K;
302
303
int S = S0+S1+S2+S3,I[4],j;
304
305
if ( S==0 || S==4 ) return 0;
306
307
if ( S==1 || S==3 )
308
{
309
if ( (S==1 && S0) || (S==3 && !S0) )
310
{
311
I[0] = 0;
312
I[1] = 1;
313
I[2] = 2;
314
I[3] = 3;
315
} else if ( (S==1 && S1) || (S==3 && !S1) )
316
{
317
I[0] = 1;
318
I[1] = 0;
319
I[2] = 2;
320
I[3] = 3;
321
} else if ( (S==1 && S2) || (S==3 && !S2) )
322
{
323
I[0] = 2;
324
I[1] = 0;
325
I[2] = 1;
326
I[3] = 3;
327
} else if ( (S==1 && S3) || (S==3 && !S3) )
328
{
329
I[0] = 3;
330
I[1] = 0;
331
I[2] = 1;
332
I[3] = 2;
333
} else { return 0; }
334
335
for( j=1; j<4; j++ )
336
{
337
t = (K-F[I[0]]) / (F[I[j]]-F[I[0]]);
338
Polygon->x[j-1] = t*(X[I[j]]-X[I[0]]) + X[I[0]];
339
Polygon->y[j-1] = t*(Y[I[j]]-Y[I[0]]) + Y[I[0]];
340
Polygon->z[j-1] = t*(Z[I[j]]-Z[I[0]]) + Z[I[0]];
341
Polygon->u[j-1] = t*(U[I[j]]-U[I[0]]) + U[I[0]];
342
Polygon->v[j-1] = t*(V[I[j]]-V[I[0]]) + V[I[0]];
343
Polygon->w[j-1] = t*(W[I[j]]-W[I[0]]) + W[I[0]];
344
Polygon->c[j-1] = t*(C[I[j]]-C[I[0]]) + C[I[0]];
345
Polygon->f[j-1] = K;
346
}
347
348
ax = Polygon->x[1] - Polygon->x[0];
349
ay = Polygon->y[1] - Polygon->y[0];
350
az = Polygon->z[1] - Polygon->z[0];
351
352
bx = Polygon->x[2] - Polygon->x[0];
353
by = Polygon->y[2] - Polygon->y[0];
354
bz = Polygon->z[2] - Polygon->z[0];
355
356
nx = ay*bz - az*by;
357
ny = az*bx - ax*bz;
358
nz = ax*by - ay*bx;
359
360
ax = Polygon->u[0] + Polygon->u[1] + Polygon->u[2];
361
ay = Polygon->v[0] + Polygon->v[1] + Polygon->v[2];
362
az = Polygon->w[0] + Polygon->w[1] + Polygon->w[2];
363
364
if ( nx*ax + ny*ay + nz*az < 0.0 )
365
{
366
double s;
367
368
#define swap( x,y ) { s=x; x=y; y=s; }
369
370
swap( Polygon->x[1], Polygon->x[2] );
371
swap( Polygon->y[1], Polygon->y[2] );
372
swap( Polygon->z[1], Polygon->z[2] );
373
swap( Polygon->u[1], Polygon->u[2] );
374
swap( Polygon->v[1], Polygon->v[2] );
375
swap( Polygon->w[1], Polygon->w[2] );
376
swap( Polygon->f[1], Polygon->f[2] );
377
swap( Polygon->c[1], Polygon->c[2] );
378
379
#undef swap
380
}
381
382
return 1;
383
} else
384
{
385
if ( (S0 && S1) || (!S0 && !S1) )
386
{
387
t = (K-F[0])/ (F[2]-F[0]);
388
tx[0] = t*(X[2]-X[0]) + X[0];
389
ty[0] = t*(Y[2]-Y[0]) + Y[0];
390
tz[0] = t*(Z[2]-Z[0]) + Z[0];
391
tu[0] = t*(U[2]-U[0]) + U[0];
392
tv[0] = t*(V[2]-V[0]) + V[0];
393
tw[0] = t*(W[2]-W[0]) + W[0];
394
tc[0] = t*(C[2]-C[0]) + C[0];
395
tf[0] = K;
396
397
t = (K-F[1]) / (F[2]-F[1]);
398
tx[1] = t*(X[2]-X[1]) + X[1];
399
ty[1] = t*(Y[2]-Y[1]) + Y[1];
400
tz[1] = t*(Z[2]-Z[1]) + Z[1];
401
tu[1] = t*(U[2]-U[1]) + U[1];
402
tv[1] = t*(V[2]-V[1]) + V[1];
403
tw[1] = t*(W[2]-W[1]) + W[1];
404
tc[1] = t*(C[2]-C[1]) + C[1];
405
tf[1] = K;
406
407
t = (K-F[1]) / (F[3]-F[1]);
408
tx[2] = t*(X[3]-X[1]) + X[1];
409
ty[2] = t*(Y[3]-Y[1]) + Y[1];
410
tz[2] = t*(Z[3]-Z[1]) + Z[1];
411
tu[2] = t*(U[3]-U[1]) + U[1];
412
tv[2] = t*(V[3]-V[1]) + V[1];
413
tw[2] = t*(W[3]-W[1]) + W[1];
414
tc[2] = t*(C[3]-C[1]) + C[1];
415
tf[2] = K;
416
417
t = (K-F[0]) / (F[3]-F[0]);
418
tx[3] = t*(X[3]-X[0]) + X[0];
419
ty[3] = t*(Y[3]-Y[0]) + Y[0];
420
tz[3] = t*(Z[3]-Z[0]) + Z[0];
421
tu[3] = t*(U[3]-U[0]) + U[0];
422
tv[3] = t*(V[3]-V[0]) + V[0];
423
tw[3] = t*(W[3]-W[0]) + W[0];
424
tc[3] = t*(C[3]-C[0]) + C[0];
425
tf[3] = K;
426
}
427
else if ( (S0 && S2) || (!S0 && !S2) )
428
{
429
t = (K-F[0]) / (F[1]-F[0]);
430
tx[0] = t*(X[1]-X[0]) + X[0];
431
ty[0] = t*(Y[1]-Y[0]) + Y[0];
432
tz[0] = t*(Z[1]-Z[0]) + Z[0];
433
tu[0] = t*(U[1]-U[0]) + U[0];
434
tv[0] = t*(V[1]-V[0]) + V[0];
435
tw[0] = t*(W[1]-W[0]) + W[0];
436
tc[0] = t*(C[1]-C[0]) + C[0];
437
tf[0] = K;
438
439
t = (K-F[2]) / (F[1]-F[2]);
440
tx[1] = t*(X[1]-X[2]) + X[2];
441
ty[1] = t*(Y[1]-Y[2]) + Y[2];
442
tz[1] = t*(Z[1]-Z[2]) + Z[2];
443
tu[1] = t*(U[1]-U[2]) + U[2];
444
tv[1] = t*(V[1]-V[2]) + V[2];
445
tw[1] = t*(W[1]-W[2]) + W[2];
446
tc[1] = t*(C[1]-C[2]) + C[2];
447
tf[1] = K;
448
449
t = (K-F[2]) / (F[3]-F[2]);
450
tx[2] = t*(X[3]-X[2]) + X[2];
451
ty[2] = t*(Y[3]-Y[2]) + Y[2];
452
tz[2] = t*(Z[3]-Z[2]) + Z[2];
453
tu[2] = t*(U[3]-U[2]) + U[2];
454
tv[2] = t*(V[3]-V[2]) + V[2];
455
tw[2] = t*(W[3]-W[2]) + W[2];
456
tc[2] = t*(C[3]-C[2]) + C[2];
457
tf[2] = K;
458
459
t = (K-F[0]) / (F[3]-F[0]);
460
tx[3] = t*(X[3]-X[0]) + X[0];
461
ty[3] = t*(Y[3]-Y[0]) + Y[0];
462
tz[3] = t*(Z[3]-Z[0]) + Z[0];
463
tu[3] = t*(U[3]-U[0]) + U[0];
464
tv[3] = t*(V[3]-V[0]) + V[0];
465
tw[3] = t*(W[3]-W[0]) + W[0];
466
tc[3] = t*(C[3]-C[0]) + C[0];
467
tf[3] = K;
468
}
469
else if ( (S0 && S3) || (!S0 && !S3) )
470
{
471
t = (K-F[0]) / (F[1]-F[0]);
472
tx[0] = t*(X[1]-X[0]) + X[0];
473
ty[0] = t*(Y[1]-Y[0]) + Y[0];
474
tz[0] = t*(Z[1]-Z[0]) + Z[0];
475
tu[0] = t*(U[1]-U[0]) + U[0];
476
tv[0] = t*(V[1]-V[0]) + V[0];
477
tw[0] = t*(W[1]-W[0]) + W[0];
478
tc[0] = t*(C[1]-C[0]) + C[0];
479
tf[0] = K;
480
481
t = (K-F[3]) / (F[1]-F[3]);
482
tx[1] = t*(X[1]-X[3]) + X[3];
483
ty[1] = t*(Y[1]-Y[3]) + Y[3];
484
tz[1] = t*(Z[1]-Z[3]) + Z[3];
485
tu[1] = t*(U[1]-U[3]) + U[3];
486
tv[1] = t*(V[1]-V[3]) + V[3];
487
tw[1] = t*(W[1]-W[3]) + W[3];
488
tc[1] = t*(C[1]-C[3]) + C[3];
489
tf[1] = K;
490
491
t = (K-F[3]) / (F[2]-F[3]);
492
tx[2] = t*(X[2]-X[3]) + X[3];
493
ty[2] = t*(Y[2]-Y[3]) + Y[3];
494
tz[2] = t*(Z[2]-Z[3]) + Z[3];
495
tu[2] = t*(U[2]-U[3]) + U[3];
496
tv[2] = t*(V[2]-V[3]) + V[3];
497
tw[2] = t*(W[2]-W[3]) + W[3];
498
tc[2] = t*(C[2]-C[3]) + C[3];
499
tf[2] = K;
500
501
t = (K-F[0]) / (F[2]-F[0]);
502
tx[3] = t*(X[2]-X[0]) + X[0];
503
ty[3] = t*(Y[2]-Y[0]) + Y[0];
504
tz[3] = t*(Z[2]-Z[0]) + Z[0];
505
tu[3] = t*(U[2]-U[0]) + U[0];
506
tv[3] = t*(V[2]-V[0]) + V[0];
507
tw[3] = t*(W[2]-W[0]) + W[0];
508
tc[3] = t*(C[2]-C[0]) + C[0];
509
tf[3] = K;
510
}
511
512
Polygon[0].x[0] = tx[0];
513
Polygon[0].y[0] = ty[0];
514
Polygon[0].z[0] = tz[0];
515
Polygon[0].u[0] = tu[0];
516
Polygon[0].v[0] = tv[0];
517
Polygon[0].w[0] = tw[0];
518
Polygon[0].f[0] = tf[0];
519
Polygon[0].c[0] = tc[0];
520
521
ax = tx[1] - tx[0];
522
ay = ty[1] - ty[0];
523
az = tz[1] - tz[0];
524
525
bx = tx[2] - tx[0];
526
by = ty[2] - ty[0];
527
bz = tz[2] - tz[0];
528
529
nx = ay*bz - az*by;
530
ny = az*bx - ax*bz;
531
nz = ax*by - ay*bx;
532
533
ax = tu[0] + tu[1] + tu[2] + tu[3];
534
ay = tv[0] + tv[1] + tv[2] + tv[3];
535
az = tw[0] + tw[1] + tw[2] + tw[3];
536
537
if ( nx*ax + ny*ay + nz*az >= 0.0 )
538
{
539
Polygon[0].x[1] = tx[1];
540
Polygon[0].y[1] = ty[1];
541
Polygon[0].z[1] = tz[1];
542
Polygon[0].u[1] = tu[1];
543
Polygon[0].v[1] = tv[1];
544
Polygon[0].w[1] = tw[1];
545
Polygon[0].f[1] = tf[1];
546
Polygon[0].c[1] = tc[1];
547
548
Polygon[0].x[2] = tx[2];
549
Polygon[0].y[2] = ty[2];
550
Polygon[0].z[2] = tz[2];
551
Polygon[0].u[2] = tu[2];
552
Polygon[0].v[2] = tv[2];
553
Polygon[0].w[2] = tw[2];
554
Polygon[0].f[2] = tf[2];
555
Polygon[0].c[2] = tc[2];
556
} else
557
{
558
Polygon[0].x[1] = tx[2];
559
Polygon[0].y[1] = ty[2];
560
Polygon[0].z[1] = tz[2];
561
Polygon[0].u[1] = tu[2];
562
Polygon[0].v[1] = tv[2];
563
Polygon[0].w[1] = tw[2];
564
Polygon[0].f[1] = tf[2];
565
Polygon[0].c[1] = tc[2];
566
567
Polygon[0].x[2] = tx[1];
568
Polygon[0].y[2] = ty[1];
569
Polygon[0].z[2] = tz[1];
570
Polygon[0].u[2] = tu[1];
571
Polygon[0].v[2] = tv[1];
572
Polygon[0].w[2] = tw[1];
573
Polygon[0].f[2] = tf[1];
574
Polygon[0].c[2] = tc[1];
575
}
576
577
Polygon[1].x[0] = tx[0];
578
Polygon[1].y[0] = ty[0];
579
Polygon[1].z[0] = tz[0];
580
Polygon[1].u[0] = tu[0];
581
Polygon[1].v[0] = tv[0];
582
Polygon[1].w[0] = tw[0];
583
Polygon[1].f[0] = tf[0];
584
Polygon[1].c[0] = tc[0];
585
586
ax = tx[2] - tx[0];
587
ay = ty[2] - ty[0];
588
az = tz[2] - tz[0];
589
590
bx = tx[3] - tx[0];
591
by = ty[3] - ty[0];
592
bz = tz[3] - tz[0];
593
594
nx = ay*bz - az*by;
595
ny = az*bx - ax*bz;
596
nz = ax*by - ay*bx;
597
598
ax = tu[0] + tu[1] + tu[2] + tu[3];
599
ay = tv[0] + tv[1] + tv[2] + tv[3];
600
az = tw[0] + tw[1] + tw[2] + tw[3];
601
602
if ( nx*ax + ny*ay + nz*az >= 0.0 )
603
{
604
Polygon[1].x[1] = tx[2];
605
Polygon[1].y[1] = ty[2];
606
Polygon[1].z[1] = tz[2];
607
Polygon[1].u[1] = tu[2];
608
Polygon[1].v[1] = tv[2];
609
Polygon[1].w[1] = tw[2];
610
Polygon[1].f[1] = tf[2];
611
Polygon[1].c[1] = tc[2];
612
613
Polygon[1].x[2] = tx[3];
614
Polygon[1].y[2] = ty[3];
615
Polygon[1].z[2] = tz[3];
616
Polygon[1].u[2] = tu[3];
617
Polygon[1].v[2] = tv[3];
618
Polygon[1].w[2] = tw[3];
619
Polygon[1].f[2] = tf[3];
620
Polygon[1].c[2] = tc[3];
621
} else
622
{
623
Polygon[1].x[1] = tx[3];
624
Polygon[1].y[1] = ty[3];
625
Polygon[1].z[1] = tz[3];
626
Polygon[1].u[1] = tu[3];
627
Polygon[1].v[1] = tv[3];
628
Polygon[1].w[1] = tw[3];
629
Polygon[1].f[1] = tf[3];
630
Polygon[1].c[1] = tc[3];
631
632
Polygon[1].x[2] = tx[2];
633
Polygon[1].y[2] = ty[2];
634
Polygon[1].z[2] = tz[2];
635
Polygon[1].u[2] = tu[2];
636
Polygon[1].v[2] = tv[2];
637
Polygon[1].w[2] = tw[2];
638
Polygon[1].f[2] = tf[2];
639
Polygon[1].c[2] = tc[2];
640
}
641
642
return 2;
643
}
644
645
return 0;
646
}
647
648
/*******************************************************************************
649
*
650
* Name: elm_8node_tetra_shape_functions
651
*
652
* Purpose: Initialize element shape function array. Internal only.
653
*
654
* Parameters:
655
*
656
* Input: Global (filewise) variables NodeU,NodeV,NodeW
657
*
658
* Output: Global (filewise) variable N[4][4], will contain
659
* shape function coefficients
660
*
661
* Return value: void
662
*
663
******************************************************************************/
664
static void elm_8node_tetra_shape_functions()
665
{
666
double u,v,w;
667
int i,j;
668
669
for( i=0; i<4; i++ )
670
{
671
u = NodeU[i];
672
v = NodeV[i];
673
w = NodeW[i];
674
675
A[i][0] = 1;
676
A[i][1] = u;
677
A[i][2] = v;
678
A[i][3] = w;
679
}
680
681
lu_mtrinv( (double *)A,4 );
682
683
for( i=0; i<4; i++ )
684
for( j=0; j<4; j++ ) N[i][j] = A[j][i];
685
}
686
687
/*******************************************************************************
688
*
689
* Name: elm_8node_tetra_fvalue
690
*
691
* Purpose: return value of a quantity given on nodes at point (u,v)
692
* Use trough (element_type_t *) structure.
693
*
694
* Parameters:
695
*
696
* Input: (double *) quantity values at nodes
697
* (double u,double v) point where values are evaluated
698
*
699
* Output: none
700
*
701
* Return value: quantity value
702
*
703
******************************************************************************/
704
static double elm_8node_tetra_fvalue(double *F,double u,double v,double w)
705
{
706
double R=0.0;
707
int i;
708
709
for( i=0; i<4; i++ )
710
{
711
R += F[i]*(N[i][0]+N[i][1]*u+N[i][2]*v+N[i][3]*w);
712
}
713
714
return R;
715
}
716
717
/*******************************************************************************
718
*
719
* Name: elm_8node_tetra_dndu_fvalue
720
*
721
* Purpose: return value of a first partial derivate in (v) of a
722
* quantity given on nodes at point (u,v).
723
* Use trough (element_type_t *) structure.
724
*
725
*
726
* Parameters:
727
*
728
* Input: (double *) quantity values at nodes
729
* (double u,double v,double w) point where values are evaluated
730
*
731
* Output: none
732
*
733
* Return value: quantity value
734
*
735
******************************************************************************/
736
static double elm_8node_tetra_dndu_fvalue(double *F,double u,double v,double w)
737
{
738
double R=0.0;
739
int i;
740
741
for( i=0; i<4; i++ ) R += F[i]*N[i][1];
742
743
return R;
744
}
745
746
/*******************************************************************************
747
*
748
* Name: elm_8node_tetra_dndv_fvalue
749
*
750
* Purpose: return value of a first partial derivate in (v) of a
751
* quantity given on nodes at point (u,v,w).
752
* Use trough (element_type_t *) structure.
753
*
754
*
755
* Parameters:
756
*
757
* Input: (double *) quantity values at nodes
758
* (double u,double v,double w) point where values are evaluated
759
*
760
* Output: none
761
*
762
* Return value: quantity value
763
*
764
******************************************************************************/
765
static double elm_8node_tetra_dndv_fvalue(double *F,double u,double v,double w)
766
{
767
double R=0.0;
768
int i;
769
770
for( i=0; i<4; i++ ) R += F[i]*N[i][2];
771
772
return R;
773
}
774
775
/*******************************************************************************
776
*
777
* Name: elm_8node_tetra_dndw_fvalue
778
*
779
* Purpose: return value of a first partial derivate in (w) of a
780
* quantity given on nodes at point (u,v,w)
781
* Use trough (element_type_t *) structure.
782
*
783
*
784
* Parameters:
785
*
786
* Input: (double *) quantity values at nodes
787
* (double u,double v,double w) point where values are evaluated
788
*
789
* Output: none
790
*
791
* Return value: quantity value
792
*
793
******************************************************************************/
794
static double elm_8node_tetra_dndw_fvalue(double *F,double u,double v,double w)
795
{
796
double R=0.0;
797
int i;
798
799
for( i=0; i<4; i++ ) R += F[i]*N[i][3];
800
801
return R;
802
}
803
804
/******************************************************************************
805
*
806
* Name: elm_8node_tetra_initialize
807
*
808
* Purpose: Register the element type
809
*
810
* Parameters:
811
*
812
* Input: (char *) description of the element
813
* (int) numeric code for the element
814
*
815
* Output: Global list of element types is modified
816
*
817
* Return value: malloc() success
818
*
819
******************************************************************************/
820
int elm_8node_tetra_initialize()
821
{
822
static char *Name = "ELM_8NODE_TETRA";
823
824
element_type_t ElementDef;
825
826
int elm_add_element_type();
827
828
elm_8node_tetra_shape_functions();
829
830
ElementDef.ElementName = Name;
831
ElementDef.ElementCode = 508;
832
833
ElementDef.NumberOfNodes = 8;
834
835
ElementDef.NodeU = NodeU;
836
ElementDef.NodeV = NodeV;
837
ElementDef.NodeW = NodeW;
838
839
ElementDef.PartialU = (double (*)())elm_8node_tetra_dndu_fvalue;
840
ElementDef.PartialV = (double (*)())elm_8node_tetra_dndv_fvalue;
841
ElementDef.PartialW = (double (*)())elm_8node_tetra_dndw_fvalue;
842
843
ElementDef.FunctionValue = (double (*)())elm_8node_tetra_fvalue;
844
ElementDef.Triangulate = (int (*)())elm_8node_tetra_triangulate;
845
ElementDef.IsoLine = (int (*)())elm_8node_tetra_isoline;
846
ElementDef.IsoSurface = (int (*)())elm_8node_tetra_isosurface;
847
ElementDef.PointInside = (int (*)())elm_8node_tetra_point_inside;
848
849
return elm_add_element_type( &ElementDef );
850
}
851
852
853