/*****************************************************************************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 16 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. +3516 0 457 272335* Telefax: +3516 0 457 230236* EMail: [email protected]37*38* Date: 20 Sep 11616539*40* Modification history:41*42* 216 Sep 116165, 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[16][16],A[16][16];5758static double NodeU[] = { -1.0, 1.0, 1.0, -1.0,59-1.0/3.0, 1.0/3.0, 1.0, 1.0,601.0/3.0, -1.0/3.0, -1.0, -1.0,61-1.0/3.0, 1.0/3.0, 1.0/3.0, -1.0/3.0 };6263static double NodeV[] = { -1.0, -1.0, 1.0, 1.0,64-1.0, -1.0, -1.0/3.0, 1.0/3.0,651.0, 1.0, 1.0/3.0, -1.0/3.0,66-1.0/3.0, -1.0/3.0, 1.0/3.0, 1.0/3.0 };6768static int map[9][4] =69{70{ 0, 4,12,11 }, { 4,5,13,12 }, { 5,1,6,13 }, { 11,12,15,10 },71{ 12,13,14,15 }, { 13,6,7,14 }, { 10,15,9,3 }, { 15,14, 8, 9 }, { 14,7,2,8 }72};737475/*******************************************************************************76*77* Name: elm_16node_quad_shape_functions( )78*79* Purpose: Initialize element shape function array. Internal only.80*81* Parameters:82*83* Input: Global (filewise) variables NodeU,NodeV,NodeW84*85* Output: Global (filewise) variable N, will contain86* shape function coefficients87*88* Return value: void89*90******************************************************************************/91static void elm_16node_quad_shape_functions()92{93double u,v;9495int i,j;9697for( i=0; i<16; i++ )98{99u = NodeU[i];100v = NodeV[i];101102A[i][0] = 1;103A[i][1] = u;104A[i][2] = u*u;105A[i][3] = u*u*u;106A[i][4] = v;107A[i][5] = u*v;108A[i][6] = u*u*v;109A[i][7] = u*u*u*v;110A[i][8] = v*v;111A[i][9] = u*v*v;112A[i][10] = u*u*v*v;113A[i][11] = u*u*u*v*v;114A[i][12] = v*v*v;115A[i][13] = u*v*v*v;116A[i][14] = u*u*v*v*v;117A[i][15] = u*u*u*v*v*v;118}119120lu_mtrinv( (double *)A,16 );121122for( i=0; i<16; i++ )123for( j=0; j<16; j++ ) N[i][j] = A[j][i];124}125126#if 0127128/*******************************************************************************129*130* Name: elm_16node_quad_triangulate( geometry_t *,element_t * )131*132* Purpose: Triangulate an element. The process also builds up an edge133* table and adds new nodes to node table. The triangulation134* and edge table is stored in geometry_t *geom-structure.135*136* Parameters:137*138* Input: (geometry_t *) pointer to structure holding triangulation139* (element_t *) element to triangulate140*141* Output: (geometry_t *) structure is modified142*143* Return value: FALSE if malloc() fails, TRUE otherwise144*145******************************************************************************/146int elm_16node_quad_triangulate( geometry_t *geom,element_t *Elm )147{148element_t quad;149int i,j,topo[4];150151quad.DisplayFlag = TRUE;152quad.Topology = topo;153for( i=0; i<MAX_GROUP_IDS; i++ ) quad.GroupIds[i] = Elm->GroupIds[i];154155for( i=0; i<9; i++ )156{157for( j=0; j<4; j++ )158{159quad.Topology[j] = Elm->Topology[map[i][j]];160}161if ( !elm_4node_quad_triangulate( geom, &quad, Elm ) ) return FALSE;162}163164return TRUE;165}166#else167168/*******************************************************************************169*170* Name: elm_16node_quad_triangulate( geometry_t *,element_t * )171*172* Purpose: Triangulate an element. The process also builds up an edge173* table and adds new nodes to node table. The triangulation174* and edge table is stored in geometry_t *geom-structure.175*176* Parameters:177*178* Input: (geometry_t *) pointer to structure holding triangulation179* (element_t *) element to triangulate180*181* Output: (geometry_t *) structure is modified182*183* Return value: FALSE if malloc() fails, TRUE otherwise184*185******************************************************************************/186int elm_16node_quad_triangulate( geometry_t *geom,element_t *Elm )187{188static int map[18][3] =189{190{ 0,12,11 }, { 0, 4,12 }, { 4,13,12 },191{ 4, 5,13 }, { 5, 1,13 }, { 1, 6,13 },192{ 13, 6,14 }, { 6, 7,14 }, { 7, 2,14 },193{ 14, 2, 8 }, { 14, 8, 9 }, { 14, 9,15 },194{ 15, 9,10 }, { 9, 3,10 }, { 12,15,10 },195{ 12,10,11 }, { 12,13,14 }, { 12,14,15 }196};197static int edge_map[18][3] =198{199{ 0, 0, 1 }, { 1, 0, 0 }, { 0, 0, 0 },200{ 1, 0, 0 }, { 1, 0, 0 }, { 1, 0, 0 },201{ 0, 0, 0 }, { 1, 0, 0 }, { 1, 0, 0 },202{ 0, 1, 0 }, { 0, 1, 0 }, { 0, 0, 0 },203{ 0, 0, 0 }, { 1, 1, 0 }, { 0, 0, 0 },204{ 0, 1, 0 }, { 0, 0, 0 }, { 0, 0, 0 }205};206207int i,j;208209triangle_t triangle;210211triangle.Element = Elm;212213for( i=0; i<18; i++ )214{215triangle.v[0] = Elm->Topology[map[i][0]];216triangle.v[1] = Elm->Topology[map[i][1]];217triangle.v[2] = Elm->Topology[map[i][2]];218219triangle.Edge[0] = edge_map[i][0];220triangle.Edge[1] = edge_map[i][1];221triangle.Edge[2] = edge_map[i][2];222223if ( !geo_add_triangle( geom,&triangle ) ) return FALSE;224}225226return TRUE;227}228#endif229230231/*******************************************************************************232*233* Name: elm_16node_quad_fvalue( double *,double,double )234*235* Purpose: return value of a quantity given on nodes at point (u,v)236*237*238*239* Parameters:240*241* Input: (double *) quantity values at nodes242* (double u,double v) point where values are evaluated243*244* Output: none245*246* Return value: quantity value247*248******************************************************************************/249static double elm_16node_quad_fvalue( double *F, double u, double v )250{251double R,q,p,s,t;252int i,j,k,n;253254R = 0.0;255for( i=0; i<16; i++ )256{257n = 0;258q = 0.0;259s = 1.0;260for( j=0; j<4; j++ )261{262p = 0.0;263t = 1.0;264for( k=0; k<4; k++, n++ ) { p += N[i][n]*t; t *= u; }265q += p * s;266s *= v;267}268R += F[i] * q;269}270271return R;272}273274/*******************************************************************************275*276* Name: elm_16node_quad_dndu_fvalue( double *,double,double )277*278* Purpose: return value of a first partial derivate in (u) of a279* quantity given on nodes at point (u,v)280*281*282* Parameters:283*284* Input: (double *) quantity values at nodes285* (double u,double v) point where values are evaluated286*287* Output: none288*289* Return value: quantity value290*291******************************************************************************/292static double elm_16node_quad_dndu_fvalue( double *F, double u, double v )293{294double R,q,p,s,t;295int i,j,k,n;296297R = 0.0;298for( i=0; i<16; i++ )299{300n = 0;301q = 0.0;302s = 1.0;303for( j=1; j<4; j++ )304{305p = 0.0;306t = 1.0;307for( k=0; k<4; k++, n++ ) { p += N[i][4*k+j]*t; t *= v; }308q += p * s;309s *= u;310}311R += F[i] * q;312}313314return R;315}316317/*******************************************************************************318*319* Name: elm_16node_quad_dndv_fvalue( double *,double,double )320*321* Purpose: return value of a first partial derivate in (v) of a322* quantity given on nodes at point (u,v)323*324*325* Parameters:326*327* Input: (double *) quantity values at nodes328* (double u,double v) point where values are evaluated329*330* Output: none331*332* Return value: quantity value333*334******************************************************************************/335static double elm_16node_quad_dndv_fvalue( double *F, double u, double v )336{337double R,q,p,s,t;338int i,j,k,n;339340R = 0.0;341for( i=0; i<16; i++ )342{343n = 0;344q = 0.0;345s = 1.0;346for( j=1; j<4; j++ )347{348p = 0.0;349t = 1.0;350for( k=0; k<4; k++, n++ ) { p += N[i][n]*t; t *= u; }351q += p * s;352s *= v;353}354R += F[i] * q;355}356357return R;358}359360/*******************************************************************************361*362* Name: elm_16node_quad_dd(double *F,double *u,double *v,double *Values)363*364* Purpose: Return matrix of second partial derivates of given quantity365* at given point u,v.366*367* Parameters:368*369* Input: (double *)F: quantity values at nodes370* (double)u,v: point of evaluation371*372* Output: (double *)Values: 2x2 matrix of partial derivates373*374* Return value: void375*376*******************************************************************************/377static void elm_16node_quad_ddu( double *F,double u,double v,double *Values )378{379double ddu = 0.0, dudv=0.0, ddv = 0.0;380double q,p,s,t;381int i,j,k,n;382383ddu = 0.0;384for( i=0; i<16; i++ )385{386n = 0;387q = 0.0;388s = 1.0;389for( j=2; j<4; j++ )390{391p = 0.0;392t = 1.0;393for( k=0; k<4; k++, n++ ) { p += N[i][4*k+j]*t; t *= v; }394q += p * s;395s *= u;396}397ddu += F[i] * q;398}399400ddv = 0.0;401for( i=0; i<16; i++ )402{403n = 0;404q = 0.0;405s = 1.0;406for( j=2; j<4; j++ )407{408p = 0.0;409t = 1.0;410for( k=0; k<4; k++, n++ ) { p += N[i][n]*t; t *= u; }411q += p * s;412s *= v;413}414ddv += F[i] * q;415}416417dudv = 0.0;418for( i=0; i<16; i++ )419{420n = 0;421q = 0.0;422s = 1.0;423for( j=1; j<4; j++ )424{425p = 0.0;426t = 1.0;427for( k=1; k<4; k++, n++ ) { p += N[i][n]*t; t *= u; }428q += p * s;429s *= v;430}431dudv += F[i] * q;432}433434Values[0] = ddu;435Values[1] = dudv;436Values[2] = dudv;437Values[3] = ddv;438}439440/*******************************************************************************441*442* Name: elm_16node_quad_point_inside(443* double *nx,double *ny,double *nz,444* double px, double py, double pz,445* double *u,double *v,double *w )446*447* Purpose: Find if point (px,py,pz) is inside the element, and return448* element coordinates of the point.449*450* Parameters:451*452* Input: (double *) nx,ny,nz n coordinates453* (double) px,py,pz point to consider454*455* Output: (double *) u,v,w point in element coordinates if inside456*457* Return value: in/out status458*459* NOTES: the goal here can be hard for more involved element types. kind of460* trivial for this one... TODO: FIX THIS....461*462******************************************************************************/463int elm_16node_quad_point_inside464(465double *nx, double *ny, double *nz,466double px, double py, double pz, double *u,double *v,double *w467)468{469double x[4],y[4],z[4],uu,vv,ww;470int i, j, k;471int elm_4node_quad_point_inside();472473for( i=0; i<9; i++ )474{475for( j=0; j<4; j++ )476{477k = map[i][j];478x[j] = nx[k];479y[j] = ny[k];480z[j] = nz[k];481}482483if ( elm_4node_quad_point_inside( x,y,z,px,py,pz,&uu,&vv,&ww ) )484{485k = map[i][0];486*u = 2*(uu/2+0.5)/3 + NodeU[k];487*v = 2*(vv/2+0.5)/3 + NodeV[k];488489return TRUE;490}491}492return FALSE;493}494495/*******************************************************************************496*497* Name: elm_16node_quad_isoline498*499* Purpose: Extract a iso line from triangle with given threshold500*501* Parameters:502*503* Input: (double) K, contour threshold504* (double *) F, contour quantity505* (double *) C, color quantity506* (double *) X,Y,Z vertex coords.507*508* Output: (line_t *) place to store the line509*510* Return value: number of lines generated (0,...,16)511*512******************************************************************************/513int elm_16node_quad_isoline514(515double K, double *F, double *C,double *X,double *Y,double *Z,line_t *Line516)517{518double f[4],c[4],x[4],y[4],z[4];519520int i, j, k, n=0, above=0;521int elm_4node_quad_isoline();522523for( i=0; i<16; i++ ) above += F[i]>K;524if ( above == 0 || above == 16 ) return 0;525526for( i=0; i<9; i++ )527{528for( j=0; j<4; j++ )529{530k = map[i][j];531f[j] = F[k];532c[j] = C[k];533x[j] = X[k];534y[j] = Y[k];535z[j] = Z[k];536}537n += elm_4node_quad_isoline( K,f,c,x,y,z,&Line[n] );538}539540return n;541}542543544/******************************************************************************545*546* Name: elm_16node_quad_initialize( )547*548* Purpose: Register the element type549*550* Parameters:551*552* Input: (char *) description of the element553* (int) numeric code for the element554*555* Output: Global list of element types is modified556*557* Return value: malloc() success558*559******************************************************************************/560int elm_16node_quad_initialize()561{562element_type_t ElementDef;563564static char *Name = "ELM_16NODE_QUAD";565int elm_add_element_type();566567elm_16node_quad_shape_functions();568569ElementDef.ElementName = Name;570ElementDef.ElementCode = 416;571572ElementDef.NumberOfNodes = 16;573ElementDef.NodeU = NodeU;574ElementDef.NodeV = NodeV;575ElementDef.NodeW = NULL;576577ElementDef.PartialU = (double (*)())elm_16node_quad_dndu_fvalue;578ElementDef.PartialV = (double (*)())elm_16node_quad_dndv_fvalue;579ElementDef.PartialW = NULL;580ElementDef.SecondPartials = (double (*)())elm_16node_quad_ddu;581582ElementDef.FunctionValue = (double (*)())elm_16node_quad_fvalue;583584ElementDef.Triangulate = (int (*)())elm_16node_quad_triangulate;585ElementDef.PointInside = (int (*)())elm_16node_quad_point_inside;586ElementDef.IsoLine = (int (*)())elm_16node_quad_isoline;587ElementDef.IsoSurface = (int (*)())NULL;588589return elm_add_element_type( &ElementDef );590}591592593