/* This file is part of the FElt finite element analysis package. Copyright (C) 1993-2000 Jason I. Gobat and Darren C. Atkinson This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /************************************************************************ * File: rod.c * * * * Description: This file contains the definition structure and the * * stiffness and stress functions for the one-dimensional * * heat transfer (thermal analysis) element. * * The assumed element shape is a simple circular rod. * ************************************************************************/ # include # include # include "allocate.h" # include "fe.h" # include "error.h" # include "misc.h" int RodLumpedCapacityMatrix ( ); int RodConsistentCapacityMatrix ( ); int rodEltSetup ( ); int rodEltStress ( ); struct definition rodDefinition = { "rod", rodEltSetup, rodEltStress, Linear, 2, 2, 0, 1, {0, 1, 0, 0, 0, 0, 0}, 0 }; Vector RodResolveConvection ( ); int rodEltSetup (element, mass_mode, tangent) Element element; char mass_mode; int tangent; { unsigned i; Vector equiv; int count; double factor; double length; count = 0; if (element -> material -> Kx == 0) { error ("Rod element %d has 0.0 for x-conductivity (Kx)", element -> number); count ++; } if (element -> material -> A == 0) { error ("Rod element %d has 0.0 for cross-sectional area (A)", element -> number); count ++; } if (mass_mode && element -> material -> c == 0) { error ("Rod element %d has 0.0 for heat capacitance (c)", element -> number); count ++; } length = ElementLength (element, 3); if (length <= TINY) { error ("length of element %d is zero to machine precision", element -> number); count ++; } if (count) return count; factor = element -> material -> A * element -> material -> Kx / length; if (element -> K == NullMatrix) element -> K = CreateMatrix (2,2); MatrixData (element -> K) [1][1] = factor; MatrixData (element -> K) [1][2] = -factor; MatrixData (element -> K) [2][1] = -factor; MatrixData (element -> K) [2][2] = factor; if (element -> numdistributed > 0) { equiv = RodResolveConvection (element, &count); if (equiv == NullMatrix) return count; for (i = 1; i <= 2 ; i++) element -> node[i] -> eq_force[1] += VectorData (equiv) [i]; } if (mass_mode) { if (element -> M == NullMatrix) element -> M = CreateMatrix (2,2); if (mass_mode == 'l') RodLumpedCapacityMatrix (element); else if (mass_mode == 'c') RodConsistentCapacityMatrix (element); } return 0; } int rodEltStress (element) Element element; { element -> ninteg = 0; return 0; } int RodLumpedCapacityMatrix (e) Element e; { double factor; double L; L = ElementLength (e, 3); factor = e -> material -> A * e -> material -> c * e -> material -> rho * L / 2.0; MatrixData (e -> M) [1][1] = factor; MatrixData (e -> M) [2][2] = factor; MatrixData (e -> M) [1][2] = 0.0; MatrixData (e -> M) [2][1] = 0.0; return 0; } int RodConsistentCapacityMatrix (e) Element e; { double factor; double L; L = ElementLength (e, 3); factor = e -> material -> A * e -> material -> c * e -> material -> rho * L / 6.0; MatrixData (e -> M) [1][1] = 2*factor; MatrixData (e -> M) [1][2] = factor; MatrixData (e -> M) [2][1] = factor; MatrixData (e -> M) [2][2] = 2*factor; return 0; } Vector RodResolveConvection (element, err_count) Element element; int *err_count; { double length; double factor; int count; double end_area; double surface_area; double conv_coeff; double Tinf; unsigned node_a, node_b; unsigned i; static Vector equiv = NullMatrix; static Matrix convK; if (equiv == NullMatrix) { equiv = CreateVector (2); convK = CreateMatrix (2,2); } count = 0; if (element -> numdistributed > 3) { error ("rod element %d can have at most three convecting surfaces", element -> number); count++; } end_area = element -> material -> A; length = ElementLength (element, 3); surface_area = 2.0*sqrt(M_PI*end_area)*length; ZeroMatrix (convK); for (i = 1 ; i <= 2 ; i++) VectorData (equiv) [i] = 0.0; for (i = 1 ; i <= element -> numdistributed ; i++) { if (element -> distributed[i] -> nvalues != 2) { error ("convection %s does not have 2 nodal values (element %d)", element -> distributed[i] -> name, element -> number); count++; } node_a = element -> distributed[i] -> value[1].node; node_b = element -> distributed[i] -> value[2].node; if (node_a < 1 || node_a > 2 || node_b < 1 || node_b > 2) { error ("incorrect node numbering for convection %s (element %d)", element -> distributed[i] -> name,element -> number); count++; } /* * Thats all the error checking we can do right now, * bail out if we've had any */ if (count) { *err_count = count; return NullMatrix; } /* * calculate the additional "force" that we will store in the * nodes eq_force structure */ conv_coeff = element -> distributed[i] -> value[1].magnitude; Tinf = element -> distributed[i] -> value[2].magnitude; if (node_a == node_b) { factor = conv_coeff*Tinf*end_area; VectorData (equiv) [node_a] += factor; } else { factor = conv_coeff*Tinf*surface_area/2.0; VectorData (equiv) [node_a] += factor; VectorData (equiv) [node_b] += factor; } /* * calculate the contribution of this convecting edge to * the overall element stiffness matrix */ if (node_a == node_b) { factor = conv_coeff*end_area; MatrixData (convK) [node_a][node_a] += factor; } else { factor = conv_coeff*surface_area/6.0; MatrixData (convK) [1][1] += 2.0*factor; MatrixData (convK) [1][2] += factor; MatrixData (convK) [2][1] += factor; MatrixData (convK) [2][2] += 2.0*factor; } } /* * add all of the convective contributions into the * element -> K stiffness matrix */ AddMatrices (element -> K, element -> K, convK); /* * Now that we know all is okay, allocate some memory if we * haven't already done so for some other element */ SetEquivalentForceMemory (element); *err_count = 0; return equiv; }