文章目录
- 前言
- 一、主程序
- 二、一维有限元求解程序-框架
- 三、组装刚度矩阵
- assemble_matrix_from_1D_integral.m
- 2.1 算法
- 2.2 get_standard_gauss_1D.m
- 2.3 get_Gauss_local_1D.m
前言
只是为方便学习,不做其他用途,课程理论学习来自b站视频有限元基础编程-何晓明
一、主程序
function result = main_poisson_solver_1D(left,right,h_partition,basis_type,Gauss_point_number)
% 算例为何老师课件第一章85页的例1
% 何晓明老师的程序改编而来
% 一维泊松方程的有限元求解
% 我们程序中用“FE”代替“finite element”
% 试探(trial)FE函数和测试(test)FE函数需要相同
% 到目前为止,该代码只能处理一维线性有限元和一维拉格朗日二次有限元。
% 对于其他类型的FE,我们需要在代码中添加相应的信息。
% 问题域是[left,right]
% h_partition是均匀网格划分的步长
% basis_type:FE基函数的类型
% basis_type=101:1D 线性有限元% N_basis: N代表FE基函数个数,而不是网格划分个数
% N_partition: N表示网格划分个数,而不是FE基函数个数
% N:子区间的个数
% M_partition,T_partition, M_basis,T_basis:参考程序“generate_M_T_1D.m”中的注释
% function_a: 泊松方程左边的系数函数
% funciton_f: 泊松方程的右边函数
% function_g: Dirichelet边界函数在何老师第一章的课件 章节1-1
% function_q_tilde: the name of the Neumann boundary function q(x,y) when p(x,y)=0 in my notes "Notes for tool box of standard triangular FE" section 1-1.
% function_q: the name of the Neumann boundary function q(x,y) when p(x,y) is nonzero in my notes "Notes for tool box of standard triangular FE" section 1-1.
% function_p: the name of the Robin coefficient function p(x,y) in my notes "Notes for tool box of standard triangular FE" section 1-1.% h_basis 有限元节点的步长.N_partition = (right-left)/h_partition;if basis_type==101N_basis=N_partition;
end% 划分网格信息和有限元基函数
[M_partition,T_partition]=generate_M_T_1D(left,right,h_partition,101);if basis_type==101 %1D 线性有限元M_basis=M_partition;T_basis=T_partition;
end % 高斯积分在参考区间[-1,1]上的高斯点和权重
[Gauss_coefficient_reference_1D,Gauss_point_reference_1D] = generate_Gauss_reference_1D(Gauss_point_number);% 组装刚度矩阵
number_of_elements=N_partition;
matrix_size=[N_basis+1 N_basis+1];
vector_size=N_basis+1;
if basis_type==101number_of_trial_local_basis=2;number_of_test_local_basis=2;
end%组装刚度矩阵
A=assemble_matrix_from_1D_integral('function_a',M_partition,T_partition,T_basis,T_basis,number_of_trial_local_basis,number_of_test_local_basis,number_of_elements,matrix_size,Gauss_coefficient_reference_1D,Gauss_point_reference_1D,basis_type,1,basis_type,1);%组装载荷矢量
b = assemble_vector_from_1D_integral('function_f',M_partition,T_partition,T_basis,number_of_test_local_basis,number_of_elements,vector_size,Gauss_coefficient_reference_1D,Gauss_point_reference_1D,basis_type,0);%得到边界节点的信息矩阵
boundary_nodes = generate_boundary_nodes_1D(N_basis);%处理狄利克雷边界条件
[A,b]=treat_Dirichlet_boundary_1D('function_g',A,b,boundary_nodes,M_basis);%计算数值解
result=A\b;%计算所有节点上的最大误差
if basis_type==101h_basis=h_partition;
end
maxerror=get_maximum_error_1D(result,N_basis,left,h_basis);
maximum_error_at_all_nodes_of_FE = maxerrorend
二、一维有限元求解程序-框架
function result = main_poisson_solver_1D(left,right,h_partition,basis_type,Gauss_point_number)
% 算例为何老师课件第一章85页的例1
% 何晓明老师的程序改编而来
% 一维泊松方程的有限元求解
% 我们程序中用“FE”代替“finite element”
% 试探(trial)FE函数和测试(test)FE函数需要相同
% 到目前为止,该代码只能处理一维线性有限元和一维拉格朗日二次有限元。
% 对于其他类型的FE,我们需要在代码中添加相应的信息。
% 问题域是[left,right]
% h_partition是均匀网格划分的步长
% basis_type:FE基函数的类型
% basis_type=101:1D 线性有限元% N_basis: N代表FE基函数个数,而不是网格划分个数
% N_partition: N表示网格划分个数,而不是FE基函数个数
% N:子区间的个数
% M_partition,T_partition, M_basis,T_basis:参考程序“generate_M_T_1D.m”中的注释
% function_a: 泊松方程左边的系数函数
% funciton_f: 泊松方程的右边函数
% function_g: Dirichelet边界函数在何老师第一章的课件 章节1-1
% function_q_tilde: the name of the Neumann boundary function q(x,y) when p(x,y)=0 in my notes "Notes for tool box of standard triangular FE" section 1-1.
% function_q: the name of the Neumann boundary function q(x,y) when p(x,y) is nonzero in my notes "Notes for tool box of standard triangular FE" section 1-1.
% function_p: the name of the Robin coefficient function p(x,y) in my notes "Notes for tool box of standard triangular FE" section 1-1.% h_basis 有限元节点的步长.N_partition = (right-left)/h_partition;if basis_type==101N_basis=N_partition;
end% 划分网格信息和有限元基函数
[M_partition,T_partition]=generate_M_T_1D(left,right,h_partition,101);if basis_type==101 %1D 线性有限元M_basis=M_partition;T_basis=T_partition;
end % 高斯积分在参考区间[-1,1]上的高斯点和权重
[Gauss_coefficient_reference_1D,Gauss_point_reference_1D] = generate_Gauss_reference_1D(Gauss_point_number);% 组装刚度矩阵
number_of_elements=N_partition;
matrix_size=[N_basis+1 N_basis+1];
vector_size=N_basis+1;
if basis_type==101number_of_trial_local_basis=2;number_of_test_local_basis=2;
end%组装刚度矩阵
A=assemble_matrix_from_1D_integral('function_a',M_partition,T_partition,T_basis,T_basis,number_of_trial_local_basis,number_of_test_local_basis,number_of_elements,matrix_size,Gauss_coefficient_reference_1D,Gauss_point_reference_1D,basis_type,1,basis_type,1);%组装载荷矢量
b = assemble_vector_from_1D_integral('function_f',M_partition,T_partition,T_basis,number_of_test_local_basis,number_of_elements,vector_size,Gauss_coefficient_reference_1D,Gauss_point_reference_1D,basis_type,0);%得到边界节点的信息矩阵
boundary_nodes = generate_boundary_nodes_1D(N_basis);%处理狄利克雷边界条件
[A,b]=treat_Dirichlet_boundary_1D('function_g',A,b,boundary_nodes,M_basis);%计算数值解
result=A\b;%计算所有节点上的最大误差
if basis_type==101h_basis=h_partition;
end
maxerror=get_maximum_error_1D(result,N_basis,left,h_basis);
maximum_error_at_all_nodes_of_FE = maxerrorend
三、组装刚度矩阵
assemble_matrix_from_1D_integral.m
function A = assemble_matrix_from_1D_integral(coefficient_function_name,P_mesh,T_mesh,T_basis_trial,T_basis_test,number_of_trial_local_basis,number_of_test_local_basis,number_of_elements,matrix_size,Gauss_point_number,trial_basis_type,trial_derivative_degree,test_basis_type,test_derivative_degree)
%% 注释
%{目的:计算刚度矩阵A从整个定义域上的一维积分组合出一个矩阵一维积分的被积函数必须为以下格式:a coefficient function * a trial FE basis function(or its derivatives) * a test FE basis function (or its derivatives).系数函数 * 试探函数(或其导数) * 测试函数(或其导数)
------------------------------------------------------------------------------------------------------------------------
Input:coefficient_function_name ---------- 系数函数 c(x)P_mesh ---------- 存储等分区间中所有节点的坐标T_mesh ---------- 存储等分区间中每个单元节点的全局索引T_basis_trial ---------- 试探(trial function)基函数的节点全局索引T_basis_test ---------- 测试(test function)基函数的节点全局索引number_of_trial_local_basis ---------- 局部试探函数的局部FE基函数的个数number_of_test_local_basis ---------- 局部测试函数的局部FE基函数的个数number_of_elements ---------- 网格划分的单元个数matrix_size ---------- 总刚的大小 存储总刚的行数和列数Gauss_point_number ---------- 高斯点数trial_basis_type ---------- 试探FE基函数的类型trial_derivative_degree ---------- 试探FE基函数的导数阶test_basis_type ---------- 测试FE基函数的类型test_derivative_degree ---------- 测试FE基函数的导数阶Output:A ------- 总体刚度矩阵
------------------------------------------------------------------------------------------------------------------------------注:standard_GaussWeight,standard_GaussPoint:参考区间[-1,1]上的高斯系数和高斯点trial_basis_type:试用FE基函数的类型。trial_vertices: 试探函数单元的所有顶点的坐标trial_basis_type:试验FE基函数的类型trial_basis_index: 有限元试探基函数的指标,以指定我们要使用哪个有限元试探基函数trial_derivative_degree: the trial FE basis的导数阶test_vertices、test_basis_type、test_basis_index、test_derivative_degree:与trial_basis类似vertices: 一维单元上的两个顶点的坐标Gauss_coefficient_local_1D,Gauss_point_local_1D: 局部区间上的高斯系数和高斯点------------------------------------------------------------------------------------------------------------------------------ 孟伟, 大连理工大学- 1475207248@qq.com / mw21933005@mail.dlut.edu.cn
------------------------------------------------------------------------------------------------------------------------------
%}
%% 程序
%{
思路:遍历所有单元在每个元素上,计算试探和测验FE基函数的所有可能组合的非零积分将这些非零积分的值组合到刚度矩阵中
%}A=sparse(matrix_size(1),matrix_size(2)); %总刚 初始化
% 高斯积分在标准高斯区间[-1,1]上的高斯点和权重
[standard_GaussWeight,standard_GaussPoint] = get_standard_gauss_1D(Gauss_point_number);for n=1:number_of_elements %遍历所有单元vertices = P_mesh(:,T_mesh(:,n)); %第n个单元的节点坐标 T_mesh(:,n)取出节点的全局编号矩阵T的第n列lower_bound=min(vertices(1),vertices(2));upper_bound=max(vertices(1),vertices(2));% Gauss_coefficient_local_1D,Gauss_point_local_1D: 局部区间对应 区间[-1,1] 生成的新高斯系数和高斯点[local_GaussWeight_1D,local_GaussPoint_1D] = get_Gauss_local_1D(standard_GaussWeight,standard_GaussPoint,lower_bound,upper_bound);% 计算单元上非零积分 并将其组装到刚度矩阵A中for alpha=1:number_of_trial_local_basis for beta=1:number_of_test_local_basis % Gauss_quadrature_for_1D_integral_trial_test()函数 用高斯积分公式计算[xn,xn+1]上的一维积分temp = Gauss_quadrature_for_1D_integral_trial_test(coefficient_function_name,local_GaussWeight_1D,local_GaussPoint_1D,vertices,trial_basis_type,alpha,trial_derivative_degree,vertices,test_basis_type,beta,test_derivative_degree); %i = T_basis_test(beta,n);%j = T_basis_trial(alpha,n);%A(i,j) = A(i,j) + temp;A(T_basis_test(beta,n),T_basis_trial(alpha,n)) = A(T_basis_test(beta,n),T_basis_trial(alpha,n))+temp;endendend
2.1 算法
2.2 get_standard_gauss_1D.m
function [standard_GaussWeight,standard_GaussPoint] = get_standard_gauss_1D(Gauss_point_number)
%%
%{
-------------------------------------------------------------------------------------------------得到标准高斯区间[-1,1]上的高斯点和高斯权重Input:Gauss_point_number ---------- 高斯点个数Output:standard_GaussWeight ------- 标准高斯区间的高斯权重standard_GaussPoint ------- 标准高斯区间的高斯点---------------------------------------- 孟伟, 大连理工大学- 1475207248@qq.com / mw21933005@mail.dlut.edu.cn
-------------------------------------------------------------------------------------------------
%}
%%
if Gauss_point_number==2standard_GaussWeight=[1,1];standard_GaussPoint=[-1/sqrt(3),1/sqrt(3)];
elseif Gauss_point_number==4standard_GaussWeight=[0.3478548451,0.3478548451,0.6521451549,0.6521451549];standard_GaussPoint=[0.8611363116,-0.8611363116,0.3399810436,-0.3399810436];
elseif Gauss_point_number==8standard_GaussWeight=[0.1012285363,0.1012285363,0.2223810345,0.2223810345,0.3137066459,0.3137066459,0.3626837834,0.3626837834];standard_GaussPoint=[0.9602898565,-0.9602898565,0.7966664774,-0.7966664774,0.5255324099,-0.5255324099,0.1834346425,-0.1834346425];endend
2.3 get_Gauss_local_1D.m
function [local_GaussWeight_1D,local_GaussPoint_1D] = get_Gauss_local_1D(standard_GaussWeight_1D,standard_GaussPoint_1D,lower_bound,upper_bound)
%{目的: 使用仿射变换在任意区间[lower_bound,upper_bound]上生成高斯系数和高斯点由[lower_bound,upper_bound]区间 转换为 高斯积分标准区间[-1,1]上的高斯系数和高斯点
--------------------------------------------------------------------------------------Input:lower_bound ----------------- 积分下限upper_bound ----------------- 积分上限standard_GaussWeight -------- 标准高斯区间[-1,1]的高斯权重standard_GaussPoint -------- 标准高斯区间[-1,1]的高斯点Output:local_GaussWeight_1D ------- 任意区间上对应的高斯系数local_GaussPoint_1D ------- 任意区间上对应的高斯点
--------------------------------------------------------------------------------------注1:[a,b] 区间的gauss积分 ---> [-1,1] 区间的gauss积分 [-1,1] gauss积分系数 * (b-a)/2[-1,1] gauss积分点 * (b-a)/2 + (b+a)/2local_GaussWeight_1D:存储的是一个向量
--------------------------------------------------------------------------------------- 孟伟, 大连理工大学- 1475207248@qq.com / mw21933005@mail.dlut.edu.cn
--------------------------------------------------------------------------------------
%}local_GaussWeight_1D = (upper_bound-lower_bound) * standard_GaussWeight_1D / 2;
local_GaussPoint_1D =(upper_bound-lower_bound) * standard_GaussPoint_1D / 2 + (upper_bound + lower_bound)/ 2;
end
程序太多了,我就不一一放上去了,可以从我的博客有限元基础编程-何晓明老师课件-一维程序实现matlab下载
最后非常感谢何晓明老师无私的讲解