/*****************************************************************************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* Six node wedge volume element.47*48* 5-----------449* /| /| w v50* / | / | | /51* / | / | |/52* / 2----/------1 ---u53* / / / //54* / / /// //55* / // //56* / // //57* 3/ / //58* | / //59* | / //60* |//61* 062*/6364static double A[6][6],N[6][6];6566static double NodeU[] = { 0.0, 1.0, 0.0, 0.0, 1.0, 0.0 };67static double NodeV[] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0 };68static double NodeW[] = { -1.0,-1.0,-1.0, 1.0, 1.0, 1.0 };6970/*******************************************************************************71*72* Name: elm_6node_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_6node_wedge_triangulate( geometry_t *geom,element_t *wedge )89{90element_t element;91int i,j;92int elm_4node_quad_triangulate();93int geo_add_edge();94int elm_3node_triangle_triangulate();959697if ( GlobalOptions.VolumeSides )98{99int topo[4];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<4; j++ )108{109element.Topology[j] = wedge->Topology[ElmWedgeFace[i][j]];110}111if ( !elm_4node_quad_triangulate( geom, &element, wedge ) ) return FALSE;112}113114for( i=3; i<5; i++ )115{116for( j=0; j<3; j++ )117{118element.Topology[j] = wedge->Topology[ElmWedgeFace[i][j]];119}120if ( !elm_3node_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_6node_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[6][6], will contain148* shape function coefficients149*150* Return value: void151* Return value: void152*153******************************************************************************/154static void elm_6node_wedge_shape_functions()155{156double u,v,w;157int i,j;158159for( i=0; i<6; i++ )160{161u = NodeU[i];162v = NodeV[i];163w = NodeW[i];164165A[i][0] = 1;166A[i][1] = u;167A[i][2] = v;168A[i][3] = w;169A[i][4] = u*w;170A[i][5] = v*w;171}172173lu_mtrinv( (double *)A,6 );174175for( i=0; i<6; i++ )176for( j=0; j<6; j++ ) N[i][j] = A[j][i];177}178179/*******************************************************************************180*181* Name: elm_6node_wedge_fvalue182*183* Purpose: return value of a quantity given on nodes at point (u,v)184* Use trough (element_type_t *) structure.185*186* Parameters:187*188* Input: (double *) quantity values at nodes189* (double u,double v) point where values are evaluated190*191* Output: none192*193* Return value: quantity value194*195******************************************************************************/196static double elm_6node_wedge_fvalue(double *F,double u,double v,double w)197{198double R=0.0,uw=u*w,vw=v*w;199int i;200201for( i=0; i<6; i++ )202{203R += F[i]*(N[i][0]+204N[i][1]*u+205N[i][2]*v+206N[i][3]*w+207N[i][4]*uw+208N[i][5]*vw);209}210211return R;212}213214/*******************************************************************************215*216* Name: elm_6node_wedge_dndu_fvalue217*218* Purpose: return value of a first partial derivate in (v) of a219* quantity given on nodes at point (u,v).220* Use trough (element_type_t *) structure.221*222*223* Parameters:224*225* Input: (double *) quantity values at nodes226* (double u,double v,double w) point where values are evaluated227*228* Output: none229*230* Return value: quantity value231*232******************************************************************************/233static double elm_6node_wedge_dndu_fvalue(double *F,double u,double v,double w)234{235double R=0.0;236int i;237238for( i=0; i<6; i++ )239{240R += F[i]*( N[i][1] + N[i][4]*w );241}242243return R;244}245246/*******************************************************************************247*248* Name: elm_6node_wedge_dndv_fvalue249*250* Purpose: return value of a first partial derivate in (v) of a251* quantity given on nodes at point (u,v,w).252* Use trough (element_type_t *) structure.253*254*255* Parameters:256*257* Input: (double *) quantity values at nodes258* (double u,double v,double w) point where values are evaluated259*260* Output: none261*262* Return value: quantity value263*264******************************************************************************/265static double elm_6node_wedge_dndv_fvalue(double *F,double u,double v,double w)266{267double R=0.0;268int i;269270for( i=0; i<6; i++ )271{272R += F[i]*( N[i][2] + N[i][5]*w );273}274275return R;276}277278/*******************************************************************************279*280* Name: elm_6node_wedge_dndw_fvalue281*282* Purpose: return value of a first partial derivate in (w) of a283* quantity given on nodes at point (u,v,w)284* Use trough (element_type_t *) structure.285*286*287* Parameters:288*289* Input: (double *) quantity values at nodes290* (double u,double v,double w) point where values are evaluated291*292* Output: none293*294* Return value: quantity value295*296******************************************************************************/297static double elm_6node_wedge_dndw_fvalue(double *F,double u,double v,double w)298{299double R=0.0;300int i;301302for( i=0; i<6; i++ )303{304R += F[i]*( N[i][3] + N[i][4]*u + N[i][5]*v );305}306307return R;308}309310311312/*******************************************************************************313*314* Name: elm_6node_wedge_point_inside(315* double *nx,double *ny,double *nz,316* double px, double py, double pz,317* double *u,double *v,double *w )318*319* Purpose: Find if point (px,py,pz) is inside the element, and return320* element coordinates of the point.321*322* Parameters:323*324* Input: (double *) nx,ny,nz node coordinates325* (double) px,py,pz point to consider326*327* Output: (double *) u,v,w point in element coordinates if inside328*329* Return value: in/out status330*331* NOTES: the goal here can be hard for more involved element types. kind of332* trivial for this one...333*334******************************************************************************/335int elm_6node_wedge_point_inside336(337double *nx, double *ny, double *nz,338double px, double py, double pz, double *u,double *v,double *w339)340{341double x[4],y[4],z[4],r,s,t,maxx,minx,maxy,miny,maxz,minz;342int i,j;343344static int map[3][4] =345{346{ 4,3,2,0 }, { 4,2,1,0 }, { 4,5,3,2 }347};348349int elm_4node_tetra_point_inside();350351maxx = minx = nx[0];352maxy = miny = ny[0];353maxz = minz = nz[0];354355for( i=1; i<6; i++ )356{357maxx = MAX( nx[i],maxx );358maxy = MAX( ny[i],maxy );359maxz = MAX( nz[i],maxz );360361minx = MIN( nx[i],minx );362miny = MIN( ny[i],miny );363minz = MIN( nz[i],minz );364}365366if ( px > maxx || px < minx ) return FALSE;367if ( py > maxy || py < miny ) return FALSE;368if ( pz > maxz || pz < minz ) return FALSE;369370for( i=0; i<3; i++ )371{372for( j=0; j<4; j++ )373{374x[j] = nx[map[i][j]];375y[j] = ny[map[i][j]];376z[j] = nz[map[i][j]];377}378379if ( elm_4node_tetra_point_inside( x,y,z,px,py,pz,&r,&s,&t ) )380{381*u = NodeU[map[i][0]]*r + NodeU[map[i][1]]*s + NodeU[map[i][2]]*t;382*v = NodeV[map[i][0]]*r + NodeV[map[i][1]]*s + NodeV[map[i][2]]*t;383*w = NodeW[map[i][0]]*r + NodeW[map[i][1]]*s + NodeW[map[i][2]]*t;384return TRUE;385}386}387388return FALSE;389}390391/*******************************************************************************392*393* Name: elm_6node_wedge_isoline394*395* Purpose: Extract a iso line from triangle with given threshold396*397* Parameters:398*399* Input: (double) K, contour threshold400* (double *) F, contour quantity401* (double *) C, color quantity402* (double *) X,Y,Z vertex coords.403*404* Output: (line_t *) place to store the line405*406* Return value: number of lines generated (0,...,24)407*408******************************************************************************/409int elm_6node_wedge_isoline410(411double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line412)413{414double f[4],c[4],x[4],y[4],z[4];415416int i, j, k, n=0, above=0;417int elm_4node_quad_isoline();418int elm_3node_triangle_isoline();419420for( i=0; i<6; i++ ) above += F[i]>K;421if ( above == 0 || above == 6 ) return 0;422423for( i=0; i<3; i++ )424{425for( j=0; j<4; j++ )426{427k = ElmWedgeFace[i][j];428f[j] = F[k];429c[j] = C[k];430x[j] = X[k];431y[j] = Y[k];432z[j] = Z[k];433}434n += elm_4node_quad_isoline( K,f,c,x,y,z,&Line[n] );435}436437for( i=3; i<5; i++ )438{439for( j=0; j<3; j++ )440{441k = ElmWedgeFace[i][j];442f[j] = F[k];443c[j] = C[k];444x[j] = X[k];445y[j] = Y[k];446z[j] = Z[k];447}448n += elm_3node_triangle_isoline( K,f,c,x,y,z,&Line[n] );449}450451return n;452}453454/*******************************************************************************455*456* Name: elm_6node_wedge_isosurface457*458* Purpose: Extract isosurfaces for brick element.459*460* Parameters:461*462* Input: (double ) K: contour threshold463* (double *) F: contour quantity values at nodes464* (double *) C: color quantity values at nodes465* (double *) X,Y,Z: node coordinates466* (double *) U,V,W: normal vector at nodes467*468* Output: (polygon_t *)Polygon: output triangles.469*470* Return value: How many triangles we've got (possible values are 0-48)...471*472******************************************************************************/473int elm_6node_wedge_isosurface474(475double K,double *F,double *C, double *X,double *Y,double *Z,476double *U,double *V,double *W, polygon_t *Polygon477)478{479double tx[4],ty[4],tz[4],tu[4],tv[4],tw[4],tf[4],tc[4];480int i,j,n;481482int above = 0, below = 0;483484static int map[3][4] =485{486{ 4,3,2,0 }, { 4,2,1,0 }, { 4,5,3,2 }487};488int elm_4node_tetra_isosurface();489490for( i=0; i<6; i++ ) above += F[i]>K;491for( i=0; i<6; i++ ) below += F[i]<K;492if ( below == 6 || above == 6 ) return 0;493494n = 0;495for( i=0; i<3; i++ )496{497for( j=0; j<4; j++ )498{499tx[j] = X[map[i][j]];500ty[j] = Y[map[i][j]];501tz[j] = Z[map[i][j]];502tu[j] = U[map[i][j]];503tv[j] = V[map[i][j]];504tw[j] = W[map[i][j]];505tf[j] = F[map[i][j]];506tc[j] = C[map[i][j]];507}508n += elm_4node_tetra_isosurface( K,tf,tc,tx,ty,tz,tu,tv,tw,&Polygon[n] );509}510return n;511}512513514/******************************************************************************515*516* Name: elm_6node_wedge_initialize517*518* Purpose: Register the element type519*520* Parameters:521*522* Input: (char *) description of the element523* (int) numeric code for the element524*525* Output: Global list of element types is modified526*527* Return value: malloc() success528*529******************************************************************************/530int elm_6node_wedge_initialize()531{532static char *Name = "ELM_6NODE_WEDGE";533534element_type_t ElementDef;535int elm_add_element_type();536537elm_6node_wedge_shape_functions();538539ElementDef.ElementName = Name;540ElementDef.ElementCode = 706;541542ElementDef.NumberOfNodes = 6;543544ElementDef.NodeU = NodeU;545ElementDef.NodeV = NodeV;546ElementDef.NodeW = NodeW;547548ElementDef.PartialU = (double (*)())elm_6node_wedge_dndu_fvalue;549ElementDef.PartialV = (double (*)())elm_6node_wedge_dndv_fvalue;550ElementDef.PartialW = (double (*)())elm_6node_wedge_dndw_fvalue;551552ElementDef.FunctionValue = (double (*)())elm_6node_wedge_fvalue;553ElementDef.Triangulate = (int (*)())elm_6node_wedge_triangulate;554ElementDef.PointInside = (int (*)())elm_6node_wedge_point_inside;555ElementDef.IsoLine = (int (*)())elm_6node_wedge_isoline;556ElementDef.IsoSurface = (int (*)())elm_6node_wedge_isosurface;557558return elm_add_element_type( &ElementDef ) ;559}560561562