有限元编程作业——c语言三角形常应变单元计算程序

该文章展示了一个C语言编写的程序,用于计算具有给定弹性模量、泊松比、节点坐标、荷载和边界条件的三角形单元的应变和应力。程序通过构建几何矩阵、应力弹性矩阵和单元刚度矩阵,实现了与有限元软件相当的计算结果。
摘要由CSDN通过智能技术生成

计算案例:

 

其中弹性模量设置为1,泊松比设置为0.2

节点坐标:1(3,0)2(1.5,0)3(0,0)4(3,-0.4)5(1.5,-0.4)6(0,-0.4)

等效节点荷载:1(0,-1),其他节点为0

边界条件:节点3,4的位移为0

C语言计算结果窗口:

 

 

 根据窗口提示输入初始条件,程序可实现任意节点数三角形单元计算,与有限元软件计算结果一致,下附C语言程序代码:

#include <stdio.h>
#include <Windows.h>
#include <math.h>
#include <stdlib.h>
#pragma warning(disable:4996)

void print1(double **arr, int row, int col){  //输出矩阵

	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			printf("%6.2f", arr[i][j]);
		}
		printf("\n");
	} }

double **str (double x[3][2],int t,int E,double u,double*U,int m){
double x1, y1;
x1=x[0][0],y1=x[0][1];
double x2, y2;
x2=x[1][0],y2=x[1][1];
double x3, y3;
x3=x[2][0],y3=x[2][1];

 
double a1 = x2*y3 - x3*y2;
double a2 = x3*y1 - x1*y3;
double a3 = x1*y2 - x2*y1;
 
double b1 = y2 - y3;
double b2 = y3 - y1;
double b3 = y1 - y2;
 
double c1 = x3 - x2;
double c2 = x1 - x3;
double c3 = x2 - x1;
 
//算出该三角形的边长length1、2、3;
double length1 = sqrt((double)(x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
double length2 = sqrt((double)(x2 - x3)*(x2 - x3) + (y2 - y3)*(y2 - y3));
double length3 = sqrt((double)(x1 - x3)*(x1 - x3) + (y1 - y3)*(y1 - y3));
//算出该三角形的周长per
double per = (length1 + length2 + length3) / 2;
//算出该三角形的面积area;
double area = sqrt(per*(per - length1)*(per - length2)*(per - length3));
 
//建立几何矩阵(用二维数组实现)
double B[3][6];
memset(B, 0.0, sizeof(B));
//二维数组初始化
double cd = 1 / (2 * area);
//根据课本中的3-9公式
//第一行
B[0][0] = b1*cd;
B[0][2] = b2*cd;
B[0][4] = b3*cd;
//第二行
B[1][1] = c1*cd;
B[1][3] = c2*cd;
B[1][5] = c3*cd;
//第三行
B[2][0] = c1*cd;
B[2][1] = b1*cd;
B[2][2] = c2*cd;
B[2][3] = b2*cd;
B[2][4] = c3*cd;
B[2][5] = b3*cd;
//完成几何矩阵的创建;
 
//由于u=0,平面应力与平面问题的D相同;
//计算应力弹性矩阵
double D[3][3] = { { 1.0, u, 0.0 }, \
{u, 1.0, 0.0}, \
{0.0, 0.0, (1 - u) / 2}
};
for (int i = 0; i < (sizeof(D) / sizeof(D[0])); i++){
D[0][i] *= (E / (1 - u*u));
D[1][i] *= (E / (1 - u*u));
D[2][i] *= (E / (1 - u*u));
}//求得最终的应力弹性矩阵;
 
//计算应力转换矩阵
double S[3][6];
//数组初始化;
memset(S, 0.0, sizeof(S));
 
//S=D*B;
for (int j = 0; j < (sizeof(D) / sizeof(D[0])); j++){
for (int i = 0; i < (sizeof(D) / sizeof(D[0])); i++){
S[j][0] += D[j][i] * B[i][0];
S[j][1] += D[j][i] * B[i][1];
S[j][2] += D[j][i] * B[i][2];
S[j][3] += D[j][i] * B[i][3];
S[j][4] += D[j][i] * B[i][4];
S[j][5] += D[j][i] * B[i][5];
}
}
double strain[3];
memset(strain, 0.0, sizeof(strain));
for (int j = 0; j <3; j++){
for (int i = 0; i < 6; i++){
strain[j] +=B[j][i]*U[i];
}
}
double stress[3];
memset(stress, 0.0, sizeof(stress));
for (int j = 0; j <3; j++){
for (int i = 0; i < 6; i++){
stress[j] +=S[j][i]*U[i];
}
}printf("第%d个单元应变:\n",m);
	for (int j = 0; j < 3; j++)
		printf("%6.2f", strain[j]);
		printf("\n");
printf("第%d个单元应力:\n",m);
	for (int j = 0; j < 3; j++)
		printf("%6.2f", stress[j]);
		printf("\n");
return 0;}


double **gd (double x[3][2],int t,int E,double u){
double x1, y1;
x1=x[0][0],y1=x[0][1];
double x2, y2;
x2=x[1][0],y2=x[1][1];
double x3, y3;
x3=x[2][0],y3=x[2][1];

 
double a1 = x2*y3 - x3*y2;
double a2 = x3*y1 - x1*y3;
double a3 = x1*y2 - x2*y1;
 
double b1 = y2 - y3;
double b2 = y3 - y1;
double b3 = y1 - y2;
 
double c1 = x3 - x2;
double c2 = x1 - x3;
double c3 = x2 - x1;
 
//算出该三角形的边长length1、2、3;
double length1 = sqrt((double)(x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
double length2 = sqrt((double)(x2 - x3)*(x2 - x3) + (y2 - y3)*(y2 - y3));
double length3 = sqrt((double)(x1 - x3)*(x1 - x3) + (y1 - y3)*(y1 - y3));
//算出该三角形的半周长per
double per = (length1 + length2 + length3) / 2;
//算出该三角形的面积area;
double area = sqrt(per*(per - length1)*(per - length2)*(per - length3));
 
//建立几何矩阵(用二维数组实现)
double B[3][6];
memset(B, 0.0, sizeof(B));
//二维数组初始化
double cd = 1 / (2 * area);
//根据课本中的3-9公式
//第一行
B[0][0] = b1*cd;
B[0][2] = b2*cd;
B[0][4] = b3*cd;
//第二行
B[1][1] = c1*cd;
B[1][3] = c2*cd;
B[1][5] = c3*cd;
//第三行
B[2][0] = c1*cd;
B[2][1] = b1*cd;
B[2][2] = c2*cd;
B[2][3] = b2*cd;
B[2][4] = c3*cd;
B[2][5] = b3*cd;
//完成几何矩阵的创建;
 
//由于u=0,平面应力与平面问题的D相同;
//计算应力弹性矩阵
double D[3][3] = { { 1.0, u, 0.0 }, \
{u, 1.0, 0.0}, \
{0.0, 0.0, (1 - u) / 2}
};
for (int i = 0; i < (sizeof(D) / sizeof(D[0])); i++){
D[0][i] *= (E / (1 - u*u));
D[1][i] *= (E / (1 - u*u));
D[2][i] *= (E / (1 - u*u));
}//求得最终的应力弹性矩阵;
 
//计算应力转换矩阵
double S[3][6];
//数组初始化;
memset(S, 0.0, sizeof(S));
 
//S=D*B;
for (int j = 0; j < (sizeof(D) / sizeof(D[0])); j++){
for (int i = 0; i < (sizeof(D) / sizeof(D[0])); i++){
S[j][0] += D[j][i] * B[i][0];
S[j][1] += D[j][i] * B[i][1];
S[j][2] += D[j][i] * B[i][2];
S[j][3] += D[j][i] * B[i][3];
S[j][4] += D[j][i] * B[i][4];
S[j][5] += D[j][i] * B[i][5];
}
}
 
//将B、S及t,面积area带入公式得单元刚度矩阵Ke;
 
//求得B的转置矩阵B1;
 double B1[6][3];
memset(B1, 0.0, sizeof(B1));
for (int i = 0; i < (sizeof(B1) / sizeof(B1[0])); i++){
B1[i][0] = B[0][i];
B1[i][1] = B[1][i];
B1[i][2] = B[2][i];
}
 
//求单元刚度矩阵;
 double **B1S;
 B1S = (double **)malloc(sizeof(double *) * 6);					
		for (int i = 0; i < 6; i++) {
 		B1S[i] = (double*)malloc(sizeof(double) *6);				
	}
for(int i=0;i<6;i++)
		for(int j=0;j<6;j++)
			B1S[i][j]=0;
for (int j = 0; j < 6; j++){
for (int i = 0;  i< 3; i++){
B1S[j][0] += B1[j][i] * S[i][0];
B1S[j][1] += B1[j][i] * S[i][1];
B1S[j][2] += B1[j][i] * S[i][2];
B1S[j][3] += B1[j][i] * S[i][3];
B1S[j][4] += B1[j][i] * S[i][4];
B1S[j][5] += B1[j][i] * S[i][5];
}}
for (int j = 0; j < 6; j++){
for (int i = 0; i < 6; i++){
B1S[i][j] *= (area*t);
}
}

return B1S;
}


int main() {
		//输入基本参数
int t=1;
int E;
printf("请输入弹性模量:\n");
scanf_s("%d", &E);

double u ;
printf("请输入泊松比:\n");
scanf_s("%lf", &u);

	int  i, j, line, column = 2;							//line表示节点数
	printf("请输入节点数:\n");
scanf_s("%d", &line);

	double **x;													//定义二位数组的首地址(首地址为二级指针)
 
	x = (double **)malloc(sizeof(double *) * line);					//给行指针分配内存空间	
	
	for (i = 0; i < line; i++) {
 
		x[i] = (double*)malloc(sizeof(double) * column);				//给每个行指针后面分配2个int的空间作为列
	}

	printf("请依次输入节点的x、y坐标:\n");
		for( i=0;i<line;i++)
		scanf_s("%lf%lf",&x[i][0],&x[i][1]);
			
//确定单元节点
int danyuan;
printf("请输入单元数:\n");
scanf_s("%d", &danyuan);
int **y;													
 
	y = (int **)malloc(sizeof(int *) * danyuan);					
	
	for (i = 0; i < line; i++) {
 
		y[i] = (int*)malloc(sizeof(int) * 3);				
	}

	printf("请依次输入组成单元的节点:\n");
		for( i=0;i<danyuan;i++)
		scanf_s("%d%d%d", &y[i][0],&y[i][1],&y[i][2]);
		
			
			//定义整体刚度矩阵	
	double **K;													
 
	K = (double **)malloc(sizeof(double *) * (2*line));						
	
	for (i = 0; i < (2*line); i++) {
 
		K[i] = (double*)malloc(sizeof(double) * (2*line));				
	}

	for(i=0;i<2*line;i++)
		for(j=0;j<2*line;j++)
			K[i][j]=0;

//计算刚度矩阵
	double p[3][2];
memset(p, 0.0, sizeof(p));

for(int m=0;m<danyuan;m++){
	for( i=0;i<3;i++){
	for( j=0;j<2;j++)
		p[i][j]=x[y[m][i]-1][j];}

double **ki;

	ki=gd ( p, t, E, u);

for( i=0;i<3;i++)
	for(j=0;j<3;j++){
K[2*y[m][i]-2][2*y[m][j]-2]+=ki[2*i][2*j];
K[2*y[m][i]-1][2*y[m][j]-2]+=ki[2*i+1][2*j];
K[2*y[m][i]-2][2*y[m][j]-1]+=ki[2*i][2*j+1];
K[2*y[m][i]-1][2*y[m][j]-1]+=ki[2*i+1][2*j+1];}
}
//输出刚度矩阵
printf("整体刚度矩阵:\n");
print1(K,2*line,2*line);

//输入等效荷载矩阵
double *P;													
	P = (double *)malloc(sizeof(double ) * (2*line));
	printf("请依次输入等效节点荷载:\n");
	for(i=0;i<line;i++){
				printf("节点%d:\n",i+1);
				scanf_s("%lf%lf", &P[2*i],&P[2*i+1]);}
//给定边界条件
double *U;													
	U = (double *)malloc(sizeof(double ) * (2*line));
	int RANK=2*line;
	printf("请输入边界条件(位移为0时输入0,不为0时输入1):\n");
	for(i=0;i<2*line;i++)
		scanf_s("%lf",&U[i]);
for(i=0;i<2*line;i++){
	if(U[i]==0){
for(int m=0;m<2*line;m++)
	{K[m][i]=0.0;
	K[i][m]=0.0;}
	P[i]=0.0;
K[i][i]=1.0;}
}

for(i=0;i<2*line;i++)	
	U[i]=0;

//计算节点位移
	double get_A = 0.0;
	printf("利用以上A与b组成的增广阵进行高斯消去法计算方程组\n");
	for (int i = 1; i < RANK; i++)
	{
		for (int j = i; j<RANK; j++)
		{
			get_A = K[j][i - 1] / K[i - 1][i - 1];
			P[j] = P[j] - get_A * P[i - 1];
			for (int k = i-1; k < RANK; k++)
			{
				K[j][k] = K[j][k] - get_A * K[i-1][k];
			}
		}
	}
	printf("顺序消元后的上三角系数增广矩阵如下\n");
	for (int i = 0; i < RANK; i++)
	{
		for (int j = 0; j<RANK; j++)
		{
			printf("%g\t", K[i][j]);
		}
		printf("    %g", P[i]);
		printf("\n");
	}
	printf("节点位移:\n");

	for (int i = 0; i < RANK; i++)
	{
		double get_x = 0.0;
		for (int j = 0; j < RANK; j++)
		{
			get_x = get_x + K[RANK-1-i][j]*U[j];
		}
		U[RANK - 1 - i] = (P[RANK - 1 - i] - get_x + K[RANK - 1 - i][RANK - 1 - i] * U[RANK - 1 - i]) / K[RANK - 1 - i][RANK - 1 - i];
	}
	for (int i = 0; i < RANK; i++)
	{
		printf("x%d = %g\n", i + 1, U[i]);
	}

//计算单元应变应力
for(int m=0;m<danyuan;m++){
	for( i=0;i<3;i++){
	for( j=0;j<2;j++)
		p[i][j]=x[y[m][i]-1][j];}
double *v;
v = (double *)malloc(sizeof(double ) * (6));
for(i=0;i<3;i++)
	{v[2*i]=U[2*y[m][i]-2];
	v[2*i+1]=U[2*y[m][i]-1];
}
str( p, t, E, u,v,m+1);
}
	system("pause");
return 0;
}

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值