/*
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 <math.h>
# include <stdio.h>
# 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;
}
syntax highlighted by Code2HTML, v. 0.9.1