/*****************************************************************************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 5 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. +355 0 457 272335* Telefax: +355 0 457 230236* EMail: [email protected]37*38* Date: 20 Sep 199539*40* Modification history:41*42* 25 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*54*/5556static double N[5][5],A[5][5];5758static double NodeU[] = { -1.0, 1.0, 1.0, -1.0, 0.0 };59static double NodeV[] = { -1.0, -1.0, 1.0, 1.0, 0.0,};6061/*******************************************************************************62*63* Name: elm_5node_quad_shape_functions( )64*65* Purpose: Initialize element shape function array. Internal only.66*67* Parameters:68*69* Input: Global (filewise) variables NodeU,NodeV,NodeW70*71* Output: Global (filewise) variable N[6][6], will contain72* shape function coefficients73*74* Return value: void75*76******************************************************************************/77static void elm_5node_quad_shape_functions()78{79double u,v;8081int i,j;8283for( i=0; i<5; i++ )84{85u = NodeU[i];86v = NodeV[i];8788A[i][0] = 1;89A[i][1] = u;90A[i][2] = v;91A[i][3] = u*v;92A[i][4] = u*u*v*v;93}9495lu_mtrinv( (double *)A,5 );9697for( i=0; i<5; i++ )98for( j=0; j<5; j++ ) N[i][j] = A[j][i];99}100101102/*******************************************************************************103*104* Name: elm_5node_quad_triangulate( geometry_t *,element_t * )105*106* Purpose: Triangulate an element. The process also builds up an edge107* table and adds new nodes to node table. The triangulation108* and edge table is stored in geometry_t *geom-structure.109*110* Parameters:111*112* Input: (geometry_t *) pointer to structure holding triangulation113* (element_t *) element to triangulate114*115* Output: (geometry_t *) structure is modified116*117* Return value: FALSE if malloc() fails, TRUE otherwise118*119******************************************************************************/120int elm_5node_quad_triangulate( geometry_t *geom,element_t *Elm )121{122triangle_t triangle;123124triangle.Element = Elm;125126triangle.v[0] = Elm->Topology[0];127triangle.v[1] = Elm->Topology[1];128triangle.v[2] = Elm->Topology[4];129130triangle.Edge[0] = TRUE;131triangle.Edge[1] = FALSE;132triangle.Edge[2] = FALSE;133134if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;135136triangle.v[0] = Elm->Topology[1];137triangle.v[1] = Elm->Topology[2];138triangle.v[2] = Elm->Topology[4];139140triangle.Edge[0] = TRUE;141triangle.Edge[1] = FALSE;142triangle.Edge[2] = FALSE;143144if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;145146triangle.v[0] = Elm->Topology[2];147triangle.v[1] = Elm->Topology[3];148triangle.v[2] = Elm->Topology[4];149150triangle.Edge[0] = TRUE;151triangle.Edge[1] = FALSE;152triangle.Edge[2] = FALSE;153154if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;155156triangle.v[0] = Elm->Topology[3];157triangle.v[1] = Elm->Topology[0];158triangle.v[2] = Elm->Topology[4];159160triangle.Edge[0] = TRUE;161triangle.Edge[1] = FALSE;162triangle.Edge[2] = FALSE;163164if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;165166return TRUE;167}168169/*******************************************************************************170*171* Name: elm_5node_quad_fvalue( double *,double,double )172*173* Purpose: return value of a quantity given on nodes at point (u,v)174*175*176*177* Parameters:178*179* Input: (double *) quantity values at nodes180* (double u,double v) point where values are evaluated181*182* Output: none183*184* Return value: quantity value185*186******************************************************************************/187static double elm_5node_quad_fvalue( double *F, double u, double v )188{189double R,uv=u*v,uu=u*u,vv=v*v,uuv=uu*v,uvv=u*vv;190int i;191192R = 0.0;193for( i=0; i<5; i++ )194{195R += F[i]*(N[i][0] +196N[i][1]*u +197N[i][2]*v +198N[i][3]*uv +199N[i][4]*uu*vv );200}201202return R;203}204205/*******************************************************************************206*207* Name: elm_5node_quad_dndu_fvalue( double *,double,double )208*209* Purpose: return value of a first partial derivate in (u) of a210* quantity given on nodes at point (u,v)211*212*213* Parameters:214*215* Input: (double *) quantity values at nodes216* (double u,double v) point where values are evaluated217*218* Output: none219*220* Return value: quantity value221*222******************************************************************************/223static double elm_5node_quad_dndu_fvalue( double *F, double u, double v )224{225double R=0.0,uv=u*v,vv=v*v;226int i;227228for( i=0; i<5; i++ )229{230R += F[i]*(N[i][1]+N[i][3]*v+2*N[i][4]*u*v*v );231}232233return R;234}235236/*******************************************************************************237*238* Name: elm_5node_quad_dndv_fvalue( double *,double,double )239*240* Purpose: return value of a first partial derivate in (v) of a241* quantity given on nodes at point (u,v)242*243*244* Parameters:245*246* Input: (double *) quantity values at nodes247* (double u,double v) point where values are evaluated248*249* Output: none250*251* Return value: quantity value252*253******************************************************************************/254static double elm_5node_quad_dndv_fvalue( double *F, double u, double v )255{256double R=0.0,uu=u*u,uv=u*v;257258int i;259260for( i=0; i<5; i++ )261{262R += F[i]*(N[i][2]+N[i][3]*u+2*N[i][4]*uu*v );263}264265return R;266}267268/*******************************************************************************269*270* Name: elm_5node_quad_dd(double *F,double *u,double *v,double *Values)271*272* Purpose: Return matrix of second partial derivates of given quantity273* at given point u,v.274*275* Parameters:276*277* Input: (double *)F: quantity values at nodes278* (double)u,v: point of evaluation279*280* Output: (double *)Values: 2x2 matrix of partial derivates281*282* Return value: void283*284*******************************************************************************/285static void elm_5node_quad_ddu( double *F,double u,double v,double *Values )286{287double ddu = 0.0, dudv=0.0, ddv = 0.0;288289int i;290291for( i=0; i<5; i++ )292{293ddu += F[i]*( 2*N[i][4]*v*v );294ddv += F[i]*( 2*N[i][4]*u*u );295dudv += F[i]*( N[i][3] + 4*N[i][4]*u*v );296}297298Values[0] = ddu;299Values[1] = dudv;300Values[2] = dudv;301Values[3] = ddv;302}303304/*******************************************************************************305*306* Name: elm_5node_quad_point_inside(307* double *nx,double *ny,double *nz,308* double px, double py, double pz,309* double *u,double *v,double *w )310*311* Purpose: Find if point (px,py,pz) is inside the element, and return312* element coordinates of the point.313*314* Parameters:315*316* Input: (double *) nx,ny,nz n coordinates317* (double) px,py,pz point to consider318*319* Output: (double *) u,v,w point in element coordinates if inside320*321* Return value: in/out status322*323* NOTES: the goal here can be hard for more involved element types. kind of324* trivial for this one... TODO: FIX THIS....325*326******************************************************************************/327int elm_5node_quad_point_inside328(329double *nx, double *ny, double *nz,330double px, double py, double pz, double *u,double *v,double *w331)332{333int elm_4node_quad_point_inside();334return elm_4node_quad_point_inside( nx,ny,nz,px,py,pz,u,v,w );335}336337/*******************************************************************************338*339* Name: elm_5node_quad_isoline340*341* Purpose: Extract a iso line from triangle with given threshold342*343* Parameters:344*345* Input: (double) K, contour threshold346* (double *) F, contour quantity347* (double *) C, color quantity348* (double *) X,Y,Z vertex coords.349*350* Output: (line_t *) place to store the line351*352* Return value: number of lines generated (0,...,4)353*354******************************************************************************/355int elm_5node_quad_isoline356(357double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line358)359{360double f[4],c[4],x[4],y[4],z[4];361362int i, j, k, n=0, above=0;363364static int map[4][2] =365{366{ 0,1 }, { 1,2 }, { 2,3 }, { 3,0 }367};368369int elm_3node_triangle_isoline();370371for( i=0; i<5; i++ ) above += F[i]>K;372if ( above == 0 || above == 5 ) return 0;373374f[2] = F[4];375c[2] = C[4];376x[2] = X[4];377y[2] = Y[4];378z[2] = Z[4];379380for( i=0; i<4; i++ )381{382for( j=1; j<2; j++ )383{384k = map[i][j];385f[j] = F[k];386c[j] = C[k];387x[j] = X[k];388y[j] = Y[k];389z[j] = Z[k];390}391n += elm_3node_triangle_isoline( K,f,c,x,y,z,&Line[n] );392}393394return n;395}396397398/******************************************************************************399*400* Name: elm_5node_quad_initialize( )401*402* Purpose: Register the element type403*404* Parameters:405*406* Input: (char *) description of the element407* (int) numeric code for the element408*409* Output: Global list of element types is modified410*411* Return value: malloc() success412*413******************************************************************************/414int elm_5node_quad_initialize()415{416element_type_t ElementDef;417418static char *Name = "ELM_5NODE_QUAD";419420int elm_add_element_type();421422elm_5node_quad_shape_functions();423424ElementDef.ElementName = Name;425ElementDef.ElementCode = 405;426427ElementDef.NumberOfNodes = 5;428ElementDef.NodeU = NodeU;429ElementDef.NodeV = NodeV;430ElementDef.NodeW = NULL;431432ElementDef.PartialU = (double (*)())elm_5node_quad_dndu_fvalue;433ElementDef.PartialV = (double (*)())elm_5node_quad_dndv_fvalue;434ElementDef.PartialW = NULL;435ElementDef.SecondPartials = (double (*)())elm_5node_quad_ddu;436437ElementDef.FunctionValue = (double (*)())elm_5node_quad_fvalue;438439ElementDef.Triangulate = (int (*)())elm_5node_quad_triangulate;440ElementDef.PointInside = (int (*)())elm_5node_quad_point_inside;441ElementDef.IsoLine = (int (*)())elm_5node_quad_isoline;442ElementDef.IsoSurface = (int (*)())NULL;443444return elm_add_element_type( &ElementDef );445}446447448