/*****************************************************************************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 six node triangle 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*41* Modification history:42*43******************************************************************************/4445#include "../elmerpost.h"46#include <elements.h>474849/*50* SIX NODE TRIANGLE ELEMENT51*52* shape functions: N0 = (1-u-v)(1-2u-2v) 2 v=153* N1 = u(2u-1) / \54* N2 = v(2v-1) / \55* N3 = 4u(1-u-v) 5 456* N4 = 4uv / \57* N5 = 4v(1-u-v) 0-----3-----1 u=158*59*/6061static double N[6][6],A[6][6];6263static double NodeU[] = { 0.0, 1.0, 0.0, 0.5, 0.5, 0.0 };64static double NodeV[] = { 0.0, 0.0, 1.0, 0.0, 0.5, 0.5 };6566/*******************************************************************************67*68* Name: elm_6node_triangle_shape_functions( )69*70* Purpose: Initialize element shape function array. Internal only.71*72* Parameters:73*74* Input: Global (filewise) variables NodeU,NodeV,NodeW75*76* Output: Global (filewise) variable N[6][6], will contain77* shape function coefficients78*79* Return value: void80*81******************************************************************************/82static void elm_6node_triangle_shape_functions()83{84double u,v;8586int i,j;8788for( i=0; i<6; i++ )89{90u = NodeU[i];91v = NodeV[i];9293A[i][0] = 1;94A[i][1] = u;95A[i][2] = v;96A[i][3] = u*v;97A[i][4] = u*u;98A[i][5] = v*v;99}100101lu_mtrinv( (double *)A,6 );102103for( i=0; i<6; i++ )104for( j=0; j<6; j++ ) N[i][j] = A[j][i];105}106107/*******************************************************************************108*109* Name: elm_6node_triangle_triangulate( geometry_t *,element_t * )110*111* Purpose: Triangulate an element. The process also builds up an edge112* table and adds new nodes to node table. The triangulation113* and edge table is stored in geometry_t *geom-structure.114*115* Parameters:116*117* Input: (geometry_t *) pointer to structure holding triangulation118* (element_t *) element to triangulate119*120* Output: (geometry_t *) structure is modified121*122* Return value: FALSE if malloc() fails, TRUE otherwise123*124******************************************************************************/125int elm_6node_triangle_triangulate( geometry_t *geom, element_t *Elm, element_t *Parent )126{127double u,v,w,s;128129static int map[4][3] =130{131{ 0,3,5 }, { 3,1,4 }, { 3,4,5 }, { 4,2,5 }132};133static int edge_map[4][3] =134{135{ 1,0,1 }, { 1,1,0 }, { 0,0,0 }, { 1,1,0 }136};137138int i,j;139140triangle_t triangle;141142triangle.Element = Parent;143for( i=0; i<4; i++ )144{145triangle.v[0] = Elm->Topology[map[i][0]];146triangle.v[1] = Elm->Topology[map[i][1]];147triangle.v[2] = Elm->Topology[map[i][2]];148149triangle.Edge[0] = edge_map[i][0];150triangle.Edge[1] = edge_map[i][1];151triangle.Edge[2] = edge_map[i][2];152153if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;154}155156return TRUE;157}158159/*******************************************************************************160*161* Name: elm_6node_triangle_point_inside(162* double *nx,double *ny,double *nz,163* double px, double py, double pz,164* double *u,double *v,double *w )165*166* Purpose: Find if point (px,py,pz) is inside the element, and return167* element coordinates of the point.168*169* Parameters:170*171* Input: (double *) nx,ny,nz node coordinates172* (double) px,py,pz point to consider173*174* Output: (double *) u,v,w point in element coordinates if inside175*176* Return value: in/out status177*178* NOTES: the goal here can be hard for more involved element types. kind of179* trivial for this one... (TODO: this is for xy-plane tri only)180*181******************************************************************************/182int elm_6node_triangle_point_inside183(184double *nx, double *ny, double *nz,185double px, double py, double pz, double *u,double *v,double *w186)187{188int elm_3node_triangle_point_inside();189return elm_3node_triangle_point_inside( nx,ny,nz,px,py,pz,u,v,w );190}191192/*******************************************************************************193*194* Name: elm_6node_triangle_fvalue( double *,double,double )195*196* Purpose: return value of a quantity given on nodes at point (u,v)197*198*199* Parameters:200*201* Input: (double *) quantity values at nodes202* (double u,double v) point where value is evaluated203*204* Output: none205*206* Return value: quantity value207*208******************************************************************************/209static double elm_6node_triangle_fvalue( double *F,double u,double v )210{211double R=0.0,uv=u*v,u2=u*u,v2=v*v;212int i;213214for( i=0; i<6; i++ )215{216R += F[i]*( N[i][0] +217N[i][1]*u +218N[i][2]*v +219N[i][3]*uv +220N[i][4]*u2 +221N[i][5]*v2 );222}223224return R;225}226227/*******************************************************************************228*229* Name: elm_6node_triangle_dndu_fvalue( double *,double,double )230*231* Purpose: return value of a first partial derivate in (u) of a232* quantity given on nodes at point (u,v)233*234*235* Parameters:236*237* Input: (double *) quantity values at nodes238* (double u,double v) point where value is evaluated239*240* Output: none241*242* Return value: quantity value243*244******************************************************************************/245static double elm_6node_triangle_dndu_fvalue(double *F,double u,double v)246{247double R=0.0,u2=2*u;248int i;249250for( i=0; i<6; i++ )251{252R += F[i]*( N[i][1] + N[i][3]*v + N[i][4]*u2 );253}254255return R;256}257258/*******************************************************************************259*260* Name: elm_6node_triangle_dndv_fvalue( double *,double,double )261*262* Purpose: return value of a first partial derivate in (v) of a263* quantity given on nodes at point (u,v)264*265*266* Parameters:267*268* Input: (double *) quantity values at nodes269* (double u,double v) point where value is evaluated270*271* Output: none272*273* Return value: quantity value274*275******************************************************************************/276static double elm_6node_triangle_dndv_fvalue(double *F,double u,double v)277{278double R=0.0,v2=2*v;279int i;280281for( i=0; i<6; i++ )282{283R += F[i]*(N[i][2]+N[i][3]*u+N[i][5]*v2);284}285286return R;287}288289/*******************************************************************************290*291* Name: elm_6node_triangle_isoline292*293* Purpose: Extract a iso line from triangle with given threshold294*295* Parameters:296*297* Input: (double) K, contour threshold298* (double *) F, contour quantity299* (double *) C, color quantity300* (double *) X,Y,Z vertex coords.301*302* Output: (line_t *) place to store the line303*304* Return value: number of lines generated (0,...,6)305*306******************************************************************************/307int elm_6node_triangle_isoline308(309double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line310)311{312double f[3],c[3],x[3],y[3],z[3];313314int i, j, k, n=0, above=0;315316static int map[6][2] =317{318{ 0,3 }, { 3,1 }, { 1,4 }, { 4,2 }, { 2,5 }, { 5,0 }319};320321int elm_3node_triangle_isoline();322323for( i=0; i<6; i++ ) above += F[i]>K;324if ( above == 0 || above == 6 ) return 0;325326f[0] = elm_6node_triangle_fvalue( F,1.0/3.0,1.0/3.0 );327c[0] = elm_6node_triangle_fvalue( C,1.0/3.0,1.0/3.0 );328x[0] = elm_6node_triangle_fvalue( X,1.0/3.0,1.0/3.0 );329y[0] = elm_6node_triangle_fvalue( Y,1.0/3.0,1.0/3.0 );330z[0] = elm_6node_triangle_fvalue( Z,1.0/3.0,1.0/3.0 );331332for( i=0; i<6; i++ )333{334for( j=1; j<3; j++ )335{336k = map[i][j-1];337f[j] = F[k];338c[j] = C[k];339x[j] = X[k];340y[j] = Y[k];341z[j] = Z[k];342}343n += elm_3node_triangle_isoline( K,f,c,x,y,z,&Line[n] );344}345346return n;347}348349350/*******************************************************************************351*352* Name: elm_6node_triangle_initialize( )353*354* Purpose: Register the element type355*356* Parameters:357*358* Input: (char *) description of the element359* (int) numeric code for the element360*361* Output: Global list of element types is modified362*363* Return value: malloc() success364*365******************************************************************************/366int elm_6node_triangle_initialize()367{368static char *Name = "ELM_6NODE_TRIANGLE";369370element_type_t ElementDef;371int elm_add_element_type();372373elm_6node_triangle_shape_functions();374375ElementDef.ElementName = Name;376ElementDef.ElementCode = 306;377378ElementDef.NumberOfNodes = 6;379380ElementDef.NodeU = NodeU;381ElementDef.NodeV = NodeV;382ElementDef.NodeW = NULL;383384ElementDef.PartialU = (double (*)())elm_6node_triangle_dndu_fvalue;385ElementDef.PartialV = (double (*)())elm_6node_triangle_dndv_fvalue;386ElementDef.PartialW = (double (*)())NULL;387388ElementDef.FunctionValue = (double (*)())elm_6node_triangle_fvalue;389ElementDef.Triangulate = (int (*)())elm_6node_triangle_triangulate;390ElementDef.PointInside = (int (*)())elm_6node_triangle_point_inside;391ElementDef.IsoLine = (int (*)())elm_6node_triangle_isoline;392ElementDef.IsoSurface = (int (*)())NULL;393394return elm_add_element_type( &ElementDef ) ;395}396397398