/*****************************************************************************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 pyramid 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* Five node pyramid volume element.47*48*/4950static double A[5][5],N[5][5];5152static double NodeU[] = { -1.0, 1.0, 1.0, -1.0, 0.0 };53static double NodeV[] = { -1.0,-1.0, 1.0, 1.0, 0.0 };54static double NodeW[] = { 0.0, 0.0, 0.0, 0.0, 1.0};5556/*******************************************************************************57*58* Name: elm_5node_pyramid_triangulate59*60* Purpose: Triangulate an element. The process also builds up an edge61* table and adds new nodes to node table. The triangulation62* and edge table is stored in geometry_t *geom-structure.63*64* Parameters:65*66* Input: (geometry_t *) pointer to structure holding triangulation67* (element_t *) element to triangulate68*69* Output: (geometry_t *) structure is modified70*71* Return value: FALSE if malloc() fails, TRUE otherwise72*73******************************************************************************/74static int elm_5node_pyramid_triangulate( geometry_t *geom,element_t *pyramid )75{76element_t element;77int i,j;7879int PyramidFace[5][4] = { { 0,1,2,3 }, { 0,1,4,0 }, { 1,2,4,0 }, { 2,3,4,0 }, { 3,0,4,0 } };8081int elm_4node_quad_triangulate();82int geo_add_edge();83int elm_3node_triangle_triangulate();8485if ( GlobalOptions.VolumeSides )86{87int topo[4];8889element.DisplayFlag = TRUE;90element.Topology = topo;91for( i=0; i<MAX_GROUP_IDS; i++ ) element.GroupIds[i] = pyramid->GroupIds[i];9293for( j=0; j<4; j++ )94{95element.Topology[j] = pyramid->Topology[PyramidFace[0][j]];96}97if ( !elm_4node_quad_triangulate( geom, &element, pyramid ) ) return FALSE;9899for( i=1; i<5; i++ )100{101for( j=0; j<3; j++ )102{103element.Topology[j] = pyramid->Topology[PyramidFace[i][j]];104}105}106if ( !elm_3node_triangle_triangulate( geom, &element, pyramid ) ) return FALSE;107} else {108if ( !geo_add_edge( geom, pyramid->Topology[0], pyramid->Topology[1],pyramid ) ) return FALSE;109if ( !geo_add_edge( geom, pyramid->Topology[1], pyramid->Topology[2],pyramid ) ) return FALSE;110if ( !geo_add_edge( geom, pyramid->Topology[2], pyramid->Topology[3],pyramid ) ) return FALSE;111if ( !geo_add_edge( geom, pyramid->Topology[3], pyramid->Topology[0],pyramid ) ) return FALSE;112if ( !geo_add_edge( geom, pyramid->Topology[0], pyramid->Topology[4],pyramid ) ) return FALSE;113if ( !geo_add_edge( geom, pyramid->Topology[1], pyramid->Topology[4],pyramid ) ) return FALSE;114if ( !geo_add_edge( geom, pyramid->Topology[2], pyramid->Topology[4],pyramid ) ) return FALSE;115if ( !geo_add_edge( geom, pyramid->Topology[3], pyramid->Topology[4],pyramid ) ) return FALSE;116}117118return TRUE;119}120121/*******************************************************************************122*123* Name: elm_5node_pyramid_shape_functions124*125* Purpose: Initialize element shape function array. Internal only.126*127* Parameters:128*129* Input: Global (filewise) variables NodeU,NodeV,NodeW130*131* Output: Global (filewise) variable N[6][6], will contain132* shape function coefficients133*134* Return value: void135* Return value: void136*137******************************************************************************/138static void elm_5node_pyramid_shape_functions()139{140double u,v,w;141int i,j;142143#if 0144for( i=0; i<5; i++ )145{146u = NodeU[i];147v = NodeV[i];148w = NodeW[i];149150A[i][0] = 1;151A[i][1] = u;152A[i][2] = v;153A[i][3] = w;154A[i][4] = u*v;155}156157lu_mtrinv( (double *)A,5 );158159for( i=0; i<5; i++ )160for( j=0; j<5; j++ ) N[i][j] = A[j][i];161#endif162}163164/*******************************************************************************165*166* Name: elm_5node_pyramid_fvalue167*168* Purpose: return value of a quantity given on nodes at point (u,v)169* Use trough (element_type_t *) structure.170*171* Parameters:172*173* Input: (double *) quantity values at nodes174* (double u,double v) point where values are evaluated175*176* Output: none177*178* Return value: quantity value179*180******************************************************************************/181static double elm_5node_pyramid_fvalue(double *F,double u,double v,double w)182{183double R=0.0, s;184int i;185186if ( w == 1 ) w = 1-1.0e-12;187s = 1.0 / (1-w);188189R = R + F[0] * ( (1-u) * (1-v) - w + u*v*w * s ) / 4;190R = R + F[1] * ( (1+u) * (1-v) - w - u*v*w * s ) / 4;191R = R + F[2] * ( (1+u) * (1+v) - w + u*v*w * s ) / 4;192R = R + F[3] * ( (1-u) * (1+v) - w - u*v*w * s ) / 4;193R = R + F[4] * w;194195return R;196}197198/*******************************************************************************199*200* Name: elm_5node_pyramid_dndu_fvalue201*202* Purpose: return value of a first partial derivate in (v) of a203* quantity given on nodes at point (u,v).204* Use trough (element_type_t *) structure.205*206*207* Parameters:208*209* Input: (double *) quantity values at nodes210* (double u,double v,double w) point where values are evaluated211*212* Output: none213*214* Return value: quantity value215*216******************************************************************************/217static double elm_5node_pyramid_dndu_fvalue(double *F,double u,double v,double w)218{219double R=0.0,s;220int i;221222if ( w == 1 ) w = 1-1.0e-12;223s = 1.0 / (1-w);224225R = R + F[0] * ( -(1-v) + v*w * s ) / 4;226R = R + F[1] * ( (1-v) - v*w * s ) / 4;227R = R + F[2] * ( (1+v) + v*w * s ) / 4;228R = R + F[3] * ( -(1+v) - v*w * s ) / 4;229230return R;231}232233/*******************************************************************************234*235* Name: elm_5node_pyramid_dndv_fvalue236*237* Purpose: return value of a first partial derivate in (v) of a238* quantity given on nodes at point (u,v,w).239* Use trough (element_type_t *) structure.240*241*242* Parameters:243*244* Input: (double *) quantity values at nodes245* (double u,double v,double w) point where values are evaluated246*247* Output: none248*249* Return value: quantity value250*251******************************************************************************/252static double elm_5node_pyramid_dndv_fvalue(double *F,double u,double v,double w)253{254double R=0.0,s;255int i;256257if ( w == 1 ) w = 1-1.0e-12;258s = 1.0 / (1-w);259260R = R + F[0] * ( -(1-u) + u*w * s ) / 4;261R = R + F[1] * ( -(1+u) - u*w * s ) / 4;262R = R + F[2] * ( (1+u) + u*w * s ) / 4;263R = R + F[3] * ( (1-u) - u*w * s ) / 4;264265return R;266}267268/*******************************************************************************269*270* Name: elm_5node_pyramid_dndw_fvalue271*272* Purpose: return value of a first partial derivate in (w) of a273* quantity given on nodes at point (u,v,w)274* Use trough (element_type_t *) structure.275*276*277* Parameters:278*279* Input: (double *) quantity values at nodes280* (double u,double v,double w) point where values are evaluated281*282* Output: none283*284* Return value: quantity value285*286******************************************************************************/287static double elm_5node_pyramid_dndw_fvalue(double *F,double u,double v,double w)288{289double R=0.0,s;290int i;291292if ( w == 1 ) w = 1.0-1.0e-12;293s = 1.0 / (1-w);294295R = R + F[0] * ( -1 + u*v*(2-w) * s*s ) / 4;296R = R + F[1] * ( -1 - u*v*(2-w) * s*s ) / 4;297R = R + F[2] * ( -1 + u*v*(2-w) * s*s ) / 4;298R = R + F[3] * ( -1 - u*v*(2-w) * s*s ) / 4;299R = R + F[4];300301return R;302}303304/******************************************************************************305*306* Name: elm_5node_pyramid_initialize307*308* Purpose: Register the element type309*310* Parameters:311*312* Input: (char *) description of the element313* (int) numeric code for the element314*315* Output: Global list of element types is modified316*317* Return value: malloc() success318*319******************************************************************************/320int elm_5node_pyramid_initialize()321{322static char *Name = "ELM_5NODE_PYRAMID";323324element_type_t ElementDef;325int elm_add_element_type();326327elm_5node_pyramid_shape_functions();328329ElementDef.ElementName = Name;330ElementDef.ElementCode = 605;331332ElementDef.NumberOfNodes = 5;333334ElementDef.NodeU = NodeU;335ElementDef.NodeV = NodeV;336ElementDef.NodeW = NodeW;337338ElementDef.PartialU = (double (*)())elm_5node_pyramid_dndu_fvalue;339ElementDef.PartialV = (double (*)())elm_5node_pyramid_dndv_fvalue;340ElementDef.PartialW = (double (*)())elm_5node_pyramid_dndw_fvalue;341342ElementDef.FunctionValue = (double (*)())elm_5node_pyramid_fvalue;343ElementDef.Triangulate = (int (*)())elm_5node_pyramid_triangulate;344ElementDef.PointInside = (int (*)())NULL;345346return elm_add_element_type( &ElementDef );347}348349350