/*****************************************************************************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 ten 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* TEN NODE TRIANGLE ELEMENT51*52*/5354static double N[10][10],A[10][10];5556static double NodeU[] = { 0.0, 1.0, 0.0, 1./3., 2./3., 2./3., 1./3., 0.0, 0.0, 1./3. };57static double NodeV[] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1./3., 2./3., 2./3, 1./3., 1./3. };5859/*******************************************************************************60*61* Name: elm_10node_triangle_shape_functions( )62*63* Purpose: Initialize element shape function array. Internal only.64*65* Parameters:66*67* Input: Global (filewise) variables NodeU,NodeV,NodeW68*69* Output: Global (filewise) variable N[10][10], will contain70* shape function coefficients71*72* Return value: void73*74******************************************************************************/75static void elm_10node_triangle_shape_functions()76{77double u,v;7879int i,j;8081for( i=0; i<10; i++ )82{83u = NodeU[i];84v = NodeV[i];858687A[i][0] = 1;88A[i][1] = u;89A[i][2] = v;90A[i][3] = u*v;91A[i][4] = u*u;92A[i][5] = v*v;93A[i][6] = u*u*v;94A[i][7] = u*v*v;95A[i][8] = u*u*u;96A[i][9] = v*v*v;9798}99100lu_mtrinv( (double *)A,10 );101102for( i=0; i<10; i++ )103for( j=0; j<10; j++ ) N[i][j] = A[j][i];104}105106/*******************************************************************************107*108* Name: elm_10node_triangle_triangulate( geometry_t *,element_t * )109*110* Purpose: Triangulate an element. The process also builds up an edge111* table and adds new nodes to node table. The triangulation112* and edge table is stored in geometry_t *geom-structure.113*114* Parameters:115*116* Input: (geometry_t *) pointer to structure holding triangulation117* (element_t *) element to triangulate118*119* Output: (geometry_t *) structure is modified120*121* Return value: FALSE if malloc() fails, TRUE otherwise122*123******************************************************************************/124int elm_10node_triangle_triangulate( geometry_t *geom, element_t *Elm )125{126double u,v,w,s;127128static int map[9][3] =129{130{ 0,3,8 }, { 3,4,9 }, { 3,9,8 },131{ 4,5,9 }, { 4,1,5 }, { 5,6,9 },132{ 8,9,7 }, { 9,6,7 }, { 7,6,2 }133};134static int edge_map[9][3] =135{136{ 1,0,1 }, { 1,0,0 }, { 0,0,0 },137{ 0,0,0 }, { 1,1,0 }, { 1,0,0 },138{ 0,0,1 }, { 0,0,0 }, { 0,1,1 }139};140141int i,j;142143triangle_t triangle;144145triangle.Element = Elm;146for( i=0; i<9; i++ )147{148triangle.v[0] = Elm->Topology[map[i][0]];149triangle.v[1] = Elm->Topology[map[i][1]];150triangle.v[2] = Elm->Topology[map[i][2]];151152triangle.Edge[0] = edge_map[i][0];153triangle.Edge[1] = edge_map[i][1];154triangle.Edge[2] = edge_map[i][2];155156if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;157}158159return TRUE;160}161162/*******************************************************************************163*164* Name: elm_10node_triangle_point_inside(165* double *nx,double *ny,double *nz,166* double px, double py, double pz,167* double *u,double *v,double *w )168*169* Purpose: Find if point (px,py,pz) is inside the element, and return170* element coordinates of the point.171*172* Parameters:173*174* Input: (double *) nx,ny,nz node coordinates175* (double) px,py,pz point to consider176*177* Output: (double *) u,v,w point in element coordinates if inside178*179* Return value: in/out status180*181* NOTES: the goal here can be hard for more involved element types. kind of182* trivial for this one... (TODO: this is for xy-plane tri only)183*184******************************************************************************/185int elm_10node_triangle_point_inside186(187double *nx, double *ny, double *nz,188double px, double py, double pz, double *u,double *v,double *w189)190{191int elm_3node_triangle_point_inside();192return elm_3node_triangle_point_inside( nx,ny,nz,px,py,pz,u,v,w );193}194195/*******************************************************************************196*197* Name: elm_10node_triangle_fvalue( double *,double,double )198*199* Purpose: return value of a quantity given on nodes at point (u,v)200*201*202* Parameters:203*204* Input: (double *) quantity values at nodes205* (double u,double v) point where value is evaluated206*207* Output: none208*209* Return value: quantity value210*211******************************************************************************/212static double elm_10node_triangle_fvalue( double *F,double u,double v )213{214double R=0.0,uv=u*v,u2=u*u,v2=v*v;215int i;216217218for( i=0; i<10; i++ )219{220R += F[i]*( N[i][0] +221N[i][1]*u +222N[i][2]*v +223N[i][3]*uv +224N[i][4]*u2 +225N[i][5]*v2 +226N[i][6]*u2*v +227N[i][7]*u*v2 +228N[i][8]*u2*u +229N[i][9]*v2*v );230}231232return R;233}234235/*******************************************************************************236*237* Name: elm_10node_triangle_dndu_fvalue( double *,double,double )238*239* Purpose: return value of a first partial derivate in (u) of a240* quantity given on nodes at point (u,v)241*242*243* Parameters:244*245* Input: (double *) quantity values at nodes246* (double u,double v) point where value is evaluated247*248* Output: none249*250* Return value: quantity value251*252******************************************************************************/253static double elm_10node_triangle_dndu_fvalue(double *F,double u,double v)254{255double R=0.0;256int i;257258for( i=0; i<10; i++ )259{260R += F[i]*( N[i][1] + N[i][3]*v + 2*N[i][4]*u +261N[i][6]*2*u*v + N[i][7]*v*v + 3*N[i][8]*u*u );262}263264return R;265}266267/*******************************************************************************268*269* Name: elm_10node_triangle_dndv_fvalue( double *,double,double )270*271* Purpose: return value of a first partial derivate in (v) of a272* quantity given on nodes at point (u,v)273*274*275* Parameters:276*277* Input: (double *) quantity values at nodes278* (double u,double v) point where value is evaluated279*280* Output: none281*282* Return value: quantity value283*284******************************************************************************/285static double elm_10node_triangle_dndv_fvalue(double *F,double u,double v)286{287double R=0.0;288int i;289290for( i=0; i<10; i++ )291{292R += F[i]*( N[i][2] + N[i][3]*u + 2*N[i][5]*v + N[i][6]*u*u +293N[i][7]*2*u*v + 3*N[i][9]*v*v);294}295296return R;297}298299/*******************************************************************************300*301* Name: elm_10node_triangle_isoline302*303* Purpose: Extract a iso line from triangle with given threshold304*305* Parameters:306*307* Input: (double) K, contour threshold308* (double *) F, contour quantity309* (double *) C, color quantity310* (double *) X,Y,Z vertex coords.311*312* Output: (line_t *) place to store the line313*314* Return value: number of lines generated (0,...,6)315*316******************************************************************************/317int elm_10node_triangle_isoline318(319double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line320)321{322double f[3],c[3],x[3],y[3],z[3];323324int i, j, k, n=0, above=0;325326static int map[9][3] =327{328{ 0,3,8 }, { 3,4,9 }, { 3,9,8 },329{ 4,5,9 }, { 4,1,5 }, { 5,6,9 },330{ 8,9,7 }, { 9,6,7 }, { 7,6,2 }331};332333for( i=0; i<10; i++ ) above += F[i]>K;334if ( above == 0 || above == 10 ) return 0;335336for( i=0; i<9; i++ )337{338int elm_3node_triangle_isoline();339for( j=0; j<3; j++ )340{341k = map[i][j-1];342f[j] = F[k];343c[j] = C[k];344x[j] = X[k];345y[j] = Y[k];346z[j] = Z[k];347}348n += elm_3node_triangle_isoline( K,f,c,x,y,z,&Line[n] );349}350351return n;352}353354355/*******************************************************************************356*357* Name: elm_10node_triangle_initialize( )358*359* Purpose: Register the element type360*361* Parameters:362*363* Input: (char *) description of the element364* (int) numeric code for the element365*366* Output: Global list of element types is modified367*368* Return value: malloc() success369*370******************************************************************************/371int elm_10node_triangle_initialize()372{373static char *Name = "ELM_10NODE_TRIANGLE";374375element_type_t ElementDef;376377int elm_add_element_type();378379elm_10node_triangle_shape_functions();380381ElementDef.ElementName = Name;382ElementDef.ElementCode = 310;383384ElementDef.NumberOfNodes = 10;385386ElementDef.NodeU = NodeU;387ElementDef.NodeV = NodeV;388ElementDef.NodeW = NULL;389390ElementDef.PartialU = (double (*)())elm_10node_triangle_dndu_fvalue;391ElementDef.PartialV = (double (*)())elm_10node_triangle_dndv_fvalue;392ElementDef.PartialW = (double (*)())NULL;393394ElementDef.FunctionValue = (double (*)())elm_10node_triangle_fvalue;395ElementDef.Triangulate = (int (*)())elm_10node_triangle_triangulate;396ElementDef.PointInside = (int (*)())elm_10node_triangle_point_inside;397ElementDef.IsoLine = (int (*)())elm_10node_triangle_isoline;398ElementDef.IsoSurface = (int (*)())NULL;399400return elm_add_element_type( &ElementDef ) ;401}402403404