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