Introduction to Matrix inversion and finite element analysis. Is this code right?

clc;
clear;
close all;
%% =========================
% MATERIAL PROPERTIES
%% =========================
E = 300e9; % Young modulus (Pa)
d = 0.25e-2; % Diameter (m)
A = pi*d^2/4; % Area
%% =========================
% NODE COORDINATES
%% =========================
nodes = [0 0;
1 0;
1 1];
%% =========================
% ELEMENTS
%% =========================
elements = [1 3;
2 3];
%% =========================
% GLOBAL MATRIX
%% =========================
K = zeros(6);
for e = 1:2
n1 = elements(e,1);
n2 = elements(e,2);
x1 = nodes(n1,1);
y1 = nodes(n1,2);
x2 = nodes(n2,1);
y2 = nodes(n2,2);
L = sqrt((x2-x1)^2 + (y2-y1)^2);
c = (x2-x1)/L;
s = (y2-y1)/L;
% Element stiffness matrix
k = (E*A/L)* ...
[ c^2 c*s -c^2 -c*s
c*s s^2 -c*s -s^2
-c^2 -c*s c^2 c*s
-c*s -s^2 c*s s^2 ];
% DOF locations
if e == 1
dof = [1 2 5 6];
else
dof = [3 4 5 6];
end
% Assembly
K(dof,dof) = K(dof,dof) + k;
fprintf('Element %d stiffness matrix:\n',e)
disp(k)
end
Element 1 stiffness matrix:
1.0e+05 * 5.2065 5.2065 -5.2065 -5.2065 5.2065 5.2065 -5.2065 -5.2065 -5.2065 -5.2065 5.2065 5.2065 -5.2065 -5.2065 5.2065 5.2065
Element 2 stiffness matrix:
1.0e+06 * 0 0 0 0 0 1.4726 0 -1.4726 0 0 0 0 0 -1.4726 0 1.4726
%% =========================
% CHECKS BEFORE BC
%% =========================
disp('Global stiffness matrix:')
Global stiffness matrix:
disp(K)
1.0e+06 * 0.5207 0.5207 0 0 -0.5207 -0.5207 0.5207 0.5207 0 0 -0.5207 -0.5207 0 0 0 0 0 0 0 0 0 1.4726 0 -1.4726 -0.5207 -0.5207 0 0 0.5207 0.5207 -0.5207 -0.5207 0 -1.4726 0.5207 1.9933
disp('Determinant:')
Determinant:
disp(det(K))
0
disp('Eigenvalues:')
Eigenvalues:
disp(eig(K))
1.0e+06 * -0.0000 -0.0000 0.0000 0.0000 1.5378 3.4900
disp('Condition number:')
Condition number:
disp(cond(K))
8.1818e+32
%% =========================
% FORCE VECTOR
%% =========================
F = [0;
0;
0;
0;
100;
0];
%% =========================
% BOUNDARY CONDITIONS
%% =========================
fixed = [1 2 3 4];
free = [5 6];
Kff = K(free,free);
Ff = F(free);
%% =========================
% AFTER BC CHECKS
%% =========================
disp('Reduced stiffness matrix:')
Reduced stiffness matrix:
disp(Kff)
1.0e+06 * 0.5207 0.5207 0.5207 1.9933
disp('Determinant after BC:')
Determinant after BC:
disp(det(Kff))
7.6672e+11
disp('Eigenvalues after BC:')
Eigenvalues after BC:
disp(eig(Kff))
1.0e+06 * 0.3552 2.1588
disp('Condition number after BC:')
Condition number after BC:
disp(cond(Kff))
6.0781
%% =========================
% DISPLACEMENTS
%% =========================
Uf = inv(Kff)*Ff;
U = zeros(6,1);
U(free) = Uf;
disp('Displacements:')
Displacements:
disp(U)
1.0e-03 * 0 0 0 0 0.2600 -0.0679
%% =========================
% REACTION FORCES
%% =========================
R = K*U - F;
disp('Reaction forces:')
Reaction forces:
disp(R)
-100.0000 -100.0000 0 100.0000 -0.0000 -0.0000
%% =========================
% PLOT
%% =========================
scale = 1000;
new_nodes = nodes;
new_nodes(1,1) = nodes(1,1) + scale*U(1);
new_nodes(1,2) = nodes(1,2) + scale*U(2);
new_nodes(2,1) = nodes(2,1) + scale*U(3);
new_nodes(2,2) = nodes(2,2) + scale*U(4);
new_nodes(3,1) = nodes(3,1) + scale*U(5);
new_nodes(3,2) = nodes(3,2) + scale*U(6);
figure
hold on
grid on
axis equal
% Original truss
for i = 1:2
n1 = elements(i,1);
n2 = elements(i,2);
plot([nodes(n1,1) nodes(n2,1)], ...
[nodes(n1,2) nodes(n2,2)], ...
'b','LineWidth',2)
end
% Deformed truss
for i = 1:2
n1 = elements(i,1);
n2 = elements(i,2);
plot([new_nodes(n1,1) new_nodes(n2,1)], ...
[new_nodes(n1,2) new_nodes(n2,2)], ...
'r--','LineWidth',2)
end
legend('Original','Deformed')
title('Truss Deformation')
xlabel('X')
ylabel('Y')

Respuestas (1)

Stephen23
Stephen23 el 7 de Mayo de 2026 a las 12:21
Editada: Stephen23 el 8 de Mayo de 2026 a las 4:30
Yes, the code looks correct. Here is a quick sanity-check of each key piece:
DOF numbering is consistent throughout: node i owns DOFs 2i-1 (x) and 2i (y)
NodeDOFs
(0,0) -> 1,2
(1,0) -> 3,4
(1,1) -> 5,6
Element DOF mapping matches that convention:
  • Element 1 (nodes 1 -> 3): [1,2,5,6]
  • Element 2 (nodes 2 -> 3): [3,4,5,6]
Boundary conditions pin nodes 1 and 2 (DOFs 1–4), leaving node 3 free (DOFs 5–6), correct for a two-bar truss with a tip load.
Applied force F(5)=100 puts a horizontal load at node 3 in the x-direction, which is consistent with the problem setup.
new_nodes reshape is correct and maps cleanly onto the nodes matrix layout.
Physics check element 2 is vertical (c=0, s=1), so it can only resist vertical displacement at node 3, not horizontal. The diagonal element 1 (c=s=1/sqrt(2)) is the only one bracing the horizontal load, which is why node 3 will show a large horizontal displacement and a small vertical one. That is the expected behaviour for this geometry.
Everything looks good.
I made a few tweaks to your code (e.g. fixed the legend, replaced INV with MLDIVIDE):
%% =========================
% MATERIAL PROPERTIES
%% =========================
E = 300e9; % Young modulus (Pa)
d = 0.25e-2; % Diameter (m)
A = pi*d^2/4; % Area
%% =========================
% NODE COORDINATES
%% =========================
nodes = [0,0;...
1,0;...
1,1];
%% =========================
% ELEMENTS
%% =========================
elements = [1,3;...
2,3];
%% =========================
% GLOBAL MATRIX
%% =========================
K = zeros(6);
for e = 1:2
n1 = elements(e,1);
n2 = elements(e,2);
x1 = nodes(n1,1);
y1 = nodes(n1,2);
x2 = nodes(n2,1);
y2 = nodes(n2,2);
L = sqrt((x2-x1)^2 + (y2-y1)^2);
c = (x2-x1)/L;
s = (y2-y1)/L;
% Element stiffness matrix
k = (E*A/L)* ...
[ c^2, c*s, -c^2, -c*s;...
c*s, s^2, -c*s, -s^2;...
-c^2, -c*s, c^2, c*s;...
-c*s, -s^2, c*s, s^2 ];
% DOF locations
if e == 1
dof = [1,2,5,6];
else
dof = [3,4,5,6];
end
% Assembly
K(dof,dof) = K(dof,dof) + k;
fprintf('Element %d stiffness matrix:\n',e)
disp(k)
end
Element 1 stiffness matrix:
1.0e+05 * 5.2065 5.2065 -5.2065 -5.2065 5.2065 5.2065 -5.2065 -5.2065 -5.2065 -5.2065 5.2065 5.2065 -5.2065 -5.2065 5.2065 5.2065
Element 2 stiffness matrix:
1.0e+06 * 0 0 0 0 0 1.4726 0 -1.4726 0 0 0 0 0 -1.4726 0 1.4726
%% =========================
% CHECKS BEFORE BC
%% =========================
disp('Global stiffness matrix:')
Global stiffness matrix:
disp(K)
1.0e+06 * 0.5207 0.5207 0 0 -0.5207 -0.5207 0.5207 0.5207 0 0 -0.5207 -0.5207 0 0 0 0 0 0 0 0 0 1.4726 0 -1.4726 -0.5207 -0.5207 0 0 0.5207 0.5207 -0.5207 -0.5207 0 -1.4726 0.5207 1.9933
disp('Determinant:')
Determinant:
disp(det(K))
0
disp('Eigenvalues:')
Eigenvalues:
disp(eig(K))
1.0e+06 * -0.0000 -0.0000 0.0000 0.0000 1.5378 3.4900
disp('Condition number:')
Condition number:
disp(cond(K))
8.1818e+32
%% =========================
% FORCE VECTOR
%% =========================
F = [0; 0; 0; 0; 100; 0];
%% =========================
% BOUNDARY CONDITIONS
%% =========================
fixed = [1,2,3,4];
free = [5,6];
Kff = K(free,free);
Ff = F(free);
%% =========================
% AFTER BC CHECKS
%% =========================
disp('Reduced stiffness matrix:')
Reduced stiffness matrix:
disp(Kff)
1.0e+06 * 0.5207 0.5207 0.5207 1.9933
disp('Determinant after BC:')
Determinant after BC:
disp(det(Kff))
7.6672e+11
disp('Eigenvalues after BC:')
Eigenvalues after BC:
disp(eig(Kff))
1.0e+06 * 0.3552 2.1588
disp('Condition number after BC:')
Condition number after BC:
disp(cond(Kff))
6.0781
%% =========================
% DISPLACEMENTS
%% =========================
%Uf = inv(Kff)*Ff;
Uf = Kff \ Ff; % better than INV
U = zeros(6,1);
U(free) = Uf;
disp('Displacements:')
Displacements:
disp(U)
1.0e-03 * 0 0 0 0 0.2600 -0.0679
%% =========================
% REACTION FORCES
%% =========================
R = K*U - F;
disp('Reaction forces:')
Reaction forces:
disp(R)
-100 -100 0 100 0 0
%% =========================
% PLOT
%% =========================
scale = 1000;
% new_nodes = nodes;
% new_nodes(1,1) = nodes(1,1) + scale*U(1);
% new_nodes(1,2) = nodes(1,2) + scale*U(2);
% new_nodes(2,1) = nodes(2,1) + scale*U(3);
% new_nodes(2,2) = nodes(2,2) + scale*U(4);
% new_nodes(3,1) = nodes(3,1) + scale*U(5);
% new_nodes(3,2) = nodes(3,2) + scale*U(6);
new_nodes = nodes + scale * reshape(U,2,[]).';
figure
hold on
grid on
axis equal
% Original truss
for i = 1:2
n1 = elements(i,1);
n2 = elements(i,2);
ho = plot([nodes(n1,1) nodes(n2,1)], ...
[nodes(n1,2) nodes(n2,2)], ...
'b','LineWidth',2);
end
% Deformed truss
for i = 1:2
n1 = elements(i,1);
n2 = elements(i,2);
hd = plot([new_nodes(n1,1) new_nodes(n2,1)], ...
[new_nodes(n1,2) new_nodes(n2,2)], ...
'r--','LineWidth',2);
end
legend([ho,hd],'Original','Deformed', 'location','northwest')
title('Truss Deformation')
xlabel('X')
ylabel('Y')

Categorías

Etiquetas

Preguntada:

el 7 de Mayo de 2026 a las 11:49

Editada:

el 8 de Mayo de 2026 a las 4:30

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by