|
The complete program text using Matrix.NET
follows the diagram. Color coding is "standard Visual Studio".
This example is #1 in the set of 3 solved by
EMOI, a program published in 1977 by John Mays, Professor of Civil and Urban
Engineering, University of Colorado at Denver. Note that the dofs are numbered
irregularly, indicating they were numbered ‘manually’.

#region
Using directives
using
System;
using System.Collections.Generic;
using System.Text;
using EngineeringObjects.LinearAlgebra;
#endregion
namespace
SampleFEProgram {
class Program
{
static
void Main(string[] args) {
// Elements
// 1: node1 to
node2
// 2: node2 to
node3
//
// Dofs: a = angular
rotation
// 1: x at node 2
// 2: y at node 2
// 3: a at node 2
// 4: a at node
3 // note anomoly; inconsistent dof numbering
// 5: x at node 3
// 6: y at node 3
// 7: x at node 1
// 8: y at node 1
// 9: a at node 1
//
// Load:
// 5 # force in -y
direction at node 2 (dof 2)
//
// Displacement:
// 0.01 in in x
direction at node 3 (dof 5)
// coordinates
Vector3D node1 =
new Vector3D(
0, 0, 0 );
Vector3D node2 =
new Vector3D(
12 * 12, 12 * 16, 0 );
Vector3D node3 =
new Vector3D(
12 * (12 + 15), 12 * 16, 0 );
node1.Print( "node1" );
node2.Print( "node2" );
node3.Print( "node3" );
Vector e1 = node2 - node1;
// Vector in direction of element 1
Vector e2 = node3 -
node2; // Vector in direction of element 2
e1.Print(
"e1" );
e2.Print( "e2" );
double
L1 = e1.Length;
double L2 = e2.Length;
// Beam properties
double I = 100;
// Moment of intertia, in^4
double A = 2;
// Area, in^2
double E = 30000;
// Young's modulus, #/in^2
Matrix K1 = FormElementK( A,
I, E, L1 );
K1.Print( "K1" );
// direction cosines for element
1
Vector u1 =
Vector.Unit( e1 );
u1.Print( "u1" );
// element rotation matrix
Lambda
Matrix Lambda =
Rotate( u1 );
Lambda.Print( "Lambda" );
Matrix KK1 =
Matrix.TransposeMultiply( Lambda, K1 * Lambda
);
//KK1.Print( "KK1" );
Matrix K2 = FormElementK( A,
I, E, L2 );
//K2.Print( "K2" );
Matrix G =
new Matrix( 9,
9 ); // global stiffness
// accumulate element 1
int[] e1d = {
// element 1 dofs
7,8,9,1,2,3
};
IntVector e1Dofs =
new IntVector(
e1d );
Accumulate( G, KK1, e1Dofs );
G.Print( "G" );
// accumulate element 2
int[] e2d = {
1,2,3,5,6,4 // <<< irregular
dof numbering
};
IntVector e2Dofs =
new IntVector(
e2d );
Accumulate( G, K2, e2Dofs );
G.Print( "G" );
// save G for later Force
recovery
Matrix H =
new Matrix( G
);
// establish right hand side
Vector rhs =
new Vector(
G.Rows );
// Assume that displacements and
loads are not specified for the same degree of freedom
// Specified displacement dofs
and values
Dictionary<int,
double> displacements = GetDisplacements();
// key: dof; value: displacement
ApplyDisplacements( G, displacements, rhs );
// Specified Loads
Dictionary<int,
double> loads = GetLoads();
// key: dof; value: load
ApplyLoads( rhs, loads );
//rhs.Print("rhs");
Vector x = Solve( G, rhs );
x.Print( "Displacements" );
// recover forces
Vector F = H * x;
F.Print( "External Forces"
);
UserPause();
}
//============================================================
private
static Dictionary<int,
double> GetLoads() {
Dictionary<int,
double> loads = new
Dictionary<int,
double>();
loads.Add( 2, -5.0 );
return loads;
}
//============================================================
private
static Dictionary<int,
double> GetDisplacements() {
Dictionary<int,
double> displacements =
new Dictionary<int,
double>();
displacements.Add( 7, 0 );
displacements.Add( 8, 0 );
displacements.Add( 9, 0 );
displacements.Add( 5, 0.01 );
displacements.Add( 6, 0 );
return displacements;
}
//============================================================
private
static Matrix
FormElementK(double A,
double I, double
E, double L) {
Matrix K =
new Matrix( 6,
6 );
double twelve = 12.0;
double six = 6.0;
double four = 4.0;
double two = 2.0;
double AEonL = A * E / L;
K[1, 1] = AEonL;
K[1, 4] = K[4, 1] = -AEonL;
K[4, 4] = AEonL;
double EIonL = E * I / L;
K[2, 2] = K[5, 5] = twelve * EIonL / (L * L);
K[5, 2] = -K[2, 2];
K[2, 5] = -K[2, 2];
K[3, 2] = K[2, 3] = K[6, 2] = K[2, 6] = six * EIonL / L;
K[6, 5] = K[5, 6] = -K[3, 2];
K[5, 3] = K[3, 5] = -K[3, 2];
K[3, 3] = K[6, 6] = four * EIonL;
K[6, 3] = K[3, 6] = two * EIonL;
return K;
}
//============================================================
private
static Matrix
Rotate(Vector u1) {
Matrix L =
new Matrix( 6,
6 );
double one = 1.0;
L[1, 1] = u1[1];
L[1, 2] = u1[2];
L[2, 1] = -u1[2];
L[2, 2] = u1[1];
L[3, 3] = one;
L[4, 4] =
u1[1];
L[4, 5] = u1[2];
L[5, 4] = -u1[2];
L[5, 5] = u1[1];
L[6, 6] = one;
return L;
}
//============================================================
private
static void
Accumulate(Matrix G,
Matrix K, IntVector edofs) {
int rg, cg;
for (int
r = 1; r <= K.Rows; ++r) {
rg = edofs[r];
for (int
c = 1; c <= K.Columns; ++c) {
cg = edofs[c];
G[rg, cg] += K[r, c];
}
}
}
//============================================================
private static
void ApplyDisplacements(Matrix
G, Dictionary<int,
double> displacements,
Vector rhs) {
foreach (KeyValuePair<int,
double> kvp in
displacements) {
ApplyADisplacement( G, rhs, kvp.Key, kvp.Value );
}
}
//============================================================
private
static void
ApplyADisplacement(Matrix G,
Vector rhs, int
eqn, double disp) {
if (disp != 0.0) {
// adjust rhs
for (int
i = 1; i <= G.Rows; ++i) {
rhs[i] -= disp * G[i, eqn];
}
rhs[eqn] = disp;
}
else {
// displacement is 0
rhs[eqn] = 0.0;
}
// adjust G
G.FillColumn( eqn, 0.0 );
G.FillRow( eqn, 0.0 );
G[eqn, eqn] = 1.0;
}
//============================================================
private
static void
ApplyLoads(Vector rhs,
Dictionary<int,
double> loads) {
foreach (KeyValuePair<int,
double> load in
loads) {
rhs[load.Key] = load.Value;
}
}
//============================================================
private
static Vector
Solve(Matrix G,
Vector rhs) {
double logdet, cond;
Matrix H =
Matrix.InvertSymmetric( G,
out logdet, out
cond );
Console.WriteLine();
Console.WriteLine(
"log(determinant): {0}", logdet );
Console.WriteLine(
"condition number: {0}", cond );
Vector res = H * rhs;
return res;
}
//==================================================
private
static void
UserPause() {
Console.WriteLine(
"\nPress 'Enter' to continue..." );
Console.ReadLine();
}
}
}
Output for this program:
log(determinant): 14.5632449149509
condition number:
150618.055555556
... Displacements ...
2.066610E-002 -4.587113E-002 -1.025382E-005 3.873863E-004
1.000000E-002
0.000000E+000 0.000000E+000 0.000000E+000 0.000000E+000
... External Forces ...
0.000000E+000 -5.000000E+000 0.000000E+000 3.552714E-015
-3.555368E+000
7.363707E-002 3.555368E+000 4.926363E+000 1.351102E+001
|