Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/post/src/elements/4node_quad_save.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 };
73
static double NodeV[] = { -1.0, -1.0, 1.0, 1.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 )
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
material_t *material=NULL;
103
104
#if 0
105
for( i=0; i<4; i++ )
106
{
107
x[i] = geom->Vertices[Elm->Topology[i]].x[0];
108
y[i] = geom->Vertices[Elm->Topology[i]].x[1];
109
z[i] = geom->Vertices[Elm->Topology[i]].x[2];
110
111
for( j=0; j<4; j++ )
112
{
113
f[j][i] = FuncArray[j][Elm->Topology[i]];
114
}
115
}
116
117
vertex.x[0] = elm_4node_quad_fvalue(x,0.0,0.0);
118
vertex.x[1] = elm_4node_quad_fvalue(y,0.0,0.0);
119
vertex.x[2] = elm_4node_quad_fvalue(z,0.0,0.0);
120
vertex.ElementModelNode = FALSE;
121
122
if ( (n=geo_add_vertex( geom,&vertex )) < 0 ) return FALSE;
123
124
for( j=0; j<4; j++ )
125
{
126
FuncArray[j][n] = elm_4node_quad_fvalue(f[j],0.0,0.0);
127
}
128
129
for( i=0; i<4; i++ )
130
{
131
triangle.v[0] = Elm->Topology[i];
132
if ( i==3 )
133
triangle.v[1] = Elm->Topology[0];
134
else
135
triangle.v[1] = Elm->Topology[i+1];
136
triangle.v[2] = n;
137
138
geo_triangle_normal( geom,&triangle );
139
140
triangle.Edge[0] = TRUE;
141
triangle.Edge[1] = FALSE;
142
triangle.Edge[2] = FALSE;
143
144
if ( !geo_add_triangle( geom,&triangle,material ) ) return FALSE;
145
}
146
#else
147
triangle.v[0] = Elm->Topology[0];
148
triangle.v[1] = Elm->Topology[1];
149
triangle.v[2] = Elm->Topology[2];
150
151
geo_triangle_normal( geom,&triangle );
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[0];
160
triangle.v[1] = Elm->Topology[2];
161
triangle.v[2] = Elm->Topology[3];
162
163
geo_triangle_normal( geom,&triangle );
164
165
triangle.Edge[0] = FALSE;
166
triangle.Edge[1] = TRUE;
167
triangle.Edge[2] = TRUE;
168
169
if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;
170
#endif
171
172
return TRUE;
173
}
174
175
/*******************************************************************************
176
*
177
* Name: elm_4node_quad_nvalue( double *,double,double )
178
*
179
* Purpose: return shape function values at given point (u,v)
180
*
181
*
182
*
183
* Parameters:
184
*
185
* Input: (double u,double v) point where values are evaluated
186
*
187
* Output: (double *) storage for values
188
*
189
* Return value: void
190
*
191
******************************************************************************/
192
static void elm_4node_quad_nvalue( double *R, double u, double v )
193
{
194
int i;
195
196
for( i=0; i<4; i++ )
197
{
198
R[i] = N[i][0] + N[i][1]*u + N[i][2]*v + N[i][3]*u*v;
199
}
200
}
201
202
/*******************************************************************************
203
*
204
* Name: elm_4node_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
double elm_4node_quad_fvalue( double *F, double u, double v )
221
{
222
double R=0.0,uv=u*v;
223
int i;
224
225
for( i=0; i<4; i++ )
226
{
227
R += F[i]*(N[i][0] + N[i][1]*u + N[i][2]*v + N[i][3]*uv);
228
}
229
230
return R;
231
}
232
233
/*******************************************************************************
234
*
235
* Name: elm_4node_quad_dndu_fvalue( double *,double,double )
236
*
237
* Purpose: return value of a first partial derivate in (u) of a
238
* quantity given on nodes at point (u,v)
239
*
240
*
241
* Parameters:
242
*
243
* Input: (double *) quantity values at nodes
244
* (double u,double v) point where values are evaluated
245
*
246
* Output: none
247
*
248
* Return value: quantity value
249
*
250
******************************************************************************/
251
static double elm_4node_quad_dndu_fvalue( double *F, double u, double v )
252
{
253
double R=0.0;
254
int i;
255
256
for( i=0; i<4; i++ ) R += F[i]*(N[i][1] + N[i][3]*v);
257
258
return R;
259
}
260
261
/*******************************************************************************
262
*
263
* Name: elm_4node_quad_dndv_fvalue( double *,double,double )
264
*
265
* Purpose: return value of a first partial derivate in (v) of a
266
* quantity given on nodes at point (u,v)
267
*
268
*
269
* Parameters:
270
*
271
* Input: (double *) quantity values at nodes
272
* (double u,double v) point where values are evaluated
273
*
274
* Output: none
275
*
276
* Return value: quantity value
277
*
278
******************************************************************************/
279
static double elm_4node_quad_dndv_fvalue( double *F, double u, double v )
280
{
281
double R=0.0;
282
int i;
283
284
for( i=0; i<4; i++ ) R += F[i]*(N[i][2] + N[i][3]*u);
285
286
return R;
287
}
288
289
/*******************************************************************************
290
*
291
* Name: elm_4node_quad_point_inside(
292
* double *nx,double *ny,double *nz,
293
* double px, double py, double pz,
294
* double *u,double *v,double *w )
295
*
296
* Purpose: Find if point (px,py,pz) is inside the element, and return
297
* element coordinates of the point.
298
*
299
* Parameters:
300
*
301
* Input: (double *) nx,ny,nz node coordinates
302
* (double) px,py,pz point to consider
303
*
304
* Output: (double *) u,v,w point in element coordinates if inside
305
*
306
* Return value: in/out status
307
*
308
* NOTES: the goal here can be hard for more involved element types. kind of
309
* trivial for this one...
310
*
311
******************************************************************************/
312
int elm_4node_quad_point_inside
313
(
314
double *nx, double *ny, double *nz,
315
double px, double py, double pz, double *u,double *v,double *w
316
)
317
{
318
double x[3],y[3],z[3],r,s,t;
319
int elm_3node_triangle_point_inside();
320
321
if ( px > MAX(MAX(MAX( nx[0],nx[1] ),nx[2] ),nx[3] ) ) return FALSE;
322
if ( px < MIN(MIN(MIN( nx[0],nx[1] ),nx[2] ),nx[3] ) ) return FALSE;
323
324
if ( py > MAX(MAX(MAX( ny[0],ny[1] ),ny[2] ),ny[3] ) ) return FALSE;
325
if ( py < MIN(MIN(MIN( ny[0],ny[1] ),ny[2] ),ny[3] ) ) return FALSE;
326
327
#if 0
328
if ( pz > MAX(MAX(MAX( nz[0],nz[1] ),nz[2] ),nz[3] ) ) return FALSE;
329
if ( pz < MIN(MIN(MIN( nz[0],nz[1] ),nz[2] ),nz[3] ) ) return FALSE;
330
#endif
331
332
333
#if 1
334
{
335
double ax,bx,cx,dx,ay,by,cy,dy,a,b,c,d;
336
337
ax = 0.25*( nx[0] + nx[1] + nx[2] + nx[3]);
338
bx = 0.25*(-nx[0] + nx[1] + nx[2] - nx[3]);
339
cx = 0.25*(-nx[0] - nx[1] + nx[2] + nx[3]);
340
dx = 0.25*( nx[0] - nx[1] + nx[2] - nx[3]);
341
342
ay = 0.25*( ny[0] + ny[1] + ny[2] + ny[3]);
343
by = 0.25*(-ny[0] + ny[1] + ny[2] - ny[3]);
344
cy = 0.25*(-ny[0] - ny[1] + ny[2] + ny[3]);
345
dy = 0.25*( ny[0] - ny[1] + ny[2] - ny[3]);
346
347
px -= ax;
348
py -= ay;
349
350
a = cy*dx - cx*dy;
351
b = bx*cy - by*cx + dy*px - dx*py;
352
c = by*px - bx*py;
353
354
if ( ABS(a)<1.0E-16 )
355
{
356
r = -c/b;
357
if ( r <= -1.0 || r >= 1.0 ) return FALSE;
358
359
*v = r;
360
*u = (px - cx*r)/(bx + dx*r);
361
return (*u >= -1.0 && *u <= 1.0);
362
}
363
364
if ( (d=b*b - 4*a*c) < 0.0 ) return FALSE;
365
366
r = (-b + sqrt(d))/(2*a);
367
if ( r >= -1.0 && r <= 1.0 )
368
{
369
*v = r;
370
*u = (px - cx*r)/(bx + dx*r);
371
if ( *u >= -1.0 && *u <= 1.0 ) return TRUE;
372
}
373
374
r = (-b - sqrt(d))/(2*a);
375
if ( r >= -1.0 && r <= 1.0 )
376
{
377
*v = r;
378
*u = (px - cx*r)/(bx + dx*r);
379
return (*u >= -1.0 && *u <= 1.0 );
380
}
381
382
return FALSE;
383
}
384
#endif
385
386
387
x[0] = elm_4node_quad_fvalue( nx,0.0,0.0 );
388
y[0] = elm_4node_quad_fvalue( ny,0.0,0.0 );
389
z[0] = elm_4node_quad_fvalue( nz,0.0,0.0 );
390
391
x[1] = nx[0];
392
y[1] = ny[0];
393
z[1] = nz[0];
394
x[2] = nx[1];
395
y[2] = ny[1];
396
z[2] = nz[1];
397
if ( elm_3node_triangle_point_inside( x,y,z,px,py,pz,&r,&s,&t ) )
398
{
399
*u = -r + s;
400
*v = -r - s;
401
*w = t;
402
return TRUE;
403
}
404
405
x[1] = nx[1];
406
y[1] = ny[1];
407
z[1] = nz[1];
408
x[2] = nx[2];
409
y[2] = ny[2];
410
z[2] = nz[2];
411
if ( elm_3node_triangle_point_inside( x,y,z,px,py,pz,&r,&s,&t ) )
412
{
413
*u = r + s;
414
*v = -r + s;
415
*w = t;
416
return TRUE;
417
}
418
419
x[1] = nx[2];
420
y[1] = ny[2];
421
z[1] = nz[2];
422
x[2] = nx[3];
423
y[2] = ny[3];
424
z[2] = nz[3];
425
if ( elm_3node_triangle_point_inside( x,y,z,px,py,pz,&r,&s,&t ) )
426
{
427
*u = r - s;
428
*v = r + s;
429
*w = t;
430
return TRUE;
431
}
432
433
x[1] = nx[3];
434
y[1] = ny[3];
435
z[1] = nz[3];
436
x[2] = nx[0];
437
y[2] = ny[0];
438
z[2] = nz[0];
439
if ( elm_3node_triangle_point_inside( x,y,z,px,py,pz,&r,&s,&t ) )
440
{
441
*u = -r - s;
442
*v = r - s;
443
*w = t;
444
return TRUE;
445
}
446
447
return FALSE;
448
}
449
450
/******************************************************************************
451
*
452
* Name: elm_4node_quad_initialize( )
453
*
454
* Purpose: Register the element type
455
*
456
* Parameters:
457
*
458
* Input: (char *) description of the element
459
* (int) numeric code for the element
460
*
461
* Output: Global list of element types is modified
462
*
463
* Return value: malloc() success
464
*
465
******************************************************************************/
466
int elm_4node_quad_initialize()
467
{
468
element_type_t ElementDef;
469
470
static char *Name = "ELM_4NODE_QUAD";
471
int elm_add_element_type();
472
473
ElementDef.ElementName = Name;
474
ElementDef.ElementCode = 404;
475
476
ElementDef.NumberOfNodes = 4;
477
ElementDef.NodeU = NodeU;
478
ElementDef.NodeV = NodeV;
479
ElementDef.NodeW = NULL;
480
481
ElementDef.PartialU = (double (*)())elm_4node_quad_dndu_fvalue;
482
ElementDef.PartialV = (double (*)())elm_4node_quad_dndv_fvalue;
483
ElementDef.PartialW = NULL;
484
485
ElementDef.FunctionValue = (double (*)())elm_4node_quad_fvalue;
486
ElementDef.Triangulate = (int (*)())elm_4node_quad_triangulate;
487
ElementDef.PointInside = (int (*)())elm_4node_quad_point_inside;
488
489
return elm_add_element_type( &ElementDef );
490
}
491
492