Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/elements/15node_wedge.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 6 node wedge 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
* 15 node wedge volume element.
48
*
49
* 3-----------4
50
* /| /| w v
51
* / | / | | /
52
* / | / | |/
53
* / 0----/------1 ---u
54
* / / / //
55
* / / /// //
56
* / // //
57
* / // //
58
* 5/ / //
59
* | / //
60
* | / //
61
* |//
62
* 2
63
*/
64
65
static double A[15][15],N[15][15];
66
67
static double NodeU[] = { 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 0.0, 0.5, 0.5, 0.0, 0.0, 1.0, 0.0 };
68
static double NodeV[] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 0.0, 0.5, 0.5, 0.0, 0.0, 1.0 };
69
static double NodeW[] = { -1.0,-1.0,-1.0, 1.0, 1.0, 1.0,-1.0,-1.0,-1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0 };
70
71
/*******************************************************************************
72
*
73
* Name: elm_15node_wedge_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_15node_wedge_triangulate( geometry_t *geom,element_t *wedge )
90
{
91
element_t element;
92
int i,j;
93
int elm_8node_quad_triangulate();
94
int geo_add_edge();
95
int elm_6node_triangle_triangulate();
96
97
98
if ( GlobalOptions.VolumeSides )
99
{
100
int topo[8];
101
102
element.DisplayFlag = TRUE;
103
element.Topology = topo;
104
for( i=0; i<MAX_GROUP_IDS; i++ ) element.GroupIds[i] = wedge->GroupIds[i];
105
106
for( i=0; i<3; i++ )
107
{
108
for( j=0; j<8; j++ )
109
{
110
element.Topology[j] = wedge->Topology[ElmWedgeFace[i][j]];
111
}
112
if ( !elm_8node_quad_triangulate( geom, &element, wedge ) ) return FALSE;
113
}
114
115
for( i=3; i<5; i++ )
116
{
117
for( j=0; j<6; j++ )
118
{
119
element.Topology[j] = wedge->Topology[ElmWedgeFace[i][j]];
120
}
121
if ( !elm_6node_triangle_triangulate( geom, &element, wedge ) ) return FALSE;
122
}
123
} else {
124
if ( !geo_add_edge( geom, wedge->Topology[0], wedge->Topology[1],wedge ) ) return FALSE;
125
if ( !geo_add_edge( geom, wedge->Topology[0], wedge->Topology[2],wedge ) ) return FALSE;
126
if ( !geo_add_edge( geom, wedge->Topology[0], wedge->Topology[3],wedge ) ) return FALSE;
127
if ( !geo_add_edge( geom, wedge->Topology[1], wedge->Topology[2],wedge ) ) return FALSE;
128
if ( !geo_add_edge( geom, wedge->Topology[1], wedge->Topology[4],wedge ) ) return FALSE;
129
if ( !geo_add_edge( geom, wedge->Topology[2], wedge->Topology[5],wedge ) ) return FALSE;
130
if ( !geo_add_edge( geom, wedge->Topology[3], wedge->Topology[4],wedge ) ) return FALSE;
131
if ( !geo_add_edge( geom, wedge->Topology[3], wedge->Topology[5],wedge ) ) return FALSE;
132
if ( !geo_add_edge( geom, wedge->Topology[4], wedge->Topology[5],wedge ) ) return FALSE;
133
}
134
135
return TRUE;
136
}
137
138
/*******************************************************************************
139
*
140
* Name: elm_15node_wedge_shape_functions
141
*
142
* Purpose: Initialize element shape function array. Internal only.
143
*
144
* Parameters:
145
*
146
* Input: Global (filewise) variables NodeU,NodeV,NodeW
147
*
148
* Output: Global (filewise) variable N[15][15], will contain
149
* shape function coefficients
150
*
151
* Return value: void
152
* Return value: void
153
*
154
******************************************************************************/
155
static void elm_15node_wedge_shape_functions()
156
{
157
double u,v,w;
158
int i,j;
159
160
for( i=0; i<15; i++ )
161
{
162
u = NodeU[i];
163
v = NodeV[i];
164
w = NodeW[i];
165
166
A[i][0] = 1;
167
A[i][1] = u;
168
A[i][2] = u*u;
169
A[i][3] = v;
170
A[i][4] = u*v;
171
A[i][5] = v*v;
172
A[i][6] = w;
173
A[i][7] = u*w;
174
A[i][8] = u*u*w;
175
A[i][9] = v*w;
176
A[i][10] = u*v*w;
177
A[i][11] = v*v*w;
178
A[i][12] = w*w;
179
A[i][13] = u*w*w;
180
A[i][14] = v*w*w;
181
}
182
183
lu_mtrinv( (double *)A,15 );
184
185
for( i=0; i<15; i++ )
186
for( j=0; j<15; j++ ) N[i][j] = A[j][i];
187
}
188
189
/*******************************************************************************
190
*
191
* Name: elm_15node_wedge_fvalue
192
*
193
* Purpose: return value of a quantity given on nodes at point (u,v)
194
* Use trough (element_type_t *) structure.
195
*
196
* Parameters:
197
*
198
* Input: (double *) quantity values at nodes
199
* (double u,double v) point where values are evaluated
200
*
201
* Output: none
202
*
203
* Return value: quantity value
204
*
205
******************************************************************************/
206
static double elm_15node_wedge_fvalue(double *F,double u,double v,double w)
207
{
208
double R=0.0,uw=u*w,vw=v*w;
209
int i;
210
211
for( i=0; i<15; i++ )
212
{
213
R += F[i]*(N[i][0]+
214
N[i][1]*u+
215
N[i][2]*u*u+
216
N[i][3]*v+
217
N[i][4]*u*v+
218
N[i][5]*v*v+
219
N[i][6]*w+
220
N[i][7]*u*w+
221
N[i][8]*u*u*w+
222
N[i][9]*v*w+
223
N[i][10]*u*v*w+
224
N[i][11]*v*v*w+
225
N[i][12]*w*w+
226
N[i][13]*u*w*w+
227
N[i][14]*v*w*w);
228
}
229
230
return R;
231
}
232
233
/*******************************************************************************
234
*
235
* Name: elm_15node_wedge_dndu_fvalue
236
*
237
* Purpose: return value of a first partial derivate in (v) of a
238
* quantity given on nodes at point (u,v).
239
* Use trough (element_type_t *) structure.
240
*
241
*
242
* Parameters:
243
*
244
* Input: (double *) quantity values at nodes
245
* (double u,double v,double w) point where values are evaluated
246
*
247
* Output: none
248
*
249
* Return value: quantity value
250
*
251
******************************************************************************/
252
static double elm_15node_wedge_dndu_fvalue(double *F,double u,double v,double w)
253
{
254
double R=0.0;
255
int i;
256
257
for( i=0; i<15; i++ )
258
{
259
R += F[i]*( N[i][1] + 2*N[i][2]*u + N[i][4]*v + N[i][7]*w +
260
2*N[i][8]*u*w + N[i][10]*v*w + N[i][13]*w*w );
261
}
262
263
return R;
264
}
265
266
/*******************************************************************************
267
*
268
* Name: elm_15node_wedge_dndv_fvalue
269
*
270
* Purpose: return value of a first partial derivate in (v) of a
271
* quantity given on nodes at point (u,v,w).
272
* Use trough (element_type_t *) structure.
273
*
274
*
275
* Parameters:
276
*
277
* Input: (double *) quantity values at nodes
278
* (double u,double v,double w) point where values are evaluated
279
*
280
* Output: none
281
*
282
* Return value: quantity value
283
*
284
******************************************************************************/
285
static double elm_15node_wedge_dndv_fvalue(double *F,double u,double v,double w)
286
{
287
double R=0.0;
288
int i;
289
290
for( i=0; i<15; i++ )
291
{
292
R += F[i]*( N[i][3] + N[i][4]*u + 2*N[i][5]*v + N[i][9]*w +
293
N[i][10]*u*w + 2*N[i][11]*v*w + N[i][14]*w*w );
294
}
295
296
return R;
297
}
298
299
/*******************************************************************************
300
*
301
* Name: elm_15node_wedge_dndw_fvalue
302
*
303
* Purpose: return value of a first partial derivate in (w) of a
304
* quantity given on nodes at point (u,v,w)
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_15node_wedge_dndw_fvalue(double *F,double u,double v,double w)
319
{
320
double R=0.0;
321
int i;
322
323
for( i=0; i<15; i++ )
324
{
325
R += F[i]*( N[i][6] + N[i][7]*u + N[i][8]*u*u + N[i][9]*v + N[i][10]*u*v +
326
N[i][11]*v*v + 2*N[i][12]*w + 2*N[i][13]*u*w + 2*N[i][14]*v*w );
327
}
328
329
return R;
330
}
331
332
333
334
/*******************************************************************************
335
*
336
* Name: elm_15node_wedge_point_inside(
337
* double *nx,double *ny,double *nz,
338
* double px, double py, double pz,
339
* double *u,double *v,double *w )
340
*
341
* Purpose: Find if point (px,py,pz) is inside the element, and return
342
* element coordinates of the point.
343
*
344
* Parameters:
345
*
346
* Input: (double *) nx,ny,nz node coordinates
347
* (double) px,py,pz point to consider
348
*
349
* Output: (double *) u,v,w point in element coordinates if inside
350
*
351
* Return value: in/out status
352
*
353
* NOTES: the goal here can be hard for more involved element types. kind of
354
* trivial for this one...
355
*
356
******************************************************************************/
357
int elm_15node_wedge_point_inside
358
(
359
double *nx, double *ny, double *nz,
360
double px, double py, double pz, double *u,double *v,double *w
361
)
362
{
363
double x[4],y[4],z[4],r,s,t,maxx,minx,maxy,miny,maxz,minz;
364
int i,j;
365
366
static int map[3][4] =
367
{
368
{ 4,3,2,0 }, { 4,2,1,0 }, { 4,5,3,2 }
369
};
370
371
int elm_4node_tetra_point_inside();
372
maxx = minx = nx[0];
373
maxy = miny = ny[0];
374
maxz = minz = nz[0];
375
376
for( i=1; i<15; i++ )
377
{
378
maxx = MAX( nx[i],maxx );
379
maxy = MAX( ny[i],maxy );
380
maxz = MAX( nz[i],maxz );
381
382
minx = MIN( nx[i],minx );
383
miny = MIN( ny[i],miny );
384
minz = MIN( nz[i],minz );
385
}
386
387
if ( px > maxx || px < minx ) return FALSE;
388
if ( py > maxy || py < miny ) return FALSE;
389
if ( pz > maxz || pz < minz ) return FALSE;
390
391
for( i=0; i<3; i++ )
392
{
393
for( j=0; j<4; j++ )
394
{
395
x[j] = nx[map[i][j]];
396
y[j] = ny[map[i][j]];
397
z[j] = nz[map[i][j]];
398
}
399
400
if ( elm_4node_tetra_point_inside( x,y,z,px,py,pz,&r,&s,&t ) )
401
{
402
*u = NodeU[map[i][0]]*r + NodeU[map[i][1]]*s + NodeU[map[i][2]]*t;
403
*v = NodeV[map[i][0]]*r + NodeV[map[i][1]]*s + NodeV[map[i][2]]*t;
404
*w = NodeW[map[i][0]]*r + NodeW[map[i][1]]*s + NodeW[map[i][2]]*t;
405
return TRUE;
406
}
407
}
408
409
return FALSE;
410
}
411
412
/*******************************************************************************
413
*
414
* Name: elm_15node_wedge_isoline
415
*
416
* Purpose: Extract a iso line from triangle with given threshold
417
*
418
* Parameters:
419
*
420
* Input: (double) K, contour threshold
421
* (double *) F, contour quantity
422
* (double *) C, color quantity
423
* (double *) X,Y,Z vertex coords.
424
*
425
* Output: (line_t *) place to store the line
426
*
427
* Return value: number of lines generated (0,...,24)
428
*
429
******************************************************************************/
430
int elm_15node_wedge_isoline
431
(
432
double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line
433
)
434
{
435
double f[8],c[8],x[8],y[8],z[8];
436
437
int i, j, k, n=0, above=0;
438
439
int elm_8node_quad_isoline();
440
int elm_6node_triangle_isoline();
441
442
for( i=0; i<15; i++ ) above += F[i]>K;
443
if ( above == 0 || above == 15 ) return 0;
444
445
for( i=0; i<3; i++ )
446
{
447
for( j=0; j<8; j++ )
448
{
449
k = ElmWedgeFace[i][j];
450
f[j] = F[k];
451
c[j] = C[k];
452
x[j] = X[k];
453
y[j] = Y[k];
454
z[j] = Z[k];
455
}
456
n += elm_8node_quad_isoline( K,f,c,x,y,z,&Line[n] );
457
}
458
459
for( i=3; i<5; i++ )
460
{
461
for( j=0; j<6; j++ )
462
{
463
k = ElmWedgeFace[i][j];
464
f[j] = F[k];
465
c[j] = C[k];
466
x[j] = X[k];
467
y[j] = Y[k];
468
z[j] = Z[k];
469
}
470
n += elm_6node_triangle_isoline( K,f,c,x,y,z,&Line[n] );
471
}
472
473
return n;
474
}
475
476
/*******************************************************************************
477
*
478
* Name: elm_15node_wedge_isosurface
479
*
480
* Purpose: Extract isosurfaces for brick element.
481
*
482
* Parameters:
483
*
484
* Input: (double ) K: contour threshold
485
* (double *) F: contour quantity values at nodes
486
* (double *) C: color quantity values at nodes
487
* (double *) X,Y,Z: node coordinates
488
* (double *) U,V,W: normal vector at nodes
489
*
490
* Output: (polygon_t *)Polygon: output triangles.
491
*
492
* Return value: How many triangles we've got (possible values are 0-48)...
493
*
494
******************************************************************************/
495
int elm_15node_wedge_isosurface
496
(
497
double K,double *F,double *C, double *X,double *Y,double *Z,
498
double *U,double *V,double *W, polygon_t *Polygon
499
)
500
{
501
double tx[4],ty[4],tz[4],tu[4],tv[4],tw[4],tf[4],tc[4];
502
int i,j,n;
503
504
int above = 0, below = 0;
505
506
static int map[3][4] =
507
{
508
{ 4,3,2,0 }, { 4,2,1,0 }, { 4,5,3,2 }
509
};
510
int elm_4node_tetra_isosurface();
511
512
for( i=0; i<15; i++ ) above += F[i]>K;
513
for( i=0; i<15; i++ ) below += F[i]<K;
514
if ( below == 15 || above == 15 ) return 0;
515
516
n = 0;
517
for( i=0; i<3; i++ )
518
{
519
for( j=0; j<4; j++ )
520
{
521
tx[j] = X[map[i][j]];
522
ty[j] = Y[map[i][j]];
523
tz[j] = Z[map[i][j]];
524
tu[j] = U[map[i][j]];
525
tv[j] = V[map[i][j]];
526
tw[j] = W[map[i][j]];
527
tf[j] = F[map[i][j]];
528
tc[j] = C[map[i][j]];
529
}
530
n += elm_4node_tetra_isosurface( K,tf,tc,tx,ty,tz,tu,tv,tw,&Polygon[n] );
531
}
532
return n;
533
}
534
535
536
/******************************************************************************
537
*
538
* Name: elm_15node_wedge_initialize
539
*
540
* Purpose: Register the element type
541
*
542
* Parameters:
543
*
544
* Input: (char *) description of the element
545
* (int) numeric code for the element
546
*
547
* Output: Global list of element types is modified
548
*
549
* Return value: malloc() success
550
*
551
******************************************************************************/
552
int elm_15node_wedge_initialize()
553
{
554
static char *Name = "ELM_15NODE_WEDGE";
555
556
element_type_t ElementDef;
557
int elm_add_element_type();
558
559
elm_15node_wedge_shape_functions();
560
561
ElementDef.ElementName = Name;
562
ElementDef.ElementCode = 715;
563
564
ElementDef.NumberOfNodes = 15;
565
566
ElementDef.NodeU = NodeU;
567
ElementDef.NodeV = NodeV;
568
ElementDef.NodeW = NodeW;
569
570
ElementDef.PartialU = (double (*)())elm_15node_wedge_dndu_fvalue;
571
ElementDef.PartialV = (double (*)())elm_15node_wedge_dndv_fvalue;
572
ElementDef.PartialW = (double (*)())elm_15node_wedge_dndw_fvalue;
573
574
ElementDef.FunctionValue = (double (*)())elm_15node_wedge_fvalue;
575
ElementDef.Triangulate = (int (*)())elm_15node_wedge_triangulate;
576
ElementDef.PointInside = (int (*)())elm_15node_wedge_point_inside;
577
ElementDef.IsoLine = (int (*)())elm_15node_wedge_isoline;
578
ElementDef.IsoSurface = (int (*)())elm_15node_wedge_isosurface;
579
580
return elm_add_element_type( &ElementDef ) ;
581
}
582
583