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