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