/*****************************************************************************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 6 node wedge 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: 4 Oct 199539*40******************************************************************************/4142#include "../elmerpost.h"43#include <elements.h>4445/*46* 15 node wedge volume element.47*48* 3-----------449* /| /| w v50* / | / | | /51* / | / | |/52* / 0----/------1 ---u53* / / / //54* / / /// //55* / // //56* / // //57* 5/ / //58* | / //59* | / //60* |//61* 262*/6364static double A[15][15],N[15][15];6566static double NodeU[] = { 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 0.0, 0.5, 0.5, 0.0, 0.0, 1.0, 0.0 };67static double NodeV[] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.5, 0.0, 0.5, 0.5, 0.0, 0.0, 1.0 };68static double NodeW[] = { -1.0,-1.0,-1.0, 1.0, 1.0, 1.0,-1.0,-1.0,-1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0 };6970/*******************************************************************************71*72* Name: elm_15node_wedge_triangulate73*74* Purpose: Triangulate an element. The process also builds up an edge75* table and adds new nodes to node table. The triangulation76* and edge table is stored in geometry_t *geom-structure.77*78* Parameters:79*80* Input: (geometry_t *) pointer to structure holding triangulation81* (element_t *) element to triangulate82*83* Output: (geometry_t *) structure is modified84*85* Return value: FALSE if malloc() fails, TRUE otherwise86*87******************************************************************************/88static int elm_15node_wedge_triangulate( geometry_t *geom,element_t *wedge )89{90element_t element;91int i,j;92int elm_8node_quad_triangulate();93int geo_add_edge();94int elm_6node_triangle_triangulate();959697if ( GlobalOptions.VolumeSides )98{99int topo[8];100101element.DisplayFlag = TRUE;102element.Topology = topo;103for( i=0; i<MAX_GROUP_IDS; i++ ) element.GroupIds[i] = wedge->GroupIds[i];104105for( i=0; i<3; i++ )106{107for( j=0; j<8; j++ )108{109element.Topology[j] = wedge->Topology[ElmWedgeFace[i][j]];110}111if ( !elm_8node_quad_triangulate( geom, &element, wedge ) ) return FALSE;112}113114for( i=3; i<5; i++ )115{116for( j=0; j<6; j++ )117{118element.Topology[j] = wedge->Topology[ElmWedgeFace[i][j]];119}120if ( !elm_6node_triangle_triangulate( geom, &element, wedge ) ) return FALSE;121}122} else {123if ( !geo_add_edge( geom, wedge->Topology[0], wedge->Topology[1],wedge ) ) return FALSE;124if ( !geo_add_edge( geom, wedge->Topology[0], wedge->Topology[2],wedge ) ) return FALSE;125if ( !geo_add_edge( geom, wedge->Topology[0], wedge->Topology[3],wedge ) ) return FALSE;126if ( !geo_add_edge( geom, wedge->Topology[1], wedge->Topology[2],wedge ) ) return FALSE;127if ( !geo_add_edge( geom, wedge->Topology[1], wedge->Topology[4],wedge ) ) return FALSE;128if ( !geo_add_edge( geom, wedge->Topology[2], wedge->Topology[5],wedge ) ) return FALSE;129if ( !geo_add_edge( geom, wedge->Topology[3], wedge->Topology[4],wedge ) ) return FALSE;130if ( !geo_add_edge( geom, wedge->Topology[3], wedge->Topology[5],wedge ) ) return FALSE;131if ( !geo_add_edge( geom, wedge->Topology[4], wedge->Topology[5],wedge ) ) return FALSE;132}133134return TRUE;135}136137/*******************************************************************************138*139* Name: elm_15node_wedge_shape_functions140*141* Purpose: Initialize element shape function array. Internal only.142*143* Parameters:144*145* Input: Global (filewise) variables NodeU,NodeV,NodeW146*147* Output: Global (filewise) variable N[15][15], will contain148* shape function coefficients149*150* Return value: void151* Return value: void152*153******************************************************************************/154static void elm_15node_wedge_shape_functions()155{156double u,v,w;157int i,j;158159for( i=0; i<15; i++ )160{161u = NodeU[i];162v = NodeV[i];163w = NodeW[i];164165A[i][0] = 1;166A[i][1] = u;167A[i][2] = u*u;168A[i][3] = v;169A[i][4] = u*v;170A[i][5] = v*v;171A[i][6] = w;172A[i][7] = u*w;173A[i][8] = u*u*w;174A[i][9] = v*w;175A[i][10] = u*v*w;176A[i][11] = v*v*w;177A[i][12] = w*w;178A[i][13] = u*w*w;179A[i][14] = v*w*w;180}181182lu_mtrinv( (double *)A,15 );183184for( i=0; i<15; i++ )185for( j=0; j<15; j++ ) N[i][j] = A[j][i];186}187188/*******************************************************************************189*190* Name: elm_15node_wedge_fvalue191*192* Purpose: return value of a quantity given on nodes at point (u,v)193* Use trough (element_type_t *) structure.194*195* Parameters:196*197* Input: (double *) quantity values at nodes198* (double u,double v) point where values are evaluated199*200* Output: none201*202* Return value: quantity value203*204******************************************************************************/205static double elm_15node_wedge_fvalue(double *F,double u,double v,double w)206{207double R=0.0,uw=u*w,vw=v*w;208int i;209210for( i=0; i<15; i++ )211{212R += F[i]*(N[i][0]+213N[i][1]*u+214N[i][2]*u*u+215N[i][3]*v+216N[i][4]*u*v+217N[i][5]*v*v+218N[i][6]*w+219N[i][7]*u*w+220N[i][8]*u*u*w+221N[i][9]*v*w+222N[i][10]*u*v*w+223N[i][11]*v*v*w+224N[i][12]*w*w+225N[i][13]*u*w*w+226N[i][14]*v*w*w);227}228229return R;230}231232/*******************************************************************************233*234* Name: elm_15node_wedge_dndu_fvalue235*236* Purpose: return value of a first partial derivate in (v) of a237* quantity given on nodes at point (u,v).238* Use trough (element_type_t *) structure.239*240*241* Parameters:242*243* Input: (double *) quantity values at nodes244* (double u,double v,double w) point where values are evaluated245*246* Output: none247*248* Return value: quantity value249*250******************************************************************************/251static double elm_15node_wedge_dndu_fvalue(double *F,double u,double v,double w)252{253double R=0.0;254int i;255256for( i=0; i<15; i++ )257{258R += F[i]*( N[i][1] + 2*N[i][2]*u + N[i][4]*v + N[i][7]*w +2592*N[i][8]*u*w + N[i][10]*v*w + N[i][13]*w*w );260}261262return R;263}264265/*******************************************************************************266*267* Name: elm_15node_wedge_dndv_fvalue268*269* Purpose: return value of a first partial derivate in (v) of a270* quantity given on nodes at point (u,v,w).271* Use trough (element_type_t *) structure.272*273*274* Parameters:275*276* Input: (double *) quantity values at nodes277* (double u,double v,double w) point where values are evaluated278*279* Output: none280*281* Return value: quantity value282*283******************************************************************************/284static double elm_15node_wedge_dndv_fvalue(double *F,double u,double v,double w)285{286double R=0.0;287int i;288289for( i=0; i<15; i++ )290{291R += F[i]*( N[i][3] + N[i][4]*u + 2*N[i][5]*v + N[i][9]*w +292N[i][10]*u*w + 2*N[i][11]*v*w + N[i][14]*w*w );293}294295return R;296}297298/*******************************************************************************299*300* Name: elm_15node_wedge_dndw_fvalue301*302* Purpose: return value of a first partial derivate in (w) of a303* quantity given on nodes at point (u,v,w)304* Use trough (element_type_t *) structure.305*306*307* Parameters:308*309* Input: (double *) quantity values at nodes310* (double u,double v,double w) point where values are evaluated311*312* Output: none313*314* Return value: quantity value315*316******************************************************************************/317static double elm_15node_wedge_dndw_fvalue(double *F,double u,double v,double w)318{319double R=0.0;320int i;321322for( i=0; i<15; i++ )323{324R += F[i]*( N[i][6] + N[i][7]*u + N[i][8]*u*u + N[i][9]*v + N[i][10]*u*v +325N[i][11]*v*v + 2*N[i][12]*w + 2*N[i][13]*u*w + 2*N[i][14]*v*w );326}327328return R;329}330331332333/*******************************************************************************334*335* Name: elm_15node_wedge_point_inside(336* double *nx,double *ny,double *nz,337* double px, double py, double pz,338* double *u,double *v,double *w )339*340* Purpose: Find if point (px,py,pz) is inside the element, and return341* element coordinates of the point.342*343* Parameters:344*345* Input: (double *) nx,ny,nz node coordinates346* (double) px,py,pz point to consider347*348* Output: (double *) u,v,w point in element coordinates if inside349*350* Return value: in/out status351*352* NOTES: the goal here can be hard for more involved element types. kind of353* trivial for this one...354*355******************************************************************************/356int elm_15node_wedge_point_inside357(358double *nx, double *ny, double *nz,359double px, double py, double pz, double *u,double *v,double *w360)361{362double x[4],y[4],z[4],r,s,t,maxx,minx,maxy,miny,maxz,minz;363int i,j;364365static int map[3][4] =366{367{ 4,3,2,0 }, { 4,2,1,0 }, { 4,5,3,2 }368};369370int elm_4node_tetra_point_inside();371maxx = minx = nx[0];372maxy = miny = ny[0];373maxz = minz = nz[0];374375for( i=1; i<15; i++ )376{377maxx = MAX( nx[i],maxx );378maxy = MAX( ny[i],maxy );379maxz = MAX( nz[i],maxz );380381minx = MIN( nx[i],minx );382miny = MIN( ny[i],miny );383minz = MIN( nz[i],minz );384}385386if ( px > maxx || px < minx ) return FALSE;387if ( py > maxy || py < miny ) return FALSE;388if ( pz > maxz || pz < minz ) return FALSE;389390for( i=0; i<3; i++ )391{392for( j=0; j<4; j++ )393{394x[j] = nx[map[i][j]];395y[j] = ny[map[i][j]];396z[j] = nz[map[i][j]];397}398399if ( elm_4node_tetra_point_inside( x,y,z,px,py,pz,&r,&s,&t ) )400{401*u = NodeU[map[i][0]]*r + NodeU[map[i][1]]*s + NodeU[map[i][2]]*t;402*v = NodeV[map[i][0]]*r + NodeV[map[i][1]]*s + NodeV[map[i][2]]*t;403*w = NodeW[map[i][0]]*r + NodeW[map[i][1]]*s + NodeW[map[i][2]]*t;404return TRUE;405}406}407408return FALSE;409}410411/*******************************************************************************412*413* Name: elm_15node_wedge_isoline414*415* Purpose: Extract a iso line from triangle with given threshold416*417* Parameters:418*419* Input: (double) K, contour threshold420* (double *) F, contour quantity421* (double *) C, color quantity422* (double *) X,Y,Z vertex coords.423*424* Output: (line_t *) place to store the line425*426* Return value: number of lines generated (0,...,24)427*428******************************************************************************/429int elm_15node_wedge_isoline430(431double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line432)433{434double f[8],c[8],x[8],y[8],z[8];435436int i, j, k, n=0, above=0;437438int elm_8node_quad_isoline();439int elm_6node_triangle_isoline();440441for( i=0; i<15; i++ ) above += F[i]>K;442if ( above == 0 || above == 15 ) return 0;443444for( i=0; i<3; i++ )445{446for( j=0; j<8; j++ )447{448k = ElmWedgeFace[i][j];449f[j] = F[k];450c[j] = C[k];451x[j] = X[k];452y[j] = Y[k];453z[j] = Z[k];454}455n += elm_8node_quad_isoline( K,f,c,x,y,z,&Line[n] );456}457458for( i=3; i<5; i++ )459{460for( j=0; j<6; j++ )461{462k = ElmWedgeFace[i][j];463f[j] = F[k];464c[j] = C[k];465x[j] = X[k];466y[j] = Y[k];467z[j] = Z[k];468}469n += elm_6node_triangle_isoline( K,f,c,x,y,z,&Line[n] );470}471472return n;473}474475/*******************************************************************************476*477* Name: elm_15node_wedge_isosurface478*479* Purpose: Extract isosurfaces for brick element.480*481* Parameters:482*483* Input: (double ) K: contour threshold484* (double *) F: contour quantity values at nodes485* (double *) C: color quantity values at nodes486* (double *) X,Y,Z: node coordinates487* (double *) U,V,W: normal vector at nodes488*489* Output: (polygon_t *)Polygon: output triangles.490*491* Return value: How many triangles we've got (possible values are 0-48)...492*493******************************************************************************/494int elm_15node_wedge_isosurface495(496double K,double *F,double *C, double *X,double *Y,double *Z,497double *U,double *V,double *W, polygon_t *Polygon498)499{500double tx[4],ty[4],tz[4],tu[4],tv[4],tw[4],tf[4],tc[4];501int i,j,n;502503int above = 0, below = 0;504505static int map[3][4] =506{507{ 4,3,2,0 }, { 4,2,1,0 }, { 4,5,3,2 }508};509int elm_4node_tetra_isosurface();510511for( i=0; i<15; i++ ) above += F[i]>K;512for( i=0; i<15; i++ ) below += F[i]<K;513if ( below == 15 || above == 15 ) return 0;514515n = 0;516for( i=0; i<3; i++ )517{518for( j=0; j<4; j++ )519{520tx[j] = X[map[i][j]];521ty[j] = Y[map[i][j]];522tz[j] = Z[map[i][j]];523tu[j] = U[map[i][j]];524tv[j] = V[map[i][j]];525tw[j] = W[map[i][j]];526tf[j] = F[map[i][j]];527tc[j] = C[map[i][j]];528}529n += elm_4node_tetra_isosurface( K,tf,tc,tx,ty,tz,tu,tv,tw,&Polygon[n] );530}531return n;532}533534535/******************************************************************************536*537* Name: elm_15node_wedge_initialize538*539* Purpose: Register the element type540*541* Parameters:542*543* Input: (char *) description of the element544* (int) numeric code for the element545*546* Output: Global list of element types is modified547*548* Return value: malloc() success549*550******************************************************************************/551int elm_15node_wedge_initialize()552{553static char *Name = "ELM_15NODE_WEDGE";554555element_type_t ElementDef;556int elm_add_element_type();557558elm_15node_wedge_shape_functions();559560ElementDef.ElementName = Name;561ElementDef.ElementCode = 715;562563ElementDef.NumberOfNodes = 15;564565ElementDef.NodeU = NodeU;566ElementDef.NodeV = NodeV;567ElementDef.NodeW = NodeW;568569ElementDef.PartialU = (double (*)())elm_15node_wedge_dndu_fvalue;570ElementDef.PartialV = (double (*)())elm_15node_wedge_dndv_fvalue;571ElementDef.PartialW = (double (*)())elm_15node_wedge_dndw_fvalue;572573ElementDef.FunctionValue = (double (*)())elm_15node_wedge_fvalue;574ElementDef.Triangulate = (int (*)())elm_15node_wedge_triangulate;575ElementDef.PointInside = (int (*)())elm_15node_wedge_point_inside;576ElementDef.IsoLine = (int (*)())elm_15node_wedge_isoline;577ElementDef.IsoSurface = (int (*)())elm_15node_wedge_isosurface;578579return elm_add_element_type( &ElementDef ) ;580}581582583