第三节 构造有限元法基本方程
3.1 形成未引入边界的总刚度矩阵、总荷载列阵、总边界列阵
新建类,命名为 ClassCalculation,贴入以下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Business
{
public class ClassCalculation
{
public Single[,] K = new Single[4, 4];//存放临时单元刚度矩阵
public Single[,] XY;//杆件(起点、终点)节点的坐标 x、y
public int rowsBars = ClassBasicInfo.BarsNodes.GetLength(0);//杆件数
public int rowsNodes = ClassBasicInfo.Coordinate.GetLength(0);//节点数
//构造函数取得各杆件x1,x2,y1,y2
public ClassCalculation()
{
XY = new Single[rowsBars, 4];
for (int i = 0; i < rowsBars; i++)
{
XY[i, 0] = ClassBasicInfo.Coordinate[ClassBasicInfo.BarsNodes[i, 0] - 1, 0];//起点x
XY[i, 1] = ClassBasicInfo.Coordinate[ClassBasicInfo.BarsNodes[i, 0] - 1, 1];//起点y
XY[i, 2] = ClassBasicInfo.Coordinate[ClassBasicInfo.BarsNodes[i, 1] - 1, 0];//终点x
XY[i, 3] = ClassBasicInfo.Coordinate[ClassBasicInfo.BarsNodes[i, 1] - 1, 1];//终点y
}
}
[DllImport("FORTRANCAL/MatrixCal.dll")]
public static extern void UnitStiffnessMatrix(ref Single EA, ref Single x1, ref Single x2, ref Single y1, ref Single y2, ref Single K);
//取得整体坐标下的单元刚度矩阵
public Single[,] GetK(int i)
{
UnitStiffnessMatrix(ref ClassBasicInfo.LinearStiffness[i], ref XY[i, 0], ref XY[i, 2], ref XY[i, 1], ref XY[i, 3], ref K[0,0]);
return K;
}
//取得总刚度矩阵
public void GetTatalStiffnessMatrix()
{
Single[,] K;
for (int i = 0; i < rowsBars; i++)
{
int A = ClassBasicInfo.BarsNodes[i, 0];//起点编号
int B = ClassBasicInfo.BarsNodes[i, 1];//终点编号
K = this.GetK(i);//取得单元刚度矩阵
//分块进行赋值
//左上块
ClassBasicInfo.TatalStiffnessMatrix[2 * A - 2, 2 * A - 2] += K[0, 0];
ClassBasicInfo.TatalStiffnessMatrix[2 * A - 2, 2 * A - 1] += K[0, 1];
ClassBasicInfo.TatalStiffnessMatrix[2 * A - 1, 2 * A - 2] += K[1, 0];
ClassBasicInfo.TatalStiffnessMatrix[2 * A - 1, 2 * A - 1] += K[1, 1];
//右上块
ClassBasicInfo.TatalStiffnessMatrix[2 * A - 2, 2 * B - 2] += K[0, 2];
ClassBasicInfo.TatalStiffnessMatrix[2 * A - 2, 2 * B - 1] += K[0, 3];
ClassBasicInfo.TatalStiffnessMatrix[2 * A - 1, 2 * B - 2] += K[1, 2];
ClassBasicInfo.TatalStiffnessMatrix[2 * A - 1, 2 * B - 1] += K[1, 3];
//左下块
ClassBasicInfo.TatalStiffnessMatrix[2 * B - 2, 2 * A - 2] += K[2, 0];
ClassBasicInfo.TatalStiffnessMatrix[2 * B - 2, 2 * A - 1] += K[2, 1];
ClassBasicInfo.TatalStiffnessMatrix[2 * B - 1, 2 * A - 2] += K[3, 0];
ClassBasicInfo.TatalStiffnessMatrix[2 * B - 1, 2 * A - 1] += K[3, 1];
//右下块
ClassBasicInfo.TatalStiffnessMatrix[2 * B - 2, 2 * B - 2] += K[2, 2];
ClassBasicInfo.TatalStiffnessMatrix[2 * B - 2, 2 * B - 1] += K[2, 3];
ClassBasicInfo.TatalStiffnessMatrix[2 * B - 1, 2 * B - 2] += K[3, 2];
ClassBasicInfo.TatalStiffnessMatrix[2 * B - 1, 2 * B - 1] += K[3, 3];
}
}
//取得总荷载列阵(未知支座反力以0代替)
public void GetTatalLoads()
{
for (int i = 0; i < rowsNodes; i++)
{
ClassBasicInfo.TatalLoads[2 * i] = ClassBasicInfo.Loads[i, 0];
ClassBasicInfo.TatalLoads[2 * i + 1] = ClassBasicInfo.Loads[i, 1];
}
}
//取得总边界条件
public void GetTatalRestraint()
{
for (int i = 0; i < rowsNodes; i++)
{
ClassBasicInfo.TatalRestraint[2 * i] = ClassBasicInfo.Restraint[i, 0];
ClassBasicInfo.TatalRestraint[2 * i + 1] = ClassBasicInfo.Restraint[i, 1];
}
}
//接口
public void GetAll()
{
this.GetTatalStiffnessMatrix();
this.GetTatalLoads();
this.GetTatalRestraint();
}
}
}
取得总体坐标下单元刚度矩阵函数中所用 Fortran 程序为:
subroutine UnitStiffnessMatrix(EA,x1,x2,y1,y2,K)
implicit none
!dec$ attributes dllexport::UnitStiffnessMatrix
!dec$ attributes alias:"UnitStiffnessMatrix"::UnitStiffnessMatrix
!dec$ attributes reference::EA,x1,x2,y1,y2,K
real(4)::K(4,4)
real(4)::EA,x1,x2,y1,y2
real(4)::L
real(4)::I
real(4)::cosa,sina
L = ((x1-x2)**2 + (y1-y2)**2)**0.5
I = EA/L
cosa = (x2-x1)/L
sina = (y2-y1)/L
call InitK(K,I,cosa,sina)
end subroutine
subroutine InitK(K,I,cos,sin)
implicit none
real(4)::K(4,4)
real(4)::I
real(4)::cos,sin
K(1,1) = I * (cos**2)
K(1,2) = I * (cos*sin)
K(1,3) = -1.0 * K(1,1)
K(1,4) = -1.0 * K(1,2)
K(2,2) = I * (sin**2)
K(2,3) = K(1,4)
K(2,4) = -1.0 * K(2,2)
K(3,3) = K(1,1)
K(3,4) = K(1,2)
K(4,4) = K(2,2)
K(2,1) = K(1,2)
K(3,1) = K(1,3)
K(3,2) = K(2,3)
K(4,1) = K(1,4)
K(4,2) = K(2,4)
K(4,3) = K(3,4)
end subroutine
至此,总刚度矩阵、总荷载列阵、总边界列阵已存入静态数组中。
3.2 引入边界条件,求解方程,得到各节点位移、力
新建类,命名为 ClassBoundaryIn,贴入以下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Business
{
public class ClassBoundaryIn
{
public Single[,] A;
public Single[] x;
public Single[] b;
int n = ClassBasicInfo.TatalLoads.GetLength(0);
int num = 0;
public void Init()
{
for (int i = 0; i < n; i++)
{
if (ClassBasicInfo.TatalRestraint[i] == false)//自由端
{
num = num + 1;
}
}
A = new Single[num, num];
x = new Single[num];
b = new Single[num];
}
//整合总刚度矩阵,引入边界条件
public Single[,] GetA()
{
int j = 0;
for (int i = 0; i < n; i++)
{
if (ClassBasicInfo.TatalRestraint[i] == false)//自由端
{
int m = j;
for (int k = i; k < n; k++)
{
if (ClassBasicInfo.TatalRestraint[k] == false)
{
A[j, m] = ClassBasicInfo.TatalStiffnessMatrix[i, k];
A[m, j] = ClassBasicInfo.TatalStiffnessMatrix[k, i];
m = m + 1;
}
}
j = j + 1;
}
}
return A;
}
//整合总荷载列阵
public Single[] Getb()
{
int j = 0;
for (int i = 0; i < n; i++)
{
if (ClassBasicInfo.TatalRestraint[i] == false)//自由端
{
b[j] = ClassBasicInfo.TatalLoads[i];
j = j + 1;
}
}
return b;
}
//取得位移列阵
[DllImport("FORTRANCAL/MatrixCal.dll")]
public static extern void MatrixNi(ref Single A, ref int n);
public Single[,] GetA_()
{
MatrixNi(ref A[0, 0], ref num);
return A;
}
[DllImport("FORTRANCAL/MatrixCal.dll")]
public static extern void MatrixJie(ref Single A_, ref int n, ref Single b, ref Single x);
public Single[] Getx()
{
MatrixJie(ref this.GetA_()[0, 0], ref num, ref b[0], ref x[0]);
return x;
}
//形成完整总位移列阵
public void GetTatalDisplacement()
{
int j = 0;
for (int i = 0; i < n; i++)
{
if (ClassBasicInfo.TatalRestraint[i] == false)
{
ClassBasicInfo.TatalDisplacement[i] = x[j];
j = j + 1;
}
else
{
ClassBasicInfo.TatalDisplacement[i] = 0;
}
}
}
//形成完整总荷载列阵(包括未知反力)
[DllImport("FORTRANCAL/MatrixCal.dll")]
public static extern void MatrixChen(ref Single A, ref int n, ref Single b, ref Single x);
public void GetTatalLoads()
{
MatrixChen(ref ClassBasicInfo.TatalStiffnessMatrix[0, 0], ref n, ref ClassBasicInfo.TatalLoads[0], ref ClassBasicInfo.TatalDisplacement[0]);
}
//接口
public void GetAll()
{
this.Init();
this.GetA();
this.Getb();
this.Getx();
this.GetTatalDisplacement();
this.GetTatalLoads();
}
}
}
三个 Fortran 子例程分别为:
subroutine MatrixNi(a,num)
implicit none
!dec$ attributes dllexport::MatrixNi
!dec$ attributes alias:"MatrixNi"::MatrixNi
!dec$ attributes reference::a,num
integer::num
real(4)::a(num,num)
integer::i,j,k
integer::n
n = num
do k=1,N
a(k,k) = 1.d0/a(k,k)
do j=1,N
if(j/=k) a(j,k) = a(k,k)*a(j,k)
end do
do i=1,N
do j=1,N
if(i/=k.and.j/=k) a(j,i) = a(j,i) - a(k,i)*a(j,k)
end do
if(i/=k) a(k,i) = -a(k,i)*a(k,k)
end do
end do
end subroutine
subroutine MatrixJie(a,num,b,x)
implicit none
!dec$ attributes dllexport::MatrixJie
!dec$ attributes alias:"MatrixJie"::MatrixJie
!dec$ attributes reference::a,num,b,x
integer::num
real(4)::a(num,num)
real(4)::b(num)
real(4)::x(num)
integer::n,i,j
n = num
do i = 1,N
do j = 1,N
x(i) = x(i) + a(j,i) * b(j)
end do
end do
end subroutine
subroutine MatrixChen(a,num,b,x)
implicit none
!dec$ attributes dllexport::MatrixChen
!dec$ attributes alias:"MatrixChen"::MatrixChen
!dec$ attributes reference::a,num,b,x
integer::num
real(4)::a(num,num)
real(4)::b(num)
real(4)::x(num)
integer::n,i,j
n = num
b(:) = 0
do i = 1,n
do j = 1,n
b(i) = b(i) + a(i,j) * x(j)
end do
end do
end subroutine
至此,程序已基本完成。