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