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