/*****************************************************************************1*2* Elmer, A Finite Element Software for Multiphysical Problems3*4* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland5*6* This program is free software; you can redistribute it and/or7* modify it under the terms of the GNU General Public License8* as published by the Free Software Foundation; either version 29* of the License, or (at your option) any later version.10*11* This program is distributed in the hope that it will be useful,12* but WITHOUT ANY WARRANTY; without even the implied warranty of13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14* GNU General Public License for more details.15*16* You should have received a copy of the GNU General Public License17* along with this program (in file fem/GPL-2); if not, write to the18* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,19* Boston, MA 02110-1301, USA.20*21*****************************************************************************/2223/*******************************************************************************24*25* Definition of 4 node quad element.26*27*******************************************************************************28*29* Author: Juha Ruokolainen30*31* Address: CSC - IT Center for Science Ltd.32* Keilaranta 14, P.O. BOX 40533* 02101 Espoo, Finland34* Tel. +358 0 457 272335* Telefax: +358 0 457 230236* EMail: [email protected]37*38* Date: 20 Sep 199539*40* Modification history:41*42* 28 Sep 1995, changed call to elm_triangle_normal to geo_triangle normal43* routine elm_... doesn't exist anymore44* Juha R45*46*47******************************************************************************/4849#include "../elmerpost.h"50#include "elements.h"5152/*53* Four node quadrilater surface element54*55* 3----------256* | |57* | |58* v | |59* 0----------160* u61*/6263static double N[4][4] =64{65{ 1.0/4.0, -1.0/4.0, -1.0/4.0, 1.0/4.0 }, /* 1 - u - v + uv */66{ 1.0/4.0, 1.0/4.0, -1.0/4.0, -1.0/4.0 },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};7071static double NodeU[] = { -1.0, 1.0, 1.0, -1.0 };72static double NodeV[] = { -1.0, -1.0, 1.0, 1.0 };7374/*******************************************************************************75*76* Name: elm_4node_quad_triangulate( geometry_t *,element_t * )77*78* Purpose: Triangulate an element. The process also builds up an edge79* table and adds new nodes to node table. The triangulation80* and edge table is stored in geometry_t *geom-structure.81*82* Parameters:83*84* Input: (geometry_t *) pointer to structure holding triangulation85* (element_t *) element to triangulate86*87* Output: (geometry_t *) structure is modified88*89* Return value: FALSE if malloc() fails, TRUE otherwise90*91******************************************************************************/92int elm_4node_quad_triangulate( geometry_t *geom,element_t *Elm )93{94double x[4],y[4],z[4],f[4][4],elm_4node_quad_fvalue();9596triangle_t triangle;97vertex_t vertex;9899int i,j,n;100101material_t *material=NULL;102103#if 0104for( i=0; i<4; i++ )105{106x[i] = geom->Vertices[Elm->Topology[i]].x[0];107y[i] = geom->Vertices[Elm->Topology[i]].x[1];108z[i] = geom->Vertices[Elm->Topology[i]].x[2];109110for( j=0; j<4; j++ )111{112f[j][i] = FuncArray[j][Elm->Topology[i]];113}114}115116vertex.x[0] = elm_4node_quad_fvalue(x,0.0,0.0);117vertex.x[1] = elm_4node_quad_fvalue(y,0.0,0.0);118vertex.x[2] = elm_4node_quad_fvalue(z,0.0,0.0);119vertex.ElementModelNode = FALSE;120121if ( (n=geo_add_vertex( geom,&vertex )) < 0 ) return FALSE;122123for( j=0; j<4; j++ )124{125FuncArray[j][n] = elm_4node_quad_fvalue(f[j],0.0,0.0);126}127128for( i=0; i<4; i++ )129{130triangle.v[0] = Elm->Topology[i];131if ( i==3 )132triangle.v[1] = Elm->Topology[0];133else134triangle.v[1] = Elm->Topology[i+1];135triangle.v[2] = n;136137geo_triangle_normal( geom,&triangle );138139triangle.Edge[0] = TRUE;140triangle.Edge[1] = FALSE;141triangle.Edge[2] = FALSE;142143if ( !geo_add_triangle( geom,&triangle,material ) ) return FALSE;144}145#else146triangle.v[0] = Elm->Topology[0];147triangle.v[1] = Elm->Topology[1];148triangle.v[2] = Elm->Topology[2];149150geo_triangle_normal( geom,&triangle );151152triangle.Edge[0] = TRUE;153triangle.Edge[1] = TRUE;154triangle.Edge[2] = FALSE;155156if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;157158triangle.v[0] = Elm->Topology[0];159triangle.v[1] = Elm->Topology[2];160triangle.v[2] = Elm->Topology[3];161162geo_triangle_normal( geom,&triangle );163164triangle.Edge[0] = FALSE;165triangle.Edge[1] = TRUE;166triangle.Edge[2] = TRUE;167168if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;169#endif170171return TRUE;172}173174/*******************************************************************************175*176* Name: elm_4node_quad_nvalue( double *,double,double )177*178* Purpose: return shape function values at given point (u,v)179*180*181*182* Parameters:183*184* Input: (double u,double v) point where values are evaluated185*186* Output: (double *) storage for values187*188* Return value: void189*190******************************************************************************/191static void elm_4node_quad_nvalue( double *R, double u, double v )192{193int i;194195for( i=0; i<4; i++ )196{197R[i] = N[i][0] + N[i][1]*u + N[i][2]*v + N[i][3]*u*v;198}199}200201/*******************************************************************************202*203* Name: elm_4node_quad_fvalue( double *,double,double )204*205* Purpose: return value of a quantity given on nodes at point (u,v)206*207*208*209* Parameters:210*211* Input: (double *) quantity values at nodes212* (double u,double v) point where values are evaluated213*214* Output: none215*216* Return value: quantity value217*218******************************************************************************/219double elm_4node_quad_fvalue( double *F, double u, double v )220{221double R=0.0,uv=u*v;222int i;223224for( i=0; i<4; i++ )225{226R += F[i]*(N[i][0] + N[i][1]*u + N[i][2]*v + N[i][3]*uv);227}228229return R;230}231232/*******************************************************************************233*234* Name: elm_4node_quad_dndu_fvalue( double *,double,double )235*236* Purpose: return value of a first partial derivate in (u) of a237* quantity given on nodes at point (u,v)238*239*240* Parameters:241*242* Input: (double *) quantity values at nodes243* (double u,double v) point where values are evaluated244*245* Output: none246*247* Return value: quantity value248*249******************************************************************************/250static double elm_4node_quad_dndu_fvalue( double *F, double u, double v )251{252double R=0.0;253int i;254255for( i=0; i<4; i++ ) R += F[i]*(N[i][1] + N[i][3]*v);256257return R;258}259260/*******************************************************************************261*262* Name: elm_4node_quad_dndv_fvalue( double *,double,double )263*264* Purpose: return value of a first partial derivate in (v) of a265* quantity given on nodes at point (u,v)266*267*268* Parameters:269*270* Input: (double *) quantity values at nodes271* (double u,double v) point where values are evaluated272*273* Output: none274*275* Return value: quantity value276*277******************************************************************************/278static double elm_4node_quad_dndv_fvalue( double *F, double u, double v )279{280double R=0.0;281int i;282283for( i=0; i<4; i++ ) R += F[i]*(N[i][2] + N[i][3]*u);284285return R;286}287288/*******************************************************************************289*290* Name: elm_4node_quad_point_inside(291* double *nx,double *ny,double *nz,292* double px, double py, double pz,293* double *u,double *v,double *w )294*295* Purpose: Find if point (px,py,pz) is inside the element, and return296* element coordinates of the point.297*298* Parameters:299*300* Input: (double *) nx,ny,nz node coordinates301* (double) px,py,pz point to consider302*303* Output: (double *) u,v,w point in element coordinates if inside304*305* Return value: in/out status306*307* NOTES: the goal here can be hard for more involved element types. kind of308* trivial for this one...309*310******************************************************************************/311int elm_4node_quad_point_inside312(313double *nx, double *ny, double *nz,314double px, double py, double pz, double *u,double *v,double *w315)316{317double x[3],y[3],z[3],r,s,t;318int elm_3node_triangle_point_inside();319320if ( px > MAX(MAX(MAX( nx[0],nx[1] ),nx[2] ),nx[3] ) ) return FALSE;321if ( px < MIN(MIN(MIN( nx[0],nx[1] ),nx[2] ),nx[3] ) ) return FALSE;322323if ( py > MAX(MAX(MAX( ny[0],ny[1] ),ny[2] ),ny[3] ) ) return FALSE;324if ( py < MIN(MIN(MIN( ny[0],ny[1] ),ny[2] ),ny[3] ) ) return FALSE;325326#if 0327if ( pz > MAX(MAX(MAX( nz[0],nz[1] ),nz[2] ),nz[3] ) ) return FALSE;328if ( pz < MIN(MIN(MIN( nz[0],nz[1] ),nz[2] ),nz[3] ) ) return FALSE;329#endif330331332#if 1333{334double ax,bx,cx,dx,ay,by,cy,dy,a,b,c,d;335336ax = 0.25*( nx[0] + nx[1] + nx[2] + nx[3]);337bx = 0.25*(-nx[0] + nx[1] + nx[2] - nx[3]);338cx = 0.25*(-nx[0] - nx[1] + nx[2] + nx[3]);339dx = 0.25*( nx[0] - nx[1] + nx[2] - nx[3]);340341ay = 0.25*( ny[0] + ny[1] + ny[2] + ny[3]);342by = 0.25*(-ny[0] + ny[1] + ny[2] - ny[3]);343cy = 0.25*(-ny[0] - ny[1] + ny[2] + ny[3]);344dy = 0.25*( ny[0] - ny[1] + ny[2] - ny[3]);345346px -= ax;347py -= ay;348349a = cy*dx - cx*dy;350b = bx*cy - by*cx + dy*px - dx*py;351c = by*px - bx*py;352353if ( ABS(a)<1.0E-16 )354{355r = -c/b;356if ( r <= -1.0 || r >= 1.0 ) return FALSE;357358*v = r;359*u = (px - cx*r)/(bx + dx*r);360return (*u >= -1.0 && *u <= 1.0);361}362363if ( (d=b*b - 4*a*c) < 0.0 ) return FALSE;364365r = (-b + sqrt(d))/(2*a);366if ( r >= -1.0 && r <= 1.0 )367{368*v = r;369*u = (px - cx*r)/(bx + dx*r);370if ( *u >= -1.0 && *u <= 1.0 ) return TRUE;371}372373r = (-b - sqrt(d))/(2*a);374if ( r >= -1.0 && r <= 1.0 )375{376*v = r;377*u = (px - cx*r)/(bx + dx*r);378return (*u >= -1.0 && *u <= 1.0 );379}380381return FALSE;382}383#endif384385386x[0] = elm_4node_quad_fvalue( nx,0.0,0.0 );387y[0] = elm_4node_quad_fvalue( ny,0.0,0.0 );388z[0] = elm_4node_quad_fvalue( nz,0.0,0.0 );389390x[1] = nx[0];391y[1] = ny[0];392z[1] = nz[0];393x[2] = nx[1];394y[2] = ny[1];395z[2] = nz[1];396if ( elm_3node_triangle_point_inside( x,y,z,px,py,pz,&r,&s,&t ) )397{398*u = -r + s;399*v = -r - s;400*w = t;401return TRUE;402}403404x[1] = nx[1];405y[1] = ny[1];406z[1] = nz[1];407x[2] = nx[2];408y[2] = ny[2];409z[2] = nz[2];410if ( elm_3node_triangle_point_inside( x,y,z,px,py,pz,&r,&s,&t ) )411{412*u = r + s;413*v = -r + s;414*w = t;415return TRUE;416}417418x[1] = nx[2];419y[1] = ny[2];420z[1] = nz[2];421x[2] = nx[3];422y[2] = ny[3];423z[2] = nz[3];424if ( elm_3node_triangle_point_inside( x,y,z,px,py,pz,&r,&s,&t ) )425{426*u = r - s;427*v = r + s;428*w = t;429return TRUE;430}431432x[1] = nx[3];433y[1] = ny[3];434z[1] = nz[3];435x[2] = nx[0];436y[2] = ny[0];437z[2] = nz[0];438if ( elm_3node_triangle_point_inside( x,y,z,px,py,pz,&r,&s,&t ) )439{440*u = -r - s;441*v = r - s;442*w = t;443return TRUE;444}445446return FALSE;447}448449/******************************************************************************450*451* Name: elm_4node_quad_initialize( )452*453* Purpose: Register the element type454*455* Parameters:456*457* Input: (char *) description of the element458* (int) numeric code for the element459*460* Output: Global list of element types is modified461*462* Return value: malloc() success463*464******************************************************************************/465int elm_4node_quad_initialize()466{467element_type_t ElementDef;468469static char *Name = "ELM_4NODE_QUAD";470int elm_add_element_type();471472ElementDef.ElementName = Name;473ElementDef.ElementCode = 404;474475ElementDef.NumberOfNodes = 4;476ElementDef.NodeU = NodeU;477ElementDef.NodeV = NodeV;478ElementDef.NodeW = NULL;479480ElementDef.PartialU = (double (*)())elm_4node_quad_dndu_fvalue;481ElementDef.PartialV = (double (*)())elm_4node_quad_dndv_fvalue;482ElementDef.PartialW = NULL;483484ElementDef.FunctionValue = (double (*)())elm_4node_quad_fvalue;485ElementDef.Triangulate = (int (*)())elm_4node_quad_triangulate;486ElementDef.PointInside = (int (*)())elm_4node_quad_point_inside;487488return elm_add_element_type( &ElementDef );489}490491492