Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/elements/4node_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 4 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
* Four node quadrilater surface element
55
*
56
* 3----------2
57
* | |
58
* | |
59
* v | |
60
* 0----------1
61
* u
62
*/
63
64
static double N[4][4] =
65
{
66
{ 1.0/4.0, -1.0/4.0, -1.0/4.0, 1.0/4.0 }, /* 1 - u - v + uv */
67
{ 1.0/4.0, 1.0/4.0, -1.0/4.0, -1.0/4.0 },
68
{ 1.0/4.0, 1.0/4.0, 1.0/4.0, 1.0/4.0 },
69
{ 1.0/4.0, -1.0/4.0, 1.0/4.0, -1.0/4.0 }
70
};
71
72
static double NodeU[] = { -1.0, 1.0, 1.0, -1.0, 0.0 };
73
static double NodeV[] = { -1.0, -1.0, 1.0, 1.0, 0.0 };
74
75
/*******************************************************************************
76
*
77
* Name: elm_4node_quad_triangulate( geometry_t *,element_t * )
78
*
79
* Purpose: Triangulate an element. The process also builds up an edge
80
* table and adds new nodes to node table. The triangulation
81
* and edge table is stored in geometry_t *geom-structure.
82
*
83
* Parameters:
84
*
85
* Input: (geometry_t *) pointer to structure holding triangulation
86
* (element_t *) element to triangulate
87
*
88
* Output: (geometry_t *) structure is modified
89
*
90
* Return value: FALSE if malloc() fails, TRUE otherwise
91
*
92
******************************************************************************/
93
int elm_4node_quad_triangulate( geometry_t *geom,element_t *Elm,element_t *Parent )
94
{
95
double x[4],y[4],z[4],f[4][4],elm_4node_quad_fvalue();
96
97
triangle_t triangle;
98
vertex_t vertex;
99
100
int i,j,n;
101
102
#if 0
103
for( i=0; i<4; i++ )
104
{
105
x[i] = geom->Vertices[Elm->Topology[i]].x[0];
106
y[i] = geom->Vertices[Elm->Topology[i]].x[1];
107
z[i] = geom->Vertices[Elm->Topology[i]].x[2];
108
109
for( j=0; j<4; j++ )
110
{
111
f[j][i] = FuncArray[j][Elm->Topology[i]];
112
}
113
}
114
115
vertex.x[0] = elm_4node_quad_fvalue(x,0.0,0.0);
116
vertex.x[1] = elm_4node_quad_fvalue(y,0.0,0.0);
117
vertex.x[2] = elm_4node_quad_fvalue(z,0.0,0.0);
118
vertex.ElementModelNode = FALSE;
119
120
if ( (n=geo_add_vertex( geom,&vertex )) < 0 ) return FALSE;
121
122
for( j=0; j<4; j++ )
123
{
124
FuncArray[j][n] = elm_4node_quad_fvalue(f[j],0.0,0.0);
125
}
126
127
triangle.Element = Elm;
128
for( i=0; i<4; i++ )
129
{
130
triangle.v[0] = Elm->Topology[i];
131
if ( i==3 )
132
triangle.v[1] = Elm->Topology[0];
133
else
134
triangle.v[1] = Elm->Topology[i+1];
135
triangle.v[2] = n;
136
137
geo_triangle_normal( geom,&triangle );
138
139
triangle.Edge[0] = TRUE;
140
triangle.Edge[1] = FALSE;
141
triangle.Edge[2] = FALSE;
142
143
if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;
144
}
145
#else
146
triangle.Element = Parent;
147
148
triangle.v[0] = Elm->Topology[0];
149
triangle.v[1] = Elm->Topology[1];
150
triangle.v[2] = Elm->Topology[2];
151
152
triangle.Edge[0] = TRUE;
153
triangle.Edge[1] = TRUE;
154
triangle.Edge[2] = FALSE;
155
156
if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;
157
158
triangle.v[0] = Elm->Topology[0];
159
triangle.v[1] = Elm->Topology[2];
160
triangle.v[2] = Elm->Topology[3];
161
162
triangle.Edge[0] = FALSE;
163
triangle.Edge[1] = TRUE;
164
triangle.Edge[2] = TRUE;
165
166
if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;
167
#endif
168
169
return TRUE;
170
}
171
172
/*******************************************************************************
173
*
174
* Name: elm_4node_quad_nvalue( double *,double,double )
175
*
176
* Purpose: return shape function values at given point (u,v)
177
*
178
*
179
*
180
* Parameters:
181
*
182
* Input: (double u,double v) point where values are evaluated
183
*
184
* Output: (double *) storage for values
185
*
186
* Return value: void
187
*
188
******************************************************************************/
189
static void elm_4node_quad_nvalue( double *R, double u, double v )
190
{
191
int i;
192
193
for( i=0; i<4; i++ )
194
{
195
R[i] = N[i][0] + N[i][1]*u + N[i][2]*v + N[i][3]*u*v;
196
}
197
}
198
199
/*******************************************************************************
200
*
201
* Name: elm_4node_quad_fvalue( double *,double,double )
202
*
203
* Purpose: return value of a quantity given on nodes at point (u,v)
204
*
205
*
206
*
207
* Parameters:
208
*
209
* Input: (double *) quantity values at nodes
210
* (double u,double v) point where values are evaluated
211
*
212
* Output: none
213
*
214
* Return value: quantity value
215
*
216
******************************************************************************/
217
double elm_4node_quad_fvalue( double *F, double u, double v )
218
{
219
double R=0.0,uv=u*v;
220
int i;
221
222
for( i=0; i<4; i++ )
223
{
224
R += F[i]*( N[i][0] + N[i][1]*u + N[i][2]*v + N[i][3]*uv );
225
}
226
227
return R;
228
}
229
230
/*******************************************************************************
231
*
232
* Name: elm_4node_quad_dndu_fvalue( double *,double,double )
233
*
234
* Purpose: return value of a first partial derivate in (u) of a
235
* quantity given on nodes at point (u,v)
236
*
237
*
238
* Parameters:
239
*
240
* Input: (double *) quantity values at nodes
241
* (double u,double v) point where values are evaluated
242
*
243
* Output: none
244
*
245
* Return value: quantity value
246
*
247
******************************************************************************/
248
static double elm_4node_quad_dndu_fvalue( double *F, double u, double v )
249
{
250
double R=0.0;
251
int i;
252
253
for( i=0; i<4; i++ ) R += F[i]*(N[i][1] + N[i][3]*v);
254
255
return R;
256
}
257
258
/*******************************************************************************
259
*
260
* Name: elm_4node_quad_dndv_fvalue( double *,double,double )
261
*
262
* Purpose: return value of a first partial derivate in (v) of a
263
* quantity given on nodes at point (u,v)
264
*
265
*
266
* Parameters:
267
*
268
* Input: (double *) quantity values at nodes
269
* (double u,double v) point where values are evaluated
270
*
271
* Output: none
272
*
273
* Return value: quantity value
274
*
275
******************************************************************************/
276
static double elm_4node_quad_dndv_fvalue( double *F, double u, double v )
277
{
278
double R=0.0;
279
int i;
280
281
for( i=0; i<4; i++ ) R += F[i]*(N[i][2] + N[i][3]*u);
282
283
return R;
284
}
285
286
/*******************************************************************************
287
*
288
* Name: elm_4node_quad_point_inside(
289
* double *nx,double *ny,double *nz,
290
* double px, double py, double pz,
291
* double *u,double *v,double *w )
292
*
293
* Purpose: Find if point (px,py,pz) is inside the element, and return
294
* element coordinates of the point.
295
*
296
* Parameters:
297
*
298
* Input: (double *) nx,ny,nz node coordinates
299
* (double) px,py,pz point to consider
300
*
301
* Output: (double *) u,v,w point in element coordinates if inside
302
*
303
* Return value: in/out status
304
*
305
* NOTES: the goal here can be hard for more involved element types. kind of
306
* trivial for this one...
307
*
308
******************************************************************************/
309
int elm_4node_quad_point_inside
310
(
311
double *nx, double *ny, double *nz,
312
double px, double py, double pz, double *u,double *v,double *w
313
)
314
{
315
double ax,bx,cx,dx,ay,by,cy,dy,a,b,c,d,r;
316
317
*u = *v = *w = 0.0;
318
319
if ( px > MAX(MAX(MAX( nx[0],nx[1] ),nx[2] ),nx[3] ) ) return FALSE;
320
if ( px < MIN(MIN(MIN( nx[0],nx[1] ),nx[2] ),nx[3] ) ) return FALSE;
321
322
if ( py > MAX(MAX(MAX( ny[0],ny[1] ),ny[2] ),ny[3] ) ) return FALSE;
323
if ( py < MIN(MIN(MIN( ny[0],ny[1] ),ny[2] ),ny[3] ) ) return FALSE;
324
#if 0
325
if ( pz > MAX(MAX(MAX( nz[0],nz[1] ),nz[2] ),nz[3] ) ) return FALSE;
326
if ( pz < MIN(MIN(MIN( nz[0],nz[1] ),nz[2] ),nz[3] ) ) return FALSE;
327
#endif
328
329
ax = 0.25*( nx[0] + nx[1] + nx[2] + nx[3] );
330
bx = 0.25*( -nx[0] + nx[1] + nx[2] - nx[3] );
331
cx = 0.25*( -nx[0] - nx[1] + nx[2] + nx[3] );
332
dx = 0.25*( nx[0] - nx[1] + nx[2] - nx[3] );
333
334
ay = 0.25*( ny[0] + ny[1] + ny[2] + ny[3] );
335
by = 0.25*( -ny[0] + ny[1] + ny[2] - ny[3] );
336
cy = 0.25*( -ny[0] - ny[1] + ny[2] + ny[3] );
337
dy = 0.25*( ny[0] - ny[1] + ny[2] - ny[3] );
338
339
px -= ax;
340
py -= ay;
341
342
a = cy*dx - cx*dy;
343
b = bx*cy - by*cx + dy*px - dx*py;
344
c = by*px - bx*py;
345
346
*u = *v = *w = 0.0;
347
348
if ( ABS(a) < AEPS )
349
{
350
r = -c/b;
351
if ( r < -1.0 || r > 1.0 ) return FALSE;
352
353
*v = r;
354
if ( ABS(bx + dx*r) < AEPS )
355
*u = (py - cy*r)/(by + dy*r);
356
else
357
*u = (px - cx*r)/(bx + dx*r);
358
359
return (*u >= -1.0 && *u <= 1.0);
360
}
361
362
if ( (d=b*b - 4*a*c) < 0.0 ) return FALSE;
363
364
r = 1.0/(2*a);
365
b = r*b;
366
d = r*sqrt(d);
367
368
r = -b + d;
369
if ( r >= -1.0 && r <= 1.0 )
370
{
371
*v = r;
372
if ( ABS(bx + dx*r) < AEPS )
373
*u = (py - cy*r)/(by + dy*r);
374
else
375
*u = (px - cx*r)/(bx + dx*r);
376
if ( *u >= -1.0 && *u <= 1.0 ) return TRUE;
377
}
378
379
r = -b - d;
380
if ( r >= -1.0 && r <= 1.0 )
381
{
382
*v = r;
383
if ( ABS(bx + dx*r) < AEPS )
384
*u = (py - cy*r)/(by + dy*r);
385
else
386
*u = (px - cx*r)/(bx + dx*r);
387
return (*u >= -1.0 && *u <= 1.0 );
388
}
389
390
return FALSE;
391
}
392
393
/*******************************************************************************
394
*
395
* Name: elm_4node_quad_isoline
396
*
397
* Purpose: Extract a iso line from triangle with given threshold
398
*
399
* Parameters:
400
*
401
* Input: (double) K, contour threshold
402
* (double *) F, contour quantity
403
* (double *) C, color quantity
404
* (double *) X,Y,Z vertex coords.
405
*
406
* Output: (line_t *) place to store the line
407
*
408
* Return value: number of lines generated (0,...,4)
409
*
410
******************************************************************************/
411
int elm_4node_quad_isoline
412
(
413
double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line
414
)
415
{
416
double f[3],c[3],x[3],y[3],z[3];
417
418
int i, n=0, above=0;
419
int elm_3node_triangle_isoline();
420
421
for( i=0; i<4; i++ ) above += F[i]>K;
422
if ( above == 0 || above == 4 ) return 0;
423
424
f[0] = elm_4node_quad_fvalue( F,0.0,0.0 );
425
c[0] = elm_4node_quad_fvalue( C,0.0,0.0 );
426
x[0] = elm_4node_quad_fvalue( X,0.0,0.0 );
427
y[0] = elm_4node_quad_fvalue( Y,0.0,0.0 );
428
z[0] = elm_4node_quad_fvalue( Z,0.0,0.0 );
429
430
f[1] = F[3];
431
c[1] = C[3];
432
x[1] = X[3];
433
y[1] = Y[3];
434
z[1] = Z[3];
435
for( i=0; i<4; i++ )
436
{
437
f[2] = F[i];
438
c[2] = C[i];
439
x[2] = X[i];
440
y[2] = Y[i];
441
z[2] = Z[i];
442
443
n += elm_3node_triangle_isoline( K,f,c,x,y,z,&Line[n] );
444
445
f[1] = F[i];
446
c[1] = C[i];
447
x[1] = X[i];
448
y[1] = Y[i];
449
z[1] = Z[i];
450
}
451
452
return n;
453
}
454
455
456
/******************************************************************************
457
*
458
* Name: elm_4node_quad_initialize( )
459
*
460
* Purpose: Register the element type
461
*
462
* Parameters:
463
*
464
* Input: (char *) description of the element
465
* (int) numeric code for the element
466
*
467
* Output: Global list of element types is modified
468
*
469
* Return value: malloc() success
470
*
471
******************************************************************************/
472
int elm_4node_quad_initialize()
473
{
474
element_type_t ElementDef;
475
476
static char *Name = "ELM_4NODE_QUAD";
477
int elm_add_element_type();
478
479
ElementDef.ElementName = Name;
480
ElementDef.ElementCode = 404;
481
482
ElementDef.NumberOfNodes = 4;
483
ElementDef.NodeU = NodeU;
484
ElementDef.NodeV = NodeV;
485
ElementDef.NodeW = NULL;
486
487
ElementDef.PartialU = (double (*)())elm_4node_quad_dndu_fvalue;
488
ElementDef.PartialV = (double (*)())elm_4node_quad_dndv_fvalue;
489
ElementDef.PartialW = NULL;
490
491
ElementDef.FunctionValue = (double (*)())elm_4node_quad_fvalue;
492
ElementDef.Triangulate = (int (*)())elm_4node_quad_triangulate;
493
ElementDef.PointInside = (int (*)())elm_4node_quad_point_inside;
494
ElementDef.IsoLine = (int (*)())elm_4node_quad_isoline;
495
ElementDef.IsoSurface = (int (*)())NULL;
496
497
return elm_add_element_type( &ElementDef );
498
}
499
500