Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/elements/20node_brick.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
* Definitions for 8 node brick volume 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: 27 Sep 1995
40
*
41
* Modified by:
42
*
43
* Date of modification:
44
*
45
******************************************************************************/
46
47
#include "../elmerpost.h"
48
#include <elements.h>
49
50
/*
51
* Isoparametric 20 node volume element.
52
*
53
* 7------18-------6
54
* 19| 17|
55
* / | / |
56
* 4------16-------5 |
57
* | 15 | 14
58
* | | | |
59
* 12 | 13 |
60
* | 3-----10-----|--2
61
* | 11 | 9 w v
62
* w|/v |/ |/
63
* 0-------8-------1 ---u
64
* u
65
*
66
* shape functions: N = (1+u u)(1+v v)(1+w w)(u u+v v+w w-2)/8 i = 0..7
67
* i i i i i i i
68
* N = (1-u^2)(1+v v)(1+w w)/4 i=8,10,16,18 (u = 0)
69
* i i i i
70
* N = (1+u u)(1-v^2)(1+w w)/4 i=9,11,17,19 (v = 0)
71
* i i i i
72
* N = (1+u u)(1+v v)(1-w^2)/4 i=12,13,14,15 (w = 0)
73
* i i i i
74
*
75
* @/@u N = u (1+v v)(1+w w)(2u u+v v+w w-1)/8 i = 0..7
76
* i i i i i i i
77
* @/@u N = -2u(1+v v)(1+w w)/4 i=8,10,16,18 (u = 0)
78
* i i i i
79
* @/@u N = u (1-v^2)(1+w w)/4 i=9,11,17,19 (v = 0)
80
* i i i i
81
* @/@u N = u (1+v v)(1-w^2)/4 i=12,13,14,15 (w = 0)
82
* i i i i
83
*
84
*/
85
86
static double A[20][20],N[20][20];
87
88
static double NodeU[] = {
89
-1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 0.0, 1.0,
90
0.0, -1.0, -1.0, 1.0, 1.0, -1.0, 0.0, 1.0, 0.0, -1.0
91
};
92
93
static double NodeV[] = {
94
-1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 0.0,
95
1.0, 0.0, -1.0, -1.0, 1.0, 1.0, -1.0, 0.0, 1.0, 0.0
96
};
97
98
static double NodeW[] = {
99
-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0,
100
-1.0, -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0
101
};
102
103
104
/*******************************************************************************
105
*
106
* Name: elm_20node_brick_triangulate( geometry_t *,element_t * )
107
*
108
* Purpose: Triangulate an element. The process also builds up an edge
109
* table and adds new nodes to node table. The triangulation
110
* and edge table is stored in geometry_t *geom-structure.
111
*
112
* Parameters:
113
*
114
* Input: (geometry_t *) pointer to structure holding triangulation
115
* (element_t *) element to triangulate
116
*
117
* Output: (geometry_t *) structure is modified
118
*
119
* Return value: FALSE if malloc() fails, TRUE otherwise
120
*
121
******************************************************************************/
122
static int elm_20node_brick_triangulate( geometry_t *geom,element_t *brick )
123
{
124
element_t quad;
125
int i,j;
126
int geo_add_edge();
127
int elm_4node_quad_triangulate();
128
129
if ( GlobalOptions.VolumeSides )
130
{
131
int topo[4];
132
133
quad.DisplayFlag = TRUE;
134
quad.Topology = topo;
135
for( i=0; i<MAX_GROUP_IDS; i++ ) quad.GroupIds[i] = brick->GroupIds[i];
136
137
for( i=0; i<6; i++ )
138
{
139
for( j=0; j<4; j++ )
140
{
141
quad.Topology[j] = brick->Topology[ElmBrickFace[i][j]];
142
}
143
if ( !elm_4node_quad_triangulate( geom, &quad, brick ) ) return FALSE;
144
}
145
} else {
146
if ( !geo_add_edge( geom, brick->Topology[0], brick->Topology[8], brick ) ) return FALSE;
147
if ( !geo_add_edge( geom, brick->Topology[8], brick->Topology[1], brick ) ) return FALSE;
148
if ( !geo_add_edge( geom, brick->Topology[1], brick->Topology[9], brick ) ) return FALSE;
149
if ( !geo_add_edge( geom, brick->Topology[9], brick->Topology[2], brick ) ) return FALSE;
150
if ( !geo_add_edge( geom, brick->Topology[2], brick->Topology[10], brick ) ) return FALSE;
151
if ( !geo_add_edge( geom, brick->Topology[10], brick->Topology[3], brick ) ) return FALSE;
152
if ( !geo_add_edge( geom, brick->Topology[3], brick->Topology[11], brick ) ) return FALSE;
153
if ( !geo_add_edge( geom, brick->Topology[11], brick->Topology[0], brick ) ) return FALSE;
154
if ( !geo_add_edge( geom, brick->Topology[0], brick->Topology[12], brick ) ) return FALSE;
155
if ( !geo_add_edge( geom, brick->Topology[12], brick->Topology[4], brick ) ) return FALSE;
156
if ( !geo_add_edge( geom, brick->Topology[1], brick->Topology[13], brick ) ) return FALSE;
157
if ( !geo_add_edge( geom, brick->Topology[13], brick->Topology[5], brick ) ) return FALSE;
158
if ( !geo_add_edge( geom, brick->Topology[2], brick->Topology[14], brick ) ) return FALSE;
159
if ( !geo_add_edge( geom, brick->Topology[14], brick->Topology[6], brick ) ) return FALSE;
160
if ( !geo_add_edge( geom, brick->Topology[3], brick->Topology[15], brick ) ) return FALSE;
161
if ( !geo_add_edge( geom, brick->Topology[15], brick->Topology[7], brick ) ) return FALSE;
162
if ( !geo_add_edge( geom, brick->Topology[15], brick->Topology[7], brick ) ) return FALSE;
163
if ( !geo_add_edge( geom, brick->Topology[4], brick->Topology[16], brick ) ) return FALSE;
164
if ( !geo_add_edge( geom, brick->Topology[16], brick->Topology[5], brick ) ) return FALSE;
165
if ( !geo_add_edge( geom, brick->Topology[5], brick->Topology[17], brick ) ) return FALSE;
166
if ( !geo_add_edge( geom, brick->Topology[17], brick->Topology[6], brick ) ) return FALSE;
167
if ( !geo_add_edge( geom, brick->Topology[6], brick->Topology[18], brick ) ) return FALSE;
168
if ( !geo_add_edge( geom, brick->Topology[18], brick->Topology[7], brick ) ) return FALSE;
169
if ( !geo_add_edge( geom, brick->Topology[7], brick->Topology[19], brick ) ) return FALSE;
170
if ( !geo_add_edge( geom, brick->Topology[19], brick->Topology[4], brick ) ) return FALSE;
171
}
172
173
return TRUE;
174
}
175
176
/*******************************************************************************
177
*
178
* Name: elm_20node_brick_shape_functions( )
179
*
180
* Purpose: Initialize element shape function array. Internal only.
181
*
182
* Parameters:
183
*
184
* Input: Global (filewise) variables NodeU,NodeV,NodeW
185
*
186
* Output: Global (filewise) variable N[8][8], will contain
187
* shape function coefficients
188
*
189
* Return value: void
190
*
191
******************************************************************************/
192
static void elm_20node_brick_shape_functions()
193
{
194
double u,v,w;
195
int i,j;
196
197
for( i=0; i<20; i++ )
198
{
199
u = NodeU[i];
200
v = NodeV[i];
201
w = NodeW[i];
202
203
A[i][0] = 1;
204
A[i][1] = u;
205
A[i][2] = v;
206
A[i][3] = w;
207
A[i][4] = u*v;
208
A[i][5] = u*w;
209
A[i][6] = v*w;
210
A[i][7] = u*v*w;
211
A[i][8] = u*u;
212
A[i][9] = v*v;
213
A[i][10] = w*w;
214
A[i][11] = u*u*v;
215
A[i][12] = u*u*w;
216
A[i][13] = u*v*v;
217
A[i][14] = u*w*w;
218
A[i][15] = v*v*w;
219
A[i][16] = v*w*w;
220
A[i][17] = u*u*v*w;
221
A[i][18] = u*v*v*w;
222
A[i][19] = u*v*w*w;
223
}
224
225
lu_mtrinv( (double *)A,20 );
226
227
for( i=0; i<20; i++ )
228
for( j=0; j<20; j++ ) N[i][j] = A[j][i];
229
}
230
231
/*******************************************************************************
232
*
233
* Name: elm_20node_brick_fvalue( double *,double,double,double )
234
*
235
* Purpose: return value of a quantity given on nodes at point (u,v,w)
236
* Use trough (element_type_t *) structure.
237
*
238
* Parameters:
239
*
240
* Input: (double *) quantity values at nodes
241
* (double,double,double) point where values are evaluated
242
*
243
* Output: none
244
*
245
* Return value: quantity value
246
*
247
******************************************************************************/
248
static double elm_20node_brick_fvalue(double *F,double u,double v,double w)
249
{
250
double R=0.0,uv=u*v,uw=u*w,vw=v*w,uvw=u*v*w,uu=u*u,vv=v*v,ww=w*w,
251
uuv=uu*v,uuw=uu*w,uvv=u*vv,uww=u*ww,vvw=vv*w,vww=v*ww,
252
uuvw=uu*vw,uvvw=vv*uw,uvww=uv*ww;
253
int i;
254
255
for( i=0; i<20; i++ )
256
{
257
R += F[i]*( N[i][0] +
258
N[i][1]*u +
259
N[i][2]*v +
260
N[i][3]*w +
261
N[i][4]*uv +
262
N[i][5]*uw +
263
N[i][6]*vw +
264
N[i][7]*uvw +
265
N[i][8]*uu +
266
N[i][9]*vv +
267
N[i][10]*ww +
268
N[i][11]*uuv +
269
N[i][12]*uuw +
270
N[i][13]*uvv +
271
N[i][14]*uww +
272
N[i][15]*vvw +
273
N[i][16]*vww +
274
N[i][17]*uuvw +
275
N[i][18]*uvvw +
276
N[i][19]*uvww );
277
}
278
279
return R;
280
}
281
282
/*******************************************************************************
283
*
284
* Name: elm_20node_brick_dndu_fvalue( double *,double,double,double )
285
*
286
* Purpose: return value of a first partial derivate in (v) of a
287
* quantity given on nodes at point (u,v).
288
* Use trough (element_type_t *) structure.
289
*
290
*
291
* Parameters:
292
*
293
* Input: (double *) quantity values at nodes
294
* (double u,double v,double w) point where values are evaluated
295
*
296
* Output: none
297
*
298
* Return value: quantity value
299
*
300
******************************************************************************/
301
static double elm_20node_brick_dndu_fvalue(double *F,double u,double v,double w)
302
{
303
double R=0.0,vw=v*w,u2=2*u,u2v=u2*v,u2w=u2*w,vv=v*v,ww=w*w,u2vw=u2*vw,vvw=vv*w,vww=v*ww;
304
int i;
305
306
for( i=0; i<20; i++ )
307
{
308
R += F[i]*( N[i][1] +
309
N[i][4]*v +
310
N[i][5]*w +
311
N[i][7]*vw +
312
N[i][8]*u2 +
313
N[i][11]*u2v +
314
N[i][12]*u2w +
315
N[i][13]*vv +
316
N[i][14]*ww +
317
N[i][17]*u2vw +
318
N[i][18]*vvw +
319
N[i][19]*vww );
320
}
321
322
return R;
323
}
324
/*******************************************************************************
325
*
326
* Name: elm_20node_brick_dndv_fvalue( double *,double,double,double )
327
*
328
* Purpose: return value of a first partial derivate in (v) of a
329
* quantity given on nodes at point (u,v,w).
330
* Use trough (element_type_t *) structure.
331
*
332
*
333
* Parameters:
334
*
335
* Input: (double *) quantity values at nodes
336
* (double u,double v,double w) point where values are evaluated
337
*
338
* Output: none
339
*
340
* Return value: quantity value
341
*
342
******************************************************************************/
343
static double elm_20node_brick_dndv_fvalue(double *F,double u,double v,double w)
344
{
345
double R=0.0,uw=u*w,v2=2*v,uu=u*u,uv2=u*v2,v2w=v2*w,ww=w*w,uuw=uu*w,uv2w=uw*v2,uww=u*ww;
346
int i;
347
348
for( i=0; i<20; i++ )
349
{
350
R += F[i]*( N[i][2] +
351
N[i][4]*u +
352
N[i][6]*w +
353
N[i][7]*uw +
354
N[i][9]*v2 +
355
N[i][11]*uu +
356
N[i][13]*uv2 +
357
N[i][15]*v2w +
358
N[i][16]*ww +
359
N[i][17]*uuw +
360
N[i][18]*uv2w +
361
N[i][19]*uww );
362
}
363
364
return R;
365
}
366
367
/*******************************************************************************
368
*
369
* Name: elm_20node_brick_dndw_fvalue( double *,double,double,double )
370
*
371
* Purpose: return value of a first partial derivate in (w) of a
372
* quantity given on nodes at point (u,v,w)
373
* Use trough (element_type_t *) structure.
374
*
375
*
376
* Parameters:
377
*
378
* Input: (double *) quantity values at nodes
379
* (double u,double v,double w) point where values are evaluated
380
*
381
* Output: none
382
*
383
* Return value: quantity value
384
*
385
******************************************************************************/
386
static double elm_20node_brick_dndw_fvalue(double *F,double u,double v,double w)
387
{
388
double R=0.0,uv=u*v,w2=2*w,uu=u*u,uw2=u*w2,vv=v*v,vw2=v*w2,uuv=uu*v,uvv=u*vv,uvw2=uv*w2;
389
int i;
390
391
for( i=0; i<20; i++ )
392
{
393
R += F[i]*( N[i][3] +
394
N[i][5]*u +
395
N[i][6]*v +
396
N[i][7]*uv +
397
N[i][10]*w2 +
398
N[i][12]*uu +
399
N[i][14]*uw2 +
400
N[i][15]*vv +
401
N[i][16]*vw2 +
402
N[i][17]*uuv +
403
N[i][18]*uvv +
404
N[i][19]*uvw2 );
405
}
406
407
return R;
408
}
409
410
411
/*******************************************************************************
412
*
413
* Name: elm_20node_brick_point_inside(
414
* double *nx,double *ny,double *nz,
415
* double px, double py, double pz,
416
* double *u,double *v,double *w )
417
*
418
* Purpose: Find if point (px,py,pz) is inside the element, and return
419
* element coordinates of the point.
420
*
421
* Parameters:
422
*
423
* Input: (double *) nx,ny,nz node coordinates
424
* (double) px,py,pz point to consider
425
*
426
* Output: (double *) u,v,w point in element coordinates if inside
427
*
428
* Return value: in/out status
429
*
430
* NOTES: TODO: FIX THIS
431
* trivial for this one...
432
*
433
******************************************************************************/
434
int elm_20node_brick_point_inside
435
(
436
double *nx, double *ny, double *nz,
437
double px, double py, double pz, double *u,double *v,double *w
438
)
439
{
440
int elm_8node_brick_point_inside();
441
return elm_8node_brick_point_inside( nx,ny,nz,px,py,pz,u,v,w );
442
}
443
444
/*******************************************************************************
445
*
446
* Name: elm_20node_brick_isoline
447
*
448
* Purpose: Extract a iso line from triangle with given threshold
449
*
450
* Parameters:
451
*
452
* Input: (double) K, contour threshold
453
* (double *) F, contour quantity
454
* (double *) C, color quantity
455
* (double *) X,Y,Z vertex coords.
456
*
457
* Output: (line_t *) place to store the line
458
*
459
* Return value: number of lines generated (0,...,144)
460
*
461
******************************************************************************/
462
static int elm_20node_brick_isoline
463
(
464
double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line
465
)
466
{
467
double f[8],c[8],x[8],y[8],z[8];
468
469
int i, j, k, n=0, above=0;
470
int elm_8node_quad_isoline();
471
472
for( i=0; i<20; i++ ) above += F[i]>K;
473
if ( above == 0 || above == 20 ) return 0;
474
475
for( i=0; i<6; i++ )
476
{
477
for( j=0; j<8; j++ )
478
{
479
k = ElmBrickFace[i][j];
480
f[j] = F[k];
481
c[j] = C[k];
482
x[j] = X[k];
483
y[j] = Y[k];
484
z[j] = Z[k];
485
}
486
n += elm_8node_quad_isoline( K,f,c,x,y,z,&Line[n] );
487
}
488
489
return n;
490
}
491
492
493
/*******************************************************************************
494
*
495
* Name: elm_20node_brick_isosurface(
496
* double *nx,double *ny,double *nz,
497
* double px, double py, double pz,
498
* double *u,double *v,double *w )
499
*
500
* Purpose: Find if point (px,py,pz) is inside the element, and return
501
* element coordinates of the point.
502
*
503
* Parameters:
504
*
505
* Input: (double *) nx,ny,nz node coordinates
506
* (double) px,py,pz point to consider
507
*
508
* Output: (double *) u,v,w point in element coordinates if inside
509
*
510
* Return value: in/out status
511
*
512
* NOTES: TODO: FIX THIS
513
*
514
******************************************************************************/
515
int elm_20node_brick_isosurface
516
(
517
double K,double *F,double *C,
518
double *X,double *Y,double *Z,
519
double *U,double *V,double *W,
520
polygon_t *Polygon
521
)
522
{
523
double f[8],c[8],x[8],y[8],z[8],u[8],v[8],w[8];
524
int i,j,k, n=0, above = 0;
525
int elm_8node_brick_isosurface();
526
527
for( i=0; i<20; i++ ) above += F[i]>K;
528
if ( above == 0 || above == 20 ) return 0;
529
530
n += elm_8node_brick_isosurface( K,F,C,X,Y,Z,U,V,W,Polygon );
531
return n;
532
}
533
534
535
/******************************************************************************
536
*
537
* Name: elm_20node_brick_initialize( )
538
*
539
* Purpose: Register the element type
540
*
541
* Parameters:
542
*
543
* Input: (char *) description of the element
544
* (int) numeric code for the element
545
*
546
* Output: Global list of element types is modified
547
*
548
* Return value: malloc() success
549
*
550
******************************************************************************/
551
int elm_20node_brick_initialize()
552
{
553
static char *Name = "ELM_20NODE_BRICK";
554
555
element_type_t ElementDef;
556
int elm_add_element_type();
557
558
elm_20node_brick_shape_functions();
559
560
ElementDef.ElementName = Name;
561
ElementDef.ElementCode = 820;
562
563
ElementDef.NumberOfNodes = 20;
564
565
ElementDef.NodeU = NodeU;
566
ElementDef.NodeV = NodeV;
567
ElementDef.NodeW = NodeW;
568
569
ElementDef.PartialU = (double (*)())elm_20node_brick_dndu_fvalue;
570
ElementDef.PartialV = (double (*)())elm_20node_brick_dndv_fvalue;
571
ElementDef.PartialW = (double (*)())elm_20node_brick_dndw_fvalue;
572
573
ElementDef.FunctionValue = (double (*)())elm_20node_brick_fvalue;
574
ElementDef.Triangulate = (int (*)())elm_20node_brick_triangulate;
575
ElementDef.PointInside = (int (*)())elm_20node_brick_point_inside;
576
ElementDef.IsoLine = (int (*)())elm_20node_brick_isoline;
577
ElementDef.IsoSurface = (int (*)())elm_20node_brick_isosurface;
578
579
return elm_add_element_type( &ElementDef ) ;
580
}
581
582