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