├── .gitattributes ├── .gitignore ├── README.md ├── bar_problem ├── assembly_1dbar_p1.m ├── assembly_1dbar_p2.m ├── assembly_files │ ├── assembly_1dbar_p1_numElements01.mat │ ├── assembly_1dbar_p1_numElements02.mat │ ├── assembly_1dbar_p1_numElements04.mat │ ├── assembly_1dbar_p1_numElements08.mat │ ├── assembly_1dbar_p2_numElements01.mat │ ├── assembly_1dbar_p2_numElements02.mat │ ├── assembly_1dbar_p2_numElements04.mat │ └── assembly_1dbar_p2_numElements08.mat ├── driver_p1.m ├── driver_p2.m ├── screenshots │ ├── 1dbar_p1_numElements01.png │ ├── 1dbar_p1_numElements02.png │ ├── 1dbar_p1_numElements04.png │ ├── 1dbar_p1_numElements08.png │ ├── 1dbar_p2_numElements01.png │ ├── 1dbar_p2_numElements02.png │ ├── 1dbar_p2_numElements04.png │ └── 1dbar_p2_numElements08.png └── solution_files │ ├── solution_1dbar_p1_numElements01.mat │ ├── solution_1dbar_p1_numElements02.mat │ ├── solution_1dbar_p1_numElements04.mat │ ├── solution_1dbar_p1_numElements08.mat │ ├── solution_1dbar_p2_numElements01.mat │ ├── solution_1dbar_p2_numElements02.mat │ ├── solution_1dbar_p2_numElements04.mat │ └── solution_1dbar_p2_numElements08.mat ├── extras ├── Documentation.pdf ├── Notes_020315.pdf ├── convertAssemblyFile.m ├── draw_frame.m ├── draw_plate.m ├── draw_truss.m └── main.m ├── frame_2d ├── 2dframe_problem1.mat ├── 2dframe_problem1_alt.mat ├── assembly_2dframe.m ├── assembly_2dtruss.m ├── draw_frame.m └── draw_truss.m ├── plate_problem ├── HW #10.xlsx ├── assembly12.mat ├── assembly24.mat ├── assembly6.mat ├── assemblyR.mat ├── assembly_2dplate.m ├── convertAssemblyFile.m ├── displacement_plate06.png ├── displacement_plate12.png ├── displacement_plate24.png ├── displacement_plateR.png ├── displacements12 ├── displacements24 ├── displacements6 ├── displacementsR ├── draw_plate.m ├── draw_plate_original.m ├── elements12 ├── elements24 ├── elements6 ├── elementsR ├── forces12 ├── forces24 ├── forces6 ├── forcesR ├── nodes12 ├── nodes24 ├── nodes6 ├── nodesR ├── stress_xx_plate06.png ├── stress_xx_plate12.png ├── stress_xx_plate24.png ├── stress_xx_plateR.png ├── stress_xy_plate06.png ├── stress_xy_plate12.png ├── stress_xy_plate24.png ├── stress_xy_plateR.png ├── stress_yy_plate06.png ├── stress_yy_plate12.png ├── stress_yy_plate24.png ├── stress_yy_plateR.png └── triangle.f ├── truss analysis ├── Documentation │ ├── Documentation.aux │ ├── Documentation.dvi │ ├── Documentation.log │ ├── Documentation.out │ ├── Documentation.pdf │ └── Documentation.tex ├── assembly_truss.m ├── main.m ├── sample.mat ├── sample_assembly.mat ├── sample_assembly_BCs_displacement.txt ├── sample_assembly_BCs_force.txt ├── sample_assembly_elements.txt ├── sample_assembly_nodes.txt └── sample_plot.png ├── truss_2d ├── Documentation │ ├── Documentation.aux │ ├── Documentation.dvi │ ├── Documentation.log │ ├── Documentation.out │ ├── Documentation.pdf │ ├── Documentation.tex │ └── main.m ├── assembly_2dtruss.m └── main.m ├── truss_3d ├── 3dtruss_problem1.mat ├── 3dtruss_problem2.mat ├── 3dtruss_problem3.mat ├── 3dtruss_problem4.mat ├── 3dtruss_problem5.mat └── assembly_3dtruss.m └── updated ├── demo1_gui_truss_analysis.m ├── demo1_gui_truss_analysis └── bridge.mat ├── demo2_analyze_2dframe.m ├── demo2_analyze_2dtruss.m ├── demo2_analyze_truss_frame ├── assembly_bridge.mat ├── draw_frame.m └── draw_truss.m ├── demo3_analyze_1dbar_winkler ├── analyze_1dbar_p1.m ├── analyze_1dbar_p2.m ├── assembly_files │ ├── assembly_1dbar_p1_numElements01.mat │ ├── assembly_1dbar_p1_numElements02.mat │ ├── assembly_1dbar_p1_numElements04.mat │ ├── assembly_1dbar_p1_numElements08.mat │ ├── assembly_1dbar_p2_numElements01.mat │ ├── assembly_1dbar_p2_numElements02.mat │ ├── assembly_1dbar_p2_numElements04.mat │ └── assembly_1dbar_p2_numElements08.mat └── solution_files │ ├── solution_1dbar_p1_numElements01.mat │ ├── solution_1dbar_p1_numElements02.mat │ ├── solution_1dbar_p1_numElements04.mat │ ├── solution_1dbar_p1_numElements08.mat │ ├── solution_1dbar_p2_numElements01.mat │ ├── solution_1dbar_p2_numElements02.mat │ ├── solution_1dbar_p2_numElements04.mat │ └── solution_1dbar_p2_numElements08.mat ├── demo3_driver_1dbar_p1.m ├── demo3_driver_1dbar_p2.m ├── demo4_analyze_2dplate.m ├── demo4_analyze_2dplate ├── assembly_numElements06.mat ├── assembly_numElements12.mat ├── assembly_numElements12R.mat ├── assembly_numElements24.mat └── draw_plate.m └── problem_description_demo3.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Finite Element Analysis 2 | Hi and welcome to the GitHub page for my Finite Element Analysis library. 3 | 4 | The code that I provide complement my teaching in computational mechanics. I hope that you find the library useful in learning finite element method and solving your own engineering problems. 5 | 6 | Unless I noted otherwise, I have written all code. I'd much appreciate it if you cite [my blog](https://crunchingnumbers.live) and code in your medium of output, e.g. papers, code, your very own blog. :) 7 | 8 | If you have suggestions for making my code better and simpler, please let me know! 9 | 10 | 11 | Isaac, 12 | -------------------------------------------------------------------------------- /bar_problem/assembly_1dbar_p1.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: Isaac J. Lee 3 | % E-mail: ijlee2@ices.utexas.edu 4 | % 5 | % This routine solves the bar (pile) problem with a Winkler foundation 6 | % using a linear polynomial basis. 7 | %-------------------------------------------------------------------------- 8 | function assembly_1dbar_p1(problem_size) 9 | % Load the assembly file 10 | load(strcat('assembly_files/assembly_1dbar_p1_numElements', problem_size)); 11 | 12 | % Find the number of nodes, etc. from the assembly file 13 | numNodes = size(nodes, 1); 14 | numElements = size(elements, 1); 15 | numBCs_displacement = size(BCs_displacement, 1); 16 | numBCs_force = size(BCs_force, 1); 17 | 18 | % Set the number of degrees of freedom (DOFs) for 1D elasticity 19 | numDOFsPerNode = 1; 20 | numDOFs = numDOFsPerNode * numNodes; 21 | 22 | % Initialize the stiffness matrix, the solution and RHS vectors 23 | K = zeros(numDOFs, numDOFs); 24 | u = zeros(numDOFs, 1); 25 | f = zeros(numDOFs, 1); 26 | 27 | 28 | %---------------------------------------------------------------------- 29 | % Set the gcon array 30 | % 31 | % We create gcon so that the known displacements are stored on the 32 | % bottom side of u and the known forces are stored on the top of f. 33 | % While we populate the gcon array, we prescribe the known values 34 | % into the vectors u and f. 35 | %---------------------------------------------------------------------- 36 | gcon = zeros(numNodes, numDOFsPerNode); 37 | 38 | % index_f is a vector of indices for the known forces, and 39 | % index_u is a vector of indices for the known displacements 40 | index_f = 1 : numBCs_force; 41 | index_u = (numBCs_force + 1) : numDOFs; 42 | 43 | % Counter to keep track of how many DOFs we have encountered so far 44 | count = 1; 45 | 46 | % Prescribe the forces 47 | for i = 1 : numBCs_force 48 | gcon(BCs_force(i, 1), BCs_force(i, 2)) = count; 49 | f(count) = BCs_force(i, 3); 50 | count = count + 1; 51 | end 52 | 53 | % Prescribe the displacements 54 | for i = 1 : numBCs_displacement 55 | gcon(BCs_displacement(i, 1), BCs_displacement(i, 2)) = count; 56 | u(count) = BCs_displacement(i, 3); 57 | count = count + 1; 58 | end 59 | 60 | 61 | %---------------------------------------------------------------------- 62 | % Set the quadrature rule (3-point Gauss quadrature) 63 | %---------------------------------------------------------------------- 64 | z = [-sqrt(3/5); 0; sqrt(3/5)]; 65 | w = [5/9; 8/9; 5/9]; 66 | numQuadraturePoints = size(z, 1); 67 | 68 | % Specify the basis functions and their derivatives 69 | eval_N = @(xi) [-1/2*xi + 1/2, ... 70 | 1/2*xi + 1/2]; 71 | eval_B = @(xi) [-1/2*ones(size(xi, 1), 1), ... 72 | 1/2*ones(size(xi, 1), 1)]; 73 | 74 | % Evaluate them at the quadrature points 75 | N = eval_N(z); 76 | B = eval_B(z); 77 | 78 | % Specify the distributed load 79 | P_0 = abs(BCs_force(1, 3)); 80 | L = nodes(numNodes, 1); 81 | eval_distributed_load = @(x) P_0 / L; 82 | 83 | 84 | %---------------------------------------------------------------------- 85 | % Create the stiffness matrix K and the load vector f 86 | %---------------------------------------------------------------------- 87 | numNodesPerElement = 2; 88 | numDOFsPerElement = numNodesPerElement * numDOFsPerNode; 89 | 90 | % Loop over the elements 91 | for e = 1 : numElements 92 | % Get the node indices 93 | node1Index = elements(e, 1); 94 | node2Index = elements(e, 2); 95 | 96 | % Get the nodal positions 97 | x1 = nodes(node1Index, 1); 98 | x2 = nodes(node2Index, 1); 99 | x_e = [x1; x2]; 100 | 101 | % Get the element properties (constant) 102 | E = elements(e, 3); 103 | A = elements(e, 4); 104 | k = E*A/L^2; 105 | 106 | % Evaluate the elasticity matrix (constant) 107 | C = [E]; 108 | 109 | % Initialize the element stiffness matrix and element load vector 110 | K_e = zeros(numNodesPerElement, numNodesPerElement); 111 | f_e = zeros(numNodesPerElement, 1); 112 | 113 | % Loop over the quadrature points 114 | for i = 1 : numQuadraturePoints 115 | % Get the values of the basis functions and their derivatives 116 | % at the quadrature point 117 | N_e = N(i, :); 118 | B_e = B(i, :); 119 | 120 | % Find the point x in the physical domain that corresponds to 121 | % the quadrature point 122 | x = N_e * x_e; 123 | 124 | % Evaluate the Jacobian at the quadrature point 125 | J = B_e * x_e; 126 | 127 | % Evaluate the distributed load at the quadrature point 128 | distributed_load = eval_distributed_load(x); 129 | 130 | % Form the element stiffness matrix 131 | K_e = K_e + w(i) * (A * (B_e' * C * B_e) * 1/J + k * (N_e' * N_e) * J); 132 | 133 | % Form the element load vector 134 | f_e = f_e + w(i) * (distributed_load * N_e' * J); 135 | end 136 | 137 | % Get the global DOF indices 138 | index = [gcon(node1Index, 1); ... 139 | gcon(node2Index, 1)]; 140 | 141 | % Global assembly 142 | for i = 1 : numDOFsPerElement 143 | for j = 1 : numDOFsPerElement 144 | K(index(i), index(j)) = K(index(i), index(j)) + K_e(i, j); 145 | end 146 | 147 | f(index(i)) = f(index(i)) + f_e(i); 148 | end 149 | end 150 | 151 | 152 | %---------------------------------------------------------------------- 153 | % Solve for the unknown displacements and forces 154 | %---------------------------------------------------------------------- 155 | % Solve for the unknown displacements 156 | u(index_f) = K(index_f, index_f) \ (f(index_f) - K(index_f, index_u) * u(index_u)); 157 | 158 | % Solve for the unknown forces 159 | f(index_u) = K(index_u, index_f) * u(index_f) + K(index_u, index_u) * u(index_u); 160 | 161 | save(strcat('solution_files/solution_1dbar_p1_numElements', problem_size), 'u', 'f', 'gcon', '-v6'); 162 | end -------------------------------------------------------------------------------- /bar_problem/assembly_1dbar_p2.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: Isaac J. Lee 3 | % E-mail: ijlee2@ices.utexas.edu 4 | % 5 | % This routine solves the bar (pile) problem with a Winkler foundation 6 | % using a quadratic polynomial basis. 7 | %-------------------------------------------------------------------------- 8 | function assembly_1dbar_p2(problem_size) 9 | % Load the assembly file 10 | load(strcat('assembly_files/assembly_1dbar_p2_numElements', problem_size)); 11 | 12 | % Find the number of nodes, etc. from the assembly file 13 | numNodes = size(nodes, 1); 14 | numElements = size(elements, 1); 15 | numBCs_displacement = size(BCs_displacement, 1); 16 | numBCs_force = size(BCs_force, 1); 17 | 18 | % Set the number of degrees of freedom (DOFs) for 1D elasticity 19 | numDOFsPerNode = 1; 20 | numDOFs = numDOFsPerNode * numNodes; 21 | 22 | % Initialize the stiffness matrix, the solution and RHS vectors 23 | K = zeros(numDOFs, numDOFs); 24 | u = zeros(numDOFs, 1); 25 | f = zeros(numDOFs, 1); 26 | 27 | 28 | %---------------------------------------------------------------------- 29 | % Set the gcon array 30 | % 31 | % We create gcon so that the known displacements are stored on the 32 | % bottom side of u and the known forces are stored on the top of f. 33 | % While we populate the gcon array, we prescribe the known values 34 | % into the vectors u and f. 35 | %---------------------------------------------------------------------- 36 | gcon = zeros(numNodes, numDOFsPerNode); 37 | 38 | % index_f is a vector of indices for the known forces, and 39 | % index_u is a vector of indices for the known displacements 40 | index_f = 1 : numBCs_force; 41 | index_u = (numBCs_force + 1) : numDOFs; 42 | 43 | % Counter to keep track of how many DOFs we have encountered so far 44 | count = 1; 45 | 46 | % Prescribe the forces 47 | for i = 1 : numBCs_force 48 | gcon(BCs_force(i, 1), BCs_force(i, 2)) = count; 49 | f(count) = BCs_force(i, 3); 50 | count = count + 1; 51 | end 52 | 53 | % Prescribe the displacements 54 | for i = 1 : numBCs_displacement 55 | gcon(BCs_displacement(i, 1), BCs_displacement(i, 2)) = count; 56 | u(count) = BCs_displacement(i, 3); 57 | count = count + 1; 58 | end 59 | 60 | 61 | %---------------------------------------------------------------------- 62 | % Set the quadrature rule (3-point Gauss quadrature) 63 | %---------------------------------------------------------------------- 64 | z = [-sqrt(3/5); 0; sqrt(3/5)]; 65 | w = [5/9; 8/9; 5/9]; 66 | numQuadraturePoints = size(z, 1); 67 | 68 | % Specify the basis functions and their derivatives 69 | eval_N = @(xi) [1/2*xi.^2 - 1/2*xi, ... 70 | -xi.^2 + 1, ... 71 | 1/2*xi.^2 + 1/2*xi]; 72 | eval_B = @(xi) [xi - 1/2, ... 73 | -2*xi, ... 74 | xi + 1/2]; 75 | 76 | % Evaluate them at the quadrature points 77 | N = eval_N(z); 78 | B = eval_B(z); 79 | 80 | % Specify the distributed load 81 | P_0 = abs(BCs_force(1, 3)); 82 | L = nodes(numNodes, 1); 83 | eval_distributed_load = @(x) P_0 / L; 84 | 85 | 86 | %---------------------------------------------------------------------- 87 | % Create the stiffness matrix K and the load vector f 88 | %---------------------------------------------------------------------- 89 | numNodesPerElement = 3; 90 | numDOFsPerElement = numNodesPerElement * numDOFsPerNode; 91 | 92 | % Loop over the elements 93 | for e = 1 : numElements 94 | % Get the node indices 95 | node1Index = elements(e, 1); 96 | node2Index = elements(e, 2); 97 | node3Index = elements(e, 3); 98 | 99 | % Get the nodal positions 100 | x1 = nodes(node1Index, 1); 101 | x2 = nodes(node2Index, 1); 102 | x3 = nodes(node3Index, 1); 103 | x_e = [x1; x2; x3]; 104 | 105 | % Get the element properties (constant) 106 | E = elements(e, 4); 107 | A = elements(e, 5); 108 | k = E*A/L^2; 109 | 110 | % Evaluate the elasticity matrix (constant) 111 | C = [E]; 112 | 113 | % Initialize the element stiffness matrix and element load vector 114 | K_e = zeros(numNodesPerElement, numNodesPerElement); 115 | f_e = zeros(numNodesPerElement, 1); 116 | 117 | % Loop over the quadrature points 118 | for i = 1 : numQuadraturePoints 119 | % Get the values of the basis functions and their derivatives 120 | % at the quadrature point 121 | N_e = N(i, :); 122 | B_e = B(i, :); 123 | 124 | % Find the point x in the physical domain that corresponds to 125 | % the quadrature point 126 | x = N_e * x_e; 127 | 128 | % Evaluate the Jacobian at the quadrature point 129 | J = B_e * x_e; 130 | 131 | % Evaluate the distributed load at the quadrature point 132 | distributed_load = eval_distributed_load(x); 133 | 134 | % Form the element stiffness matrix 135 | K_e = K_e + w(i) * (A * (B_e' * C * B_e) * 1/J + k * (N_e' * N_e) * J); 136 | 137 | % Form the element load vector 138 | f_e = f_e + w(i) * (distributed_load * N_e' * J); 139 | end 140 | 141 | % Get the global DOF indices 142 | index = [gcon(node1Index, 1); ... 143 | gcon(node2Index, 1); ... 144 | gcon(node3Index, 1)]; 145 | 146 | % Global assembly 147 | for i = 1 : numDOFsPerElement 148 | for j = 1 : numDOFsPerElement 149 | K(index(i), index(j)) = K(index(i), index(j)) + K_e(i, j); 150 | end 151 | 152 | f(index(i)) = f(index(i)) + f_e(i); 153 | end 154 | end 155 | 156 | 157 | %---------------------------------------------------------------------- 158 | % Solve for the unknown displacements and forces 159 | %---------------------------------------------------------------------- 160 | % Solve for the unknown displacements 161 | u(index_f) = K(index_f, index_f) \ (f(index_f) - K(index_f, index_u) * u(index_u)); 162 | 163 | % Solve for the unknown forces 164 | f(index_u) = K(index_u, index_f) * u(index_f) + K(index_u, index_u) * u(index_u); 165 | 166 | save(strcat('solution_files/solution_1dbar_p2_numElements', problem_size), 'u', 'f', 'gcon', '-v6'); 167 | end -------------------------------------------------------------------------------- /bar_problem/assembly_files/assembly_1dbar_p1_numElements01.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/assembly_files/assembly_1dbar_p1_numElements01.mat -------------------------------------------------------------------------------- /bar_problem/assembly_files/assembly_1dbar_p1_numElements02.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/assembly_files/assembly_1dbar_p1_numElements02.mat -------------------------------------------------------------------------------- /bar_problem/assembly_files/assembly_1dbar_p1_numElements04.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/assembly_files/assembly_1dbar_p1_numElements04.mat -------------------------------------------------------------------------------- /bar_problem/assembly_files/assembly_1dbar_p1_numElements08.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/assembly_files/assembly_1dbar_p1_numElements08.mat -------------------------------------------------------------------------------- /bar_problem/assembly_files/assembly_1dbar_p2_numElements01.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/assembly_files/assembly_1dbar_p2_numElements01.mat -------------------------------------------------------------------------------- /bar_problem/assembly_files/assembly_1dbar_p2_numElements02.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/assembly_files/assembly_1dbar_p2_numElements02.mat -------------------------------------------------------------------------------- /bar_problem/assembly_files/assembly_1dbar_p2_numElements04.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/assembly_files/assembly_1dbar_p2_numElements04.mat -------------------------------------------------------------------------------- /bar_problem/assembly_files/assembly_1dbar_p2_numElements08.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/assembly_files/assembly_1dbar_p2_numElements08.mat -------------------------------------------------------------------------------- /bar_problem/driver_p1.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: Isaac J. Lee 3 | % E-mail: ijlee2@ices.utexas.edu 4 | % 5 | % This driver calls the assembly routine to solve the bar problem with a 6 | % Winkler foundation for 1, 2, 4, 8 elements with a linear basis. 7 | % It then plots the FE displacement and force fields for comparison. 8 | %-------------------------------------------------------------------------- 9 | function driver_p1() 10 | clc; clf; 11 | clear all; close all; 12 | format long; 13 | 14 | % Parameters for plotting 15 | numPoints = 1000; 16 | problem_size = {'01'; '02'; '04'; '08'}; 17 | problem_color = [0.7, 0.35, 0.45; ... 18 | 0.8, 0.75, 0.3; ... 19 | 0.4, 0.75, 0.55; ... 20 | 0.4, 0.7, 0.9]; 21 | problem_legend = {'1 element'; '2 elements'; '4 elements'; '8 elements'}; 22 | 23 | % Specify the basis functions and their derivatives 24 | eval_N = @(xi) [-1/2*xi + 1/2, ... 25 | 1/2*xi + 1/2]; 26 | eval_B = @(xi) [-1/2*ones(size(xi, 1), 1), ... 27 | 1/2*ones(size(xi, 1), 1)]; 28 | 29 | 30 | %---------------------------------------------------------------------- 31 | % Begin solving the problem 32 | %---------------------------------------------------------------------- 33 | for i = 1 : size(problem_size, 1) 34 | % Solve the bar problem 35 | assembly_1dbar_p1(problem_size{i}); 36 | 37 | % Load the assembly and solution files 38 | load(strcat('assembly_files/assembly_1dbar_p1_numElements', problem_size{i}), 'nodes', 'elements'); 39 | load(strcat('solution_files/solution_1dbar_p1_numElements', problem_size{i}), 'u', 'gcon'); 40 | 41 | for e = 1 : size(elements, 1) 42 | % Get the node indices 43 | node1Index = elements(e, 1); 44 | node2Index = elements(e, 2); 45 | 46 | % Get the nodal positions 47 | x1 = nodes(node1Index, 1); 48 | x2 = nodes(node2Index, 1); 49 | x_e = [x1; x2]; 50 | 51 | % Get the element properties (constant) 52 | E = elements(e, 3); 53 | A = elements(e, 4); 54 | 55 | % Get the nodal displacements 56 | u1 = u(gcon(node1Index, 1)); 57 | u2 = u(gcon(node2Index, 1)); 58 | u_e = [u1; u2]; 59 | 60 | % Evaluate the basis functions and their derivatives at 61 | % uniformly sampled points in the parent domain 62 | xi = linspace(-1, 1, numPoints + 1)'; 63 | N_e = eval_N(xi); 64 | B_e = eval_B(xi); 65 | 66 | % Find the corresponding points in the physical domain 67 | x = N_e * x_e; 68 | 69 | % Evaluate the Jacobian at the points 70 | J = B_e * x_e; 71 | 72 | % Evaluate the displacement and force fields 73 | u_h = N_e * u_e; 74 | f_h = E*A * (B_e * u_e) ./ J; 75 | 76 | % Plot the displacement and force fields 77 | subplot(1, 2, 1); 78 | h(i) = plot(x, u_h, '-', 'Color', problem_color(i, :), 'LineWidth', 2); hold on; 79 | plot(x1, u_h(1), 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 6); hold on; 80 | plot(x2, u_h(numPoints + 1), 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 6); hold on; 81 | 82 | subplot(1, 2, 2); 83 | h(i + 4) = plot(x, f_h, '-', 'Color', problem_color(i, :), 'LineWidth', 2); hold on; 84 | plot(x1, f_h(1), 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 6); hold on; 85 | plot(x2, f_h(numPoints + 1), 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 6); hold on; 86 | end 87 | 88 | subplot(1, 2, 1); 89 | title('Displacement (p = 1)', 'FontSize', 30); 90 | xlabel('x', 'FontSize', 30); 91 | ylabel('u_h', 'FontSize', 30, 'Rotation', 0); 92 | legend(h(1:i), problem_legend{1:i}, 'FontSize', 24, 'Location', 'SouthWest'); 93 | axis([0 4 0e-5 2e-5]); 94 | axis square; 95 | grid on; 96 | set(gca, 'FontSize', 24, 'XTick', linspace(0, 4, 9), 'YTick', linspace(0e-5, 2e-5, 9)); 97 | 98 | subplot(1, 2, 2); 99 | title('Internal force (p = 1)', 'FontSize', 30); 100 | xlabel('x', 'FontSize', 30); 101 | ylabel('F_h', 'FontSize', 30, 'Rotation', 0); 102 | legend(h((1:i) + 4), problem_legend{1:i}, 'FontSize', 24, 'Location', 'SouthWest'); 103 | axis([0 4 -1.6e5 -0.8e5]); 104 | axis square; 105 | grid on; 106 | set(gca, 'FontSize', 24, 'XTick', linspace(0, 4, 9), 'YTick', linspace(-1.6e5, -0.8e5, 9)); 107 | 108 | pause; 109 | end 110 | end -------------------------------------------------------------------------------- /bar_problem/driver_p2.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: Isaac J. Lee 3 | % E-mail: ijlee2@ices.utexas.edu 4 | % 5 | % This driver calls the assembly routine to solve the bar problem with a 6 | % Winkler foundation for 1, 2, 4, 8 elements with a quadratic basis. 7 | % It then plots the FE displacement and force fields for comparison. 8 | %-------------------------------------------------------------------------- 9 | function driver_p2() 10 | clc; clf; 11 | clear all; close all; 12 | format long; 13 | 14 | % Parameters for plotting 15 | numPoints = 1000; 16 | problem_size = {'01'; '02'; '04'; '08'}; 17 | problem_color = [0.7, 0.35, 0.45; ... 18 | 0.8, 0.75, 0.3; ... 19 | 0.4, 0.75, 0.55; ... 20 | 0.4, 0.7, 0.9]; 21 | problem_legend = {'1 element'; '2 elements'; '4 elements'; '8 elements'}; 22 | 23 | % Specify the basis functions and their derivatives 24 | eval_N = @(xi) [1/2*xi.^2 - 1/2*xi, ... 25 | -xi.^2 + 1, ... 26 | 1/2*xi.^2 + 1/2*xi]; 27 | eval_B = @(xi) [xi - 1/2, ... 28 | -2*xi, ... 29 | xi + 1/2]; 30 | 31 | 32 | %---------------------------------------------------------------------- 33 | % Begin solving the problem 34 | %---------------------------------------------------------------------- 35 | for i = 1 : size(problem_size, 1) 36 | % Solve the bar problem 37 | assembly_1dbar_p2(problem_size{i}); 38 | 39 | % Load the assembly and solution files 40 | load(strcat('assembly_files/assembly_1dbar_p2_numElements', problem_size{i}), 'nodes', 'elements'); 41 | load(strcat('solution_files/solution_1dbar_p2_numElements', problem_size{i}), 'u', 'gcon'); 42 | 43 | for e = 1 : size(elements, 1) 44 | % Get the node indices 45 | node1Index = elements(e, 1); 46 | node2Index = elements(e, 2); 47 | node3Index = elements(e, 3); 48 | 49 | % Get the nodal positions 50 | x1 = nodes(node1Index, 1); 51 | x2 = nodes(node2Index, 1); 52 | x3 = nodes(node3Index, 1); 53 | x_e = [x1; x2; x3]; 54 | 55 | % Get the element properties (constant) 56 | E = elements(e, 4); 57 | A = elements(e, 5); 58 | 59 | % Get the nodal displacements 60 | u1 = u(gcon(node1Index, 1)); 61 | u2 = u(gcon(node2Index, 1)); 62 | u3 = u(gcon(node3Index, 1)); 63 | u_e = [u1; u2; u3]; 64 | 65 | % Evaluate the basis functions and their derivatives at 66 | % uniformly sampled points in the parent domain 67 | xi = linspace(-1, 1, numPoints + 1)'; 68 | N_e = eval_N(xi); 69 | B_e = eval_B(xi); 70 | 71 | % Find the corresponding points in the physical domain 72 | x = N_e * x_e; 73 | 74 | % Evaluate the Jacobian at the points 75 | J = B_e * x_e; 76 | 77 | % Evaluate the displacement and force fields 78 | u_h = N_e * u_e; 79 | f_h = E*A * (B_e * u_e) ./ J; 80 | 81 | % Plot the displacement and force fields 82 | subplot(1, 2, 1); 83 | h(i) = plot(x, u_h, '-', 'Color', problem_color(i, :), 'LineWidth', 2); hold on; 84 | plot(x1, u_h(1), 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 6); hold on; 85 | plot(x3, u_h(numPoints + 1), 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 6); hold on; 86 | 87 | subplot(1, 2, 2); 88 | h(i + 4) = plot(x, f_h, '-', 'Color', problem_color(i, :), 'LineWidth', 2); hold on; 89 | plot(x1, f_h(1), 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 6); hold on; 90 | plot(x3, f_h(numPoints + 1), 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 6); hold on; 91 | end 92 | 93 | subplot(1, 2, 1); 94 | title('Displacement (p = 2)', 'FontSize', 30); 95 | xlabel('x', 'FontSize', 30); 96 | ylabel('u_h', 'FontSize', 30, 'Rotation', 0); 97 | legend(h(1:i), problem_legend{1:i}, 'FontSize', 24, 'Location', 'SouthWest'); 98 | axis([0 4 0e-5 2e-5]); 99 | axis square; 100 | grid on; 101 | set(gca, 'FontSize', 24, 'XTick', linspace(0, 4, 9), 'YTick', linspace(0e-5, 2e-5, 9)); 102 | 103 | subplot(1, 2, 2); 104 | title('Internal force (p = 2)', 'FontSize', 30); 105 | xlabel('x', 'FontSize', 30); 106 | ylabel('F_h', 'FontSize', 30, 'Rotation', 0); 107 | legend(h((1:i) + 4), problem_legend{1:i}, 'FontSize', 24, 'Location', 'SouthWest'); 108 | axis([0 4 -1.6e5 -0.8e5]); 109 | axis square; 110 | grid on; 111 | set(gca, 'FontSize', 24, 'XTick', linspace(0, 4, 9), 'YTick', linspace(-1.6e5, -0.8e5, 9)); 112 | 113 | pause; 114 | end 115 | end -------------------------------------------------------------------------------- /bar_problem/screenshots/1dbar_p1_numElements01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/screenshots/1dbar_p1_numElements01.png -------------------------------------------------------------------------------- /bar_problem/screenshots/1dbar_p1_numElements02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/screenshots/1dbar_p1_numElements02.png -------------------------------------------------------------------------------- /bar_problem/screenshots/1dbar_p1_numElements04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/screenshots/1dbar_p1_numElements04.png -------------------------------------------------------------------------------- /bar_problem/screenshots/1dbar_p1_numElements08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/screenshots/1dbar_p1_numElements08.png -------------------------------------------------------------------------------- /bar_problem/screenshots/1dbar_p2_numElements01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/screenshots/1dbar_p2_numElements01.png -------------------------------------------------------------------------------- /bar_problem/screenshots/1dbar_p2_numElements02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/screenshots/1dbar_p2_numElements02.png -------------------------------------------------------------------------------- /bar_problem/screenshots/1dbar_p2_numElements04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/screenshots/1dbar_p2_numElements04.png -------------------------------------------------------------------------------- /bar_problem/screenshots/1dbar_p2_numElements08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/screenshots/1dbar_p2_numElements08.png -------------------------------------------------------------------------------- /bar_problem/solution_files/solution_1dbar_p1_numElements01.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/solution_files/solution_1dbar_p1_numElements01.mat -------------------------------------------------------------------------------- /bar_problem/solution_files/solution_1dbar_p1_numElements02.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/solution_files/solution_1dbar_p1_numElements02.mat -------------------------------------------------------------------------------- /bar_problem/solution_files/solution_1dbar_p1_numElements04.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/solution_files/solution_1dbar_p1_numElements04.mat -------------------------------------------------------------------------------- /bar_problem/solution_files/solution_1dbar_p1_numElements08.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/solution_files/solution_1dbar_p1_numElements08.mat -------------------------------------------------------------------------------- /bar_problem/solution_files/solution_1dbar_p2_numElements01.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/solution_files/solution_1dbar_p2_numElements01.mat -------------------------------------------------------------------------------- /bar_problem/solution_files/solution_1dbar_p2_numElements02.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/solution_files/solution_1dbar_p2_numElements02.mat -------------------------------------------------------------------------------- /bar_problem/solution_files/solution_1dbar_p2_numElements04.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/solution_files/solution_1dbar_p2_numElements04.mat -------------------------------------------------------------------------------- /bar_problem/solution_files/solution_1dbar_p2_numElements08.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/bar_problem/solution_files/solution_1dbar_p2_numElements08.mat -------------------------------------------------------------------------------- /extras/Documentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/extras/Documentation.pdf -------------------------------------------------------------------------------- /extras/Notes_020315.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/extras/Notes_020315.pdf -------------------------------------------------------------------------------- /extras/convertAssemblyFile.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: Isaac J. Lee 3 | % E-mail: ijlee2@ices.utexas.edu 4 | % 5 | % This routine reads the assembly files provided by Dr. Landis, and 6 | % converts them into the .mat file format that we had used for truss 7 | % and frame problems. The .mat file contains four arrays called nodes, 8 | % elements, BCs_displacement, and BCs_force. 9 | % 10 | % The .bin files are assumed to be in the same directory as this routine, 11 | % and the .mat file will be created in this directory. 12 | % 13 | % To run this routine, type into Matlab's command window, 14 | % convertAssemblyFile(problem) 15 | % where 16 | % problem = 1, 2, 3, or 4 17 | %-------------------------------------------------------------------------- 18 | function convertAssemblyFile(problem) 19 | clc; 20 | 21 | switch problem 22 | case 1 23 | fileName = '6'; 24 | case 2 25 | fileName = '12'; 26 | case 3 27 | fileName = '24'; 28 | case 4 29 | fileName = 'R'; 30 | end 31 | 32 | 33 | %---------------------------------------------------------------------- 34 | % Create the nodes array 35 | % (x, y) 36 | %---------------------------------------------------------------------- 37 | fileID = fopen(strcat('nodes', fileName), 'r'); 38 | numNodes = str2num(fgetl(fileID)); 39 | numDOFsPerNode = 2; 40 | numDOFs = numDOFsPerNode*numNodes; 41 | 42 | % Initialize the nodes array 43 | nodes = zeros(numNodes, 2); 44 | 45 | for i = 1 : numNodes 46 | temp = str2num(fgetl(fileID)); 47 | 48 | % x-coordinate 49 | nodes(i, 1) = temp(2); 50 | 51 | % y-coordinate 52 | nodes(i, 2) = temp(3); 53 | end 54 | 55 | fclose(fileID); 56 | 57 | 58 | %---------------------------------------------------------------------- 59 | % Create the elements array 60 | % (node 1 index, node 2 index, node 3 index, E, nu) 61 | %---------------------------------------------------------------------- 62 | fileID = fopen(strcat('elements', fileName), 'r'); 63 | temp = str2num(fgetl(fileID)); 64 | numElements = temp(1); 65 | % E = temp(2); 66 | E = 50; 67 | nu = temp(3); 68 | 69 | % Initialize the elements array 70 | elements = zeros(numElements, 5); 71 | 72 | for i = 1 : numElements 73 | temp = str2num(fgetl(fileID)); 74 | 75 | % node 1 index 76 | elements(i, 1) = temp(2); 77 | 78 | % node 2 index 79 | elements(i, 2) = temp(3); 80 | 81 | % node 3 index 82 | elements(i, 3) = temp(4); 83 | end 84 | 85 | % Young's modulus 86 | elements(:, 4) = E * ones(numElements, 1); 87 | 88 | % Poisson's ratio 89 | elements(:, 5) = nu * ones(numElements, 1); 90 | 91 | fclose(fileID); 92 | 93 | 94 | %---------------------------------------------------------------------- 95 | % Create the BCs_displacement array 96 | % (node index, dof index, value) 97 | %---------------------------------------------------------------------- 98 | fileID = fopen(strcat('displacements', fileName), 'r'); 99 | numBCs_displacement = str2num(fgetl(fileID)); 100 | 101 | % Initialize the BCs_displacement array 102 | BCs_displacement = zeros(numBCs_displacement, 3); 103 | 104 | for i = 1 : numBCs_displacement 105 | temp = str2num(fgetl(fileID)); 106 | 107 | % node index 108 | BCs_displacement(i, 1) = temp(1); 109 | 110 | % dof index 111 | BCs_displacement(i, 2) = temp(2); 112 | 113 | % value 114 | BCs_displacement(i, 3) = temp(3); 115 | end 116 | 117 | fclose(fileID); 118 | 119 | 120 | %---------------------------------------------------------------------- 121 | % Create the BCs_force array 122 | % (node index, dof index, value) 123 | %---------------------------------------------------------------------- 124 | fileID = fopen(strcat('forces', fileName), 'r'); 125 | numBCs_force = str2num(fgetl(fileID)); 126 | 127 | % Initialize the BCs_force array 128 | BCs_force = zeros(numDOFs - numBCs_displacement, 3); 129 | 130 | % The forces.bin file only lists the nodal forces with nonzero values. 131 | % However, it is easier if we list all nodal forces, and set to zero 132 | % if there was no applied force at a node in a given direction. 133 | count = 1; 134 | for i = 1 : numNodes 135 | for j = 1 : numDOFsPerNode 136 | % Consider applying a zero nodal force only if we did not 137 | % prescribe a displacement BC already 138 | if (sum(ismember(BCs_displacement(:, [1 2]), [i j], 'rows')) == 0) 139 | BCs_force(count, 1) = i; 140 | BCs_force(count, 2) = j; 141 | BCs_force(count, 3) = 0; 142 | 143 | count = count + 1; 144 | end 145 | end 146 | end 147 | 148 | if ((numDOFs - numBCs_displacement) ~= (count - 1)) 149 | fprintf('Warning: Please check this part of the code.\n'); 150 | end 151 | 152 | % Prescribe the nodal forces with nonzero values 153 | for i = 1 : numBCs_force 154 | temp = str2num(fgetl(fileID)); 155 | 156 | % Find the right row 157 | count = find(ismember(BCs_force(:, [1 2]), [temp(1) temp(2)], 'rows') == 1); 158 | 159 | BCs_force(count, 3) = temp(3); 160 | end 161 | 162 | fclose(fileID); 163 | 164 | 165 | %---------------------------------------------------------------------- 166 | % Create the .mat assembly file 167 | %---------------------------------------------------------------------- 168 | save(strcat('assembly', fileName, '.mat'), 'nodes', 'elements', 'BCs_displacement', 'BCs_force', '-v6'); 169 | end -------------------------------------------------------------------------------- /extras/draw_frame.m: -------------------------------------------------------------------------------- 1 | function draw_frame(nodes, elements, u, gcon) 2 | close all; 3 | 4 | % Number of elements 5 | numElements = size(elements, 1); 6 | 7 | % Number of points between two nodes 8 | numPoints = 1000; 9 | 10 | % Draw the undeformed structure first 11 | for i = 1 : numElements 12 | % Get the node indices 13 | nodeIndex1 = elements(i, 1); 14 | nodeIndex2 = elements(i, 2); 15 | 16 | % Get the nodal positions in the global coordinates 17 | x1 = nodes(nodeIndex1, 1); 18 | y1 = nodes(nodeIndex1, 2); 19 | x2 = nodes(nodeIndex2, 1); 20 | y2 = nodes(nodeIndex2, 2); 21 | 22 | % Set the initial positions 23 | x = linspace(x1, x2, numPoints + 1); 24 | y = linspace(y1, y2, numPoints + 1); 25 | 26 | % Draw the undeformed element 27 | plot(x, y, 'Color', [0.8 0.9 0.75], 'LineWidth', 2); hold on; 28 | 29 | % Draw the nodes 30 | plot(x1, y1, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 31 | plot(x2, y2, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 32 | end 33 | 34 | % Draw the deformed structure next 35 | for i = 1 : numElements 36 | % Get the node indices 37 | nodeIndex1 = elements(i, 1); 38 | nodeIndex2 = elements(i, 2); 39 | 40 | % Get the nodal positions in the global coordinates 41 | x1 = nodes(nodeIndex1, 1); 42 | y1 = nodes(nodeIndex1, 2); 43 | x2 = nodes(nodeIndex2, 1); 44 | y2 = nodes(nodeIndex2, 2); 45 | 46 | % Initialize the final positions 47 | x = linspace(x1, x2, numPoints + 1)'; 48 | y = linspace(y1, y2, numPoints + 1)'; 49 | 50 | % Get the material properties 51 | E = elements(i, 3); 52 | A = elements(i, 4); 53 | I = elements(i, 5); 54 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 55 | 56 | % Calculate the cosine and sine values 57 | costhetaAx = (x2 - x1)/L; 58 | costhetaAy = (y2 - y1)/L; 59 | costhetaTx = -costhetaAy; 60 | costhetaTy = costhetaAx; 61 | 62 | % Get the DOF indices 63 | index = [gcon(nodeIndex1, 1); ... 64 | gcon(nodeIndex1, 2); ... 65 | gcon(nodeIndex1, 3); ... 66 | gcon(nodeIndex2, 1); ... 67 | gcon(nodeIndex2, 2); ... 68 | gcon(nodeIndex2, 3)]; 69 | 70 | % Get the nodal displacements in the global coordinates 71 | u1x = u(index(1)); 72 | u1y = u(index(2)); 73 | theta1 = u(index(3)); 74 | u2x = u(index(4)); 75 | u2y = u(index(5)); 76 | theta2 = u(index(6)); 77 | 78 | % Calculuate the nodal displacements in the local coordinates 79 | % (the rotation DOFs remain the same) 80 | u1A = u1x * costhetaAx + u1y * costhetaAy; 81 | u1T = u1x * costhetaTx + u1y * costhetaTy; 82 | u2A = u2x * costhetaAx + u2y * costhetaAy; 83 | u2T = u2x * costhetaTx + u2y * costhetaTy; 84 | 85 | % For convenience, normalize the axial coordinate 86 | x_local = linspace(0, L, numPoints + 1)'; 87 | x_local = x_local / L; 88 | 89 | % Find the axial displacement of the bar 90 | u_h = u1A*(1 - x_local) + u2A*x_local; 91 | 92 | % Find the transversal displacement of the bar 93 | v_h = u1T*(2*x_local.^3 - 3*x_local.^2 + 1) + theta1*(x_local.^3 - 2*x_local.^2 + x_local)/L + u2T*(-2*x_local.^3 + 3*x_local.^2) + theta2*(x_local.^3 - x_local.^2)/L; 94 | 95 | % Find the x- and y-displacements of the bar 96 | ux_h = u_h * costhetaAx + v_h * costhetaTx; 97 | uy_h = u_h * costhetaAy + v_h * costhetaTy; 98 | 99 | % Find the final positions 100 | x = x + ux_h; 101 | y = y + uy_h; 102 | 103 | % Draw the deformed element 104 | plot(x, y, 'Color', [0.7 0.3 0.3], 'LineWidth', 2); hold on; 105 | 106 | % Draw the nodes 107 | plot(x1 + ux_h(1), y1 + uy_h(1), 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 108 | plot(x2 + ux_h(numPoints + 1), y2 + uy_h(numPoints + 1), 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 109 | end 110 | end -------------------------------------------------------------------------------- /extras/draw_truss.m: -------------------------------------------------------------------------------- 1 | function draw_truss(nodes, elements, u, gcon) 2 | close all; 3 | 4 | % Number of elements 5 | numElements = size(elements, 1); 6 | 7 | % Draw the undeformed structure first 8 | for i = 1 : numElements 9 | % Get the node indices 10 | nodeIndex1 = elements(i, 1); 11 | nodeIndex2 = elements(i, 2); 12 | 13 | % Get the nodal positions in the global coordinates 14 | x1 = nodes(nodeIndex1, 1); 15 | y1 = nodes(nodeIndex1, 2); 16 | x2 = nodes(nodeIndex2, 1); 17 | y2 = nodes(nodeIndex2, 2); 18 | 19 | % Draw the undeformed element 20 | line([x1 x2], [y1 y2], 'Color', [0.8 0.9 0.75], 'LineWidth', 2); hold on; 21 | 22 | % Draw the nodes 23 | plot(x1, y1, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 24 | plot(x2, y2, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 25 | end 26 | 27 | % Draw the deformed structure next 28 | for i = 1 : numElements 29 | % Get the node indices 30 | nodeIndex1 = elements(i, 1); 31 | nodeIndex2 = elements(i, 2); 32 | 33 | % Get the nodal positions in the global coordinates 34 | x1 = nodes(nodeIndex1, 1); 35 | y1 = nodes(nodeIndex1, 2); 36 | x2 = nodes(nodeIndex2, 1); 37 | y2 = nodes(nodeIndex2, 2); 38 | 39 | % Get the DOF indices 40 | index = [gcon(nodeIndex1, 1); ... 41 | gcon(nodeIndex1, 2); ... 42 | gcon(nodeIndex2, 1); ... 43 | gcon(nodeIndex2, 2)]; 44 | 45 | % Get the nodal displacements in the global coordinates 46 | u1x = u(index(1)); 47 | u1y = u(index(2)); 48 | u2x = u(index(3)); 49 | u2y = u(index(4)); 50 | 51 | % Draw the deformed element 52 | line([x1 + u1x, x2 + u2x], [y1 + u1y, y2 + u2y], 'Color', [0.7 0.3 0.3], 'LineWidth', 2); hold on; 53 | 54 | % Draw the nodes 55 | plot(x1 + u1x, y1 + u1y, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 56 | plot(x2 + u2x, y2 + u2y, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 57 | end 58 | end -------------------------------------------------------------------------------- /frame_2d/2dframe_problem1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/frame_2d/2dframe_problem1.mat -------------------------------------------------------------------------------- /frame_2d/2dframe_problem1_alt.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/frame_2d/2dframe_problem1_alt.mat -------------------------------------------------------------------------------- /frame_2d/assembly_2dframe.m: -------------------------------------------------------------------------------- 1 | function [u, f, strain_axial, force_axial, gcon] = assembly_2dframe() 2 | clc; 3 | format long; 4 | 5 | % Load the assembly file 6 | load('2dframe_problem1_alt'); 7 | 8 | % Find the number of nodes, etc. 9 | numNodes = size(nodes, 1); 10 | numElements = size(elements, 1); 11 | numBCs_displacement = size(BCs_displacement, 1); 12 | numBCs_force = size(BCs_force, 1); 13 | 14 | % Find the number of degrees of freedom (DOFs) for a 2D frame 15 | % Note, numBCs_displacement + numBCs_force = numDOFs 16 | numDOFs = 3*numNodes; 17 | 18 | 19 | %---------------------------------------------------------------------- 20 | % Set up the global connectivity array called gcon, which returns the 21 | % global DOF index when given the node index and the local DOF index. 22 | % 23 | % Initially, gcon is a (numNodes) x 3 double array with these entries: 24 | % 25 | % local dof index 26 | % 27 | % 1 (u_x) 2 (u_y) 3 (theta) 28 | % 29 | % node 1 1 2 3 30 | % index 2 4 5 6 31 | % 3 7 8 9 32 | % ... ... ... 33 | % numNodes (3*numNodes - 2) (3*numNodes - 1) (3*numNodes) 34 | % 35 | % We plan to have the bottom entries of the DOF vector u correspond 36 | % to the displacement and rotation DOFs that are already known. 37 | % So we do not actually create gcon with the entries above just yet, 38 | % but assume its existence. 39 | % 40 | % First, create a vector that tags all global DOF indices corresponding 41 | % to the displacement BCs. As the number of displacement BCs is likely 42 | % few in comparison to the total number of DOFs, we let the vector be 43 | % a sparse vector. 44 | %---------------------------------------------------------------------- 45 | tag = sparse(BCs_displacement(:, 1), BCs_displacement(:, 2), ones(numBCs_displacement, 1), numNodes, 3); 46 | tag = reshape(tag', numDOFs, 1); 47 | 48 | %---------------------------------------------------------------------- 49 | % tag is now a vector of zeros and ones, where the ones correspond to 50 | % to the displacement BCs. Sort this vector in ascending order, and 51 | % keep track of the permutation that was done. 52 | %---------------------------------------------------------------------- 53 | [temp, permutation] = sort(tag); 54 | 55 | %---------------------------------------------------------------------- 56 | % Create the gcon array 57 | %---------------------------------------------------------------------- 58 | gcon(permutation) = (1 : numDOFs)'; 59 | gcon = reshape(gcon, 3, numNodes)' 60 | 61 | % Indices corresponding to the unknown displacements and rotations, i.e. 62 | % to the known forces and moments 63 | index_u = (1 : numBCs_force)'; 64 | 65 | % Indices corresponding to the unknown forces and moment, i.e. to the 66 | % known displacements and rotations 67 | index_f = ((numBCs_force + 1) : numDOFs)'; 68 | 69 | 70 | %---------------------------------------------------------------------- 71 | % Create the global stiffness matrix K 72 | %---------------------------------------------------------------------- 73 | % Each element matrix is 6 x 6, so there are (36*numElements) many elements 74 | % that we will need to compute to find the global stiffness matrix K 75 | numEntries = 36*numElements; 76 | 77 | % Initialize the I, J, value arrays 78 | I_temp = zeros(numEntries, 1); 79 | J_temp = zeros(numEntries, 1); 80 | value = zeros(numEntries, 1); 81 | 82 | % Temporary variables useful for assembly 83 | i = (1 : 36)'; 84 | vecones = ones(6, 1); 85 | 86 | %---------------------------------------------------------------------- 87 | % Loop over the elements 88 | %---------------------------------------------------------------------- 89 | for e = 1 : numElements 90 | % Get the node indices 91 | nodeIndex1 = elements(e, 1); 92 | nodeIndex2 = elements(e, 2); 93 | 94 | % Get the global DOF indices 95 | globalDOFIndex = [gcon(nodeIndex1, 1); ... 96 | gcon(nodeIndex1, 2); ... 97 | gcon(nodeIndex1, 3); ... 98 | gcon(nodeIndex2, 1); ... 99 | gcon(nodeIndex2, 2); ... 100 | gcon(nodeIndex2, 3)]; 101 | 102 | % Get the global coordinates of the nodes 103 | x1 = nodes(nodeIndex1, 1); 104 | y1 = nodes(nodeIndex1, 2); 105 | x2 = nodes(nodeIndex2, 1); 106 | y2 = nodes(nodeIndex2, 2); 107 | 108 | % Get the material properties 109 | E = elements(e, 3); 110 | A = elements(e, 4); 111 | I = elements(e, 5); 112 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 113 | 114 | % Calculate the directional cosines 115 | costhetaAx = (x2 - x1)/L; 116 | costhetaAy = (y2 - y1)/L; 117 | costhetaTx = -costhetaAy; 118 | costhetaTy = costhetaAx; 119 | 120 | % Calculate the local-to-global coordinate transformation matrix 121 | Q = [costhetaAx, costhetaAy, 0; 122 | costhetaTx, costhetaTy, 0; 123 | 0, 0, 1]; 124 | 125 | %------------------------------------------------------------------ 126 | % Form the element matrix 127 | %------------------------------------------------------------------ 128 | % Element matrix in local coordinates 129 | K_e = [ E*A/L, 0, 0, -E*A/L, 0, 0; ... 130 | 0, 12*E*I/L^3, 6*E*I/L^2, 0, -12*E*I/L^3, 6*E*I/L^2; ... 131 | 0, 6*E*I/L^2, 4*E*I/L, 0, -6*E*I/L^2, 2*E*I/L; ... 132 | -E*A/L, 0, 0, E*A/L, 0, 0; ... 133 | 0, -12*E*I/L^3, -6*E*I/L^2, 0, 12*E*I/L^3, -6*E*I/L^2; ... 134 | 0, 6*E*I/L^2, 2*E*I/L, 0, -6*E*I/L^2, 4*E*I/L]; 135 | 136 | % Apply coordinate transformation 137 | K_e(1:3, 1:3) = Q' * K_e(1:3, 1:3) * Q; 138 | K_e(1:3, 4:6) = Q' * K_e(1:3, 4:6) * Q; 139 | K_e(4:6, 1:3) = Q' * K_e(4:6, 1:3) * Q; 140 | K_e(4:6, 4:6) = Q' * K_e(4:6, 4:6) * Q; 141 | 142 | %------------------------------------------------------------------ 143 | % Global assembly 144 | %------------------------------------------------------------------ 145 | I_temp(i) = kron(globalDOFIndex, vecones); 146 | J_temp(i) = kron(vecones, globalDOFIndex); 147 | value(i) = reshape(K_e, 36, 1); 148 | i = i + 36; 149 | end 150 | 151 | K = sparse(I_temp, J_temp, value, numDOFs, numDOFs); 152 | clear I_temp J_temp value K_e temp vecones; 153 | 154 | %---------------------------------------------------------------------- 155 | % Solve for the unknown displacements and forces 156 | %---------------------------------------------------------------------- 157 | % Initialize the solution vector and the RHS external force vector 158 | u = zeros(numDOFs, 1); 159 | f = zeros(numDOFs, 1); 160 | 161 | % Prescribe the displacements 162 | u(index_f) = BCs_displacement(:, 3); 163 | 164 | % Prescribe the nodal forces 165 | f(index_u) = BCs_force(:, 3); 166 | 167 | % Solve for the unknown displacements 168 | u(index_u) = K(index_u, index_u) \ (f(index_u) - K(index_u, index_f) * u(index_f)); 169 | 170 | % Solve for the unknown nodal forces 171 | f(index_f) = K(index_f, :) * u; 172 | 173 | 174 | %---------------------------------------------------------------------- 175 | % Post-process 176 | %---------------------------------------------------------------------- 177 | draw_frame(nodes, elements, u, gcon); 178 | 179 | u(permutation) = u; 180 | f(permutation) = f; 181 | end -------------------------------------------------------------------------------- /frame_2d/assembly_2dtruss.m: -------------------------------------------------------------------------------- 1 | function [u, f, strain_axial, force_axial, gcon] = assembly_2dtruss() 2 | clc; 3 | format long; 4 | 5 | % Load the assembly file 6 | load('2dframe_problem1'); 7 | 8 | % Eliminate the rotation BCs 9 | index = find(BCs_displacement(:, 2) ~= 3); 10 | BCs_displacement = BCs_displacement(index, :); 11 | 12 | % Eliminate the moment BCs 13 | index = find(BCs_force(:, 2) ~= 3); 14 | BCs_force = BCs_force(index, :); 15 | 16 | % Find the number of nodes, etc. 17 | numNodes = size(nodes, 1); 18 | numElements = size(elements, 1); 19 | numBCs_displacement = size(BCs_displacement, 1); 20 | numBCs_force = size(BCs_force, 1); 21 | 22 | % Find the number of degrees of freedom (DOFs) for a truss 23 | % Note, numBCs_displacement + numBCs_force = numDOFs 24 | numDOFs = 2*numNodes; 25 | 26 | 27 | %---------------------------------------------------------------------- 28 | % Set up the global connectivity array called gcon, which returns the 29 | % global DOF index when given the node index and the local DOF index. 30 | % 31 | % Initially, gcon is a (numNodes) x 2 double array with these entries: 32 | % 33 | % local dof index 34 | % 35 | % 1 2 36 | % 37 | % node 1 1 2 38 | % index 2 3 4 39 | % 3 5 6 40 | % ... ... ... 41 | % numNodes (2*numNodes - 1) (2*numNodes) 42 | % 43 | % We plan to have the bottom entries of the DOF vector u correspond 44 | % to the DOFs that are already known (given as the displacement BCs). 45 | % So we do not actually create gcon with the entries above just yet, 46 | % but assume its existence. 47 | % 48 | % First, create a vector that tags all global DOF indices corresponding 49 | % to the displacement BCs. As the number of displacement BCs is likely 50 | % few in comparison to the total number of DOFs, we let the vector be 51 | % a sparse vector. 52 | %---------------------------------------------------------------------- 53 | tag = sparse(BCs_displacement(:, 1), BCs_displacement(:, 2), ones(numBCs_displacement, 1), numNodes, 2); 54 | tag = reshape(tag', numDOFs, 1); 55 | 56 | %---------------------------------------------------------------------- 57 | % tag is now a vector of zeros and ones, where the ones correspond to 58 | % to the displacement BCs. Sort this vector in ascending order, and 59 | % keep track of the permutation that was done. 60 | %---------------------------------------------------------------------- 61 | [temp, permutation] = sort(tag); 62 | 63 | %---------------------------------------------------------------------- 64 | % Create the gcon array 65 | %---------------------------------------------------------------------- 66 | gcon(permutation) = (1 : numDOFs)'; 67 | gcon = reshape(gcon, 2, numNodes)'; 68 | 69 | % Indices corresponding to the unknown displacements (known forces) 70 | index_u = (1 : numBCs_force)'; 71 | 72 | % Vector of indices of the unknown forces (known displacements) 73 | index_f = ((numBCs_force + 1) : numDOFs)'; 74 | 75 | 76 | %---------------------------------------------------------------------- 77 | % Create the global stiffness matrix K 78 | %---------------------------------------------------------------------- 79 | % Each element matrix is 4 x 4, so there are (16*numElements) many elements 80 | % that we will need to compute to find the global stiffness matrix K 81 | numEntries = 16*numElements; 82 | 83 | % Initialize the I, J, value arrays 84 | I = zeros(numEntries, 1); 85 | J = zeros(numEntries, 1); 86 | value = zeros(numEntries, 1); 87 | 88 | % Temporary variables useful for assembly 89 | i = (1 : 16)'; 90 | vecones = ones(4, 1); 91 | 92 | %---------------------------------------------------------------------- 93 | % Loop over the elements 94 | %---------------------------------------------------------------------- 95 | for e = 1 : numElements 96 | % Get the node indices 97 | nodeIndex1 = elements(e, 1); 98 | nodeIndex2 = elements(e, 2); 99 | 100 | % Get the global DOF indices 101 | globalDOFIndex = [gcon(nodeIndex1, 1); ... 102 | gcon(nodeIndex1, 2); ... 103 | gcon(nodeIndex2, 1); ... 104 | gcon(nodeIndex2, 2)]; 105 | 106 | % Get the global coordinates of the nodes 107 | x1 = nodes(nodeIndex1, 1); 108 | y1 = nodes(nodeIndex1, 2); 109 | x2 = nodes(nodeIndex2, 1); 110 | y2 = nodes(nodeIndex2, 2); 111 | 112 | % Get the material properties 113 | E = elements(e, 3); 114 | A = elements(e, 4); 115 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 116 | 117 | % Calculate the cosine and sine values 118 | costheta = (x2 - x1)/L; 119 | sintheta = (y2 - y1)/L; 120 | 121 | %------------------------------------------------------------------ 122 | % Form the element matrix 123 | %------------------------------------------------------------------ 124 | temp = [costheta * costheta, costheta * sintheta; ... 125 | costheta * sintheta, sintheta * sintheta]; 126 | K_e = E*A/L * [ temp, -temp; ... 127 | -temp, temp]; 128 | 129 | %------------------------------------------------------------------ 130 | % Global assembly 131 | %------------------------------------------------------------------ 132 | I(i) = kron(globalDOFIndex, vecones); 133 | J(i) = kron(vecones, globalDOFIndex); 134 | value(i) = reshape(K_e, 16, 1); 135 | i = i + 16; 136 | end 137 | 138 | K = sparse(I, J, value, numDOFs, numDOFs); 139 | clear I J value K_e temp vecones; 140 | 141 | %---------------------------------------------------------------------- 142 | % Solve for the unknown displacements and forces 143 | %---------------------------------------------------------------------- 144 | % Initialize the solution vector and the RHS external force vector 145 | u = zeros(numDOFs, 1); 146 | f = zeros(numDOFs, 1); 147 | 148 | % Prescribe the displacements 149 | u(index_f) = BCs_displacement(:, 3); 150 | 151 | % Prescribe the nodal forces 152 | f(index_u) = BCs_force(:, 3); 153 | 154 | % Solve for the unknown displacements 155 | u(index_u) = K(index_u, index_u) \ (f(index_u) - K(index_u, index_f) * u(index_f)); 156 | 157 | % Solve for the unknown nodal forces 158 | f(index_f) = K(index_f, :) * u; 159 | 160 | 161 | %---------------------------------------------------------------------- 162 | % Post-process 163 | %---------------------------------------------------------------------- 164 | strain_axial = zeros(numElements, 1); 165 | force_axial = zeros(numElements, 1); 166 | 167 | figure; 168 | 169 | % Draw the undeformed structure first 170 | for i = 1 : numElements 171 | % Get the node indices 172 | nodeIndex1 = elements(i, 1); 173 | nodeIndex2 = elements(i, 2); 174 | 175 | % Get the global coordinates of the nodes 176 | x1 = nodes(nodeIndex1, 1); 177 | y1 = nodes(nodeIndex1, 2); 178 | x2 = nodes(nodeIndex2, 1); 179 | y2 = nodes(nodeIndex2, 2); 180 | 181 | % Draw the undeformed element 182 | line([x1 x2], [y1 y2], 'Color', [0.8 0.9 0.75], 'LineWidth', 2); hold on; 183 | 184 | plot(x1, y1, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 185 | plot(x2, y2, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 186 | end 187 | 188 | % Draw the deformed structure 189 | for i = 1 : numElements 190 | % Get the node indices 191 | nodeIndex1 = elements(i, 1); 192 | nodeIndex2 = elements(i, 2); 193 | 194 | % Get the global coordinates of the nodes 195 | x1 = nodes(nodeIndex1, 1); 196 | y1 = nodes(nodeIndex1, 2); 197 | x2 = nodes(nodeIndex2, 1); 198 | y2 = nodes(nodeIndex2, 2); 199 | 200 | % Get the material properties 201 | E = elements(i, 3); 202 | A = elements(i, 4); 203 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 204 | 205 | % Calculate the cosine and sine values 206 | costheta = (x2 - x1)/L; 207 | sintheta = (y2 - y1)/L; 208 | 209 | % Get the global DOF indices 210 | globalDOFIndex = [gcon(nodeIndex1, 1); ... 211 | gcon(nodeIndex1, 2); ... 212 | gcon(nodeIndex2, 1); ... 213 | gcon(nodeIndex2, 2)]; 214 | 215 | % Get the global displacements of the nodes 216 | scale_factor = 1; 217 | ux1 = scale_factor * u(globalDOFIndex(1)); 218 | uy1 = scale_factor * u(globalDOFIndex(2)); 219 | ux2 = scale_factor * u(globalDOFIndex(3)); 220 | uy2 = scale_factor * u(globalDOFIndex(4)); 221 | 222 | % Calculate the axial strain 223 | strain_axial(i) = (ux2 - ux1)/L * costheta + (uy2 - uy1)/L * sintheta; 224 | 225 | % Calculate the axial force 226 | force_axial(i) = E*A * strain_axial(i); 227 | 228 | % Draw the deformed element 229 | line([x1 + ux1, x2 + ux2], [y1 + uy1, y2 + uy2], 'Color', [0.7 0.3 0.3], 'LineWidth', 2); hold on; 230 | 231 | plot(x1 + ux1, y1 + uy1, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 232 | plot(x2 + ux2, y2 + uy2, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 233 | end 234 | 235 | draw_truss(nodes, elements, u, gcon); 236 | 237 | u(permutation) = u; 238 | f(permutation) = f; 239 | end 240 | -------------------------------------------------------------------------------- /frame_2d/draw_frame.m: -------------------------------------------------------------------------------- 1 | function draw_frame(nodes, elements, u, gcon) 2 | close all; 3 | 4 | % Number of elements 5 | numElements = size(elements, 1); 6 | 7 | % Number of points between two nodes 8 | numPoints = 1000; 9 | 10 | % Draw the undeformed structure first 11 | for i = 1 : numElements 12 | % Get the node indices 13 | nodeIndex1 = elements(i, 1); 14 | nodeIndex2 = elements(i, 2); 15 | 16 | % Get the nodal positions in the global coordinates 17 | x1 = nodes(nodeIndex1, 1); 18 | y1 = nodes(nodeIndex1, 2); 19 | x2 = nodes(nodeIndex2, 1); 20 | y2 = nodes(nodeIndex2, 2); 21 | 22 | % Set the initial positions 23 | x = linspace(x1, x2, numPoints + 1); 24 | y = linspace(y1, y2, numPoints + 1); 25 | 26 | % Draw the undeformed element 27 | plot(x, y, 'Color', [0.8 0.9 0.75], 'LineWidth', 2); hold on; 28 | 29 | % Draw the nodes 30 | plot(x1, y1, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 31 | plot(x2, y2, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 32 | end 33 | 34 | % Draw the deformed structure next 35 | for i = 1 : numElements 36 | % Get the node indices 37 | nodeIndex1 = elements(i, 1); 38 | nodeIndex2 = elements(i, 2); 39 | 40 | % Get the nodal positions in the global coordinates 41 | x1 = nodes(nodeIndex1, 1); 42 | y1 = nodes(nodeIndex1, 2); 43 | x2 = nodes(nodeIndex2, 1); 44 | y2 = nodes(nodeIndex2, 2); 45 | 46 | % Initialize the final positions 47 | x = linspace(x1, x2, numPoints + 1)'; 48 | y = linspace(y1, y2, numPoints + 1)'; 49 | 50 | % Get the bar's length 51 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 52 | 53 | % Calculate the cosine and sine values 54 | costhetaAx = (x2 - x1)/L; 55 | costhetaAy = (y2 - y1)/L; 56 | costhetaTx = -costhetaAy; 57 | costhetaTy = costhetaAx; 58 | 59 | % Get the DOF indices 60 | index = [gcon(nodeIndex1, 1); ... 61 | gcon(nodeIndex1, 2); ... 62 | gcon(nodeIndex1, 3); ... 63 | gcon(nodeIndex2, 1); ... 64 | gcon(nodeIndex2, 2); ... 65 | gcon(nodeIndex2, 3)]; 66 | 67 | % Get the nodal displacements in the global coordinates 68 | u1x = u(index(1)); 69 | u1y = u(index(2)); 70 | theta1 = u(index(3)); 71 | u2x = u(index(4)); 72 | u2y = u(index(5)); 73 | theta2 = u(index(6)); 74 | 75 | % Calculuate the nodal displacements in the local coordinates 76 | % (the rotation DOFs remain the same) 77 | u1A = u1x * costhetaAx + u1y * costhetaAy; 78 | u1T = u1x * costhetaTx + u1y * costhetaTy; 79 | u2A = u2x * costhetaAx + u2y * costhetaAy; 80 | u2T = u2x * costhetaTx + u2y * costhetaTy; 81 | 82 | % For convenience, normalize the axial coordinate 83 | x_local = linspace(0, L, numPoints + 1)'; 84 | x_local = x_local / L; 85 | 86 | % Find the axial displacement of the bar 87 | u_h = u1A*(1 - x_local) + u2A*x_local; 88 | 89 | % Find the transversal displacement of the bar 90 | v_h = u1T*(2*x_local.^3 - 3*x_local.^2 + 1) + theta1*(x_local.^3 - 2*x_local.^2 + x_local)/L + u2T*(-2*x_local.^3 + 3*x_local.^2) + theta2*(x_local.^3 - x_local.^2)/L; 91 | 92 | % Find the x- and y-displacements of the bar 93 | ux_h = u_h * costhetaAx + v_h * costhetaTx; 94 | uy_h = u_h * costhetaAy + v_h * costhetaTy; 95 | 96 | % Find the final positions 97 | x = x + ux_h; 98 | y = y + uy_h; 99 | 100 | % Draw the deformed element 101 | plot(x, y, 'Color', [0.7 0.3 0.3], 'LineWidth', 2); hold on; 102 | 103 | % Draw the nodes 104 | plot(x1 + ux_h(1), y1 + uy_h(1), 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 105 | plot(x2 + ux_h(numPoints + 1), y2 + uy_h(numPoints + 1), 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 106 | end 107 | end -------------------------------------------------------------------------------- /frame_2d/draw_truss.m: -------------------------------------------------------------------------------- 1 | function draw_truss(nodes, elements, u, gcon) 2 | close all; 3 | 4 | % Number of elements 5 | numElements = size(elements, 1); 6 | 7 | % Draw the undeformed structure first 8 | for i = 1 : numElements 9 | % Get the node indices 10 | nodeIndex1 = elements(i, 1); 11 | nodeIndex2 = elements(i, 2); 12 | 13 | % Get the nodal positions in the global coordinates 14 | x1 = nodes(nodeIndex1, 1); 15 | y1 = nodes(nodeIndex1, 2); 16 | x2 = nodes(nodeIndex2, 1); 17 | y2 = nodes(nodeIndex2, 2); 18 | 19 | % Draw the undeformed element 20 | line([x1 x2], [y1 y2], 'Color', [0.8 0.9 0.75], 'LineWidth', 2); hold on; 21 | 22 | % Draw the nodes 23 | plot(x1, y1, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 24 | plot(x2, y2, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 25 | end 26 | 27 | % Draw the deformed structure next 28 | for i = 1 : numElements 29 | % Get the node indices 30 | nodeIndex1 = elements(i, 1); 31 | nodeIndex2 = elements(i, 2); 32 | 33 | % Get the nodal positions in the global coordinates 34 | x1 = nodes(nodeIndex1, 1); 35 | y1 = nodes(nodeIndex1, 2); 36 | x2 = nodes(nodeIndex2, 1); 37 | y2 = nodes(nodeIndex2, 2); 38 | 39 | % Get the DOF indices 40 | index = [gcon(nodeIndex1, 1); ... 41 | gcon(nodeIndex1, 2); ... 42 | gcon(nodeIndex2, 1); ... 43 | gcon(nodeIndex2, 2)]; 44 | 45 | % Get the nodal displacements in the global coordinates 46 | u1x = u(index(1)); 47 | u1y = u(index(2)); 48 | u2x = u(index(3)); 49 | u2y = u(index(4)); 50 | 51 | % Draw the deformed element 52 | line([x1 + u1x, x2 + u2x], [y1 + u1y, y2 + u2y], 'Color', [0.7 0.3 0.3], 'LineWidth', 2); hold on; 53 | 54 | % Draw the nodes 55 | plot(x1 + u1x, y1 + u1y, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 56 | plot(x2 + u2x, y2 + u2y, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 57 | end 58 | end -------------------------------------------------------------------------------- /plate_problem/HW #10.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/HW #10.xlsx -------------------------------------------------------------------------------- /plate_problem/assembly12.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/assembly12.mat -------------------------------------------------------------------------------- /plate_problem/assembly24.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/assembly24.mat -------------------------------------------------------------------------------- /plate_problem/assembly6.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/assembly6.mat -------------------------------------------------------------------------------- /plate_problem/assemblyR.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/assemblyR.mat -------------------------------------------------------------------------------- /plate_problem/assembly_2dplate.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: Isaac J. Lee 3 | % E-mail: ijlee2@ices.utexas.edu 4 | %-------------------------------------------------------------------------- 5 | function assembly_2dplate() 6 | clc; 7 | clear all; close all; 8 | format long; 9 | 10 | % Load the assembly file 11 | load('assembly6'); 12 | 13 | % Find the number of nodes, etc. from the assembly file 14 | numNodes = size(nodes, 1); 15 | numElements = size(elements, 1); 16 | numBCs_displacement = size(BCs_displacement, 1); 17 | numBCs_force = size(BCs_force, 1); 18 | 19 | % Find the number of degrees of freedom (DOFs) for 2D elasticity 20 | numDOFsPerNode = 2; 21 | numDOFs = numDOFsPerNode*numNodes; 22 | 23 | if (numBCs_displacement + numBCs_force ~= numDOFs) 24 | fprintf('Warning: Please check the BCs.\n'); 25 | end 26 | 27 | 28 | %---------------------------------------------------------------------- 29 | % Set up the gcon array so that all the known displacements are on the 30 | % bottom side of u and all the known forces are on the top side of f. 31 | % While we populate the gcon array, we prescribe the known values into 32 | % the vectors u and f. 33 | %---------------------------------------------------------------------- 34 | % Initialize the gcon (global connectivity) array 35 | gcon = zeros(numNodes, numDOFsPerNode); 36 | 37 | % Initialize the solution and the RHS vectors 38 | u = zeros(numDOFs, 1); 39 | f = zeros(numDOFs, 1); 40 | 41 | % index_f stores all the indices corresponding to the known forces, 42 | % and index_u all the indices corresponding to the known displacements. 43 | index_f = 1 : numBCs_force; 44 | index_u = (numBCs_force + 1) : numDOFs; 45 | 46 | % Prescribe the forces 47 | count = 1; 48 | for i = 1 : numBCs_force 49 | gcon(BCs_force(i, 1), BCs_force(i, 2)) = count; 50 | f(count) = BCs_force(i, 3); 51 | count = count + 1; 52 | end 53 | 54 | % Prescribe the displacements 55 | for i = 1 : numBCs_displacement 56 | gcon(BCs_displacement(i, 1), BCs_displacement(i, 2)) = count; 57 | u(count) = BCs_displacement(i, 3); 58 | count = count + 1; 59 | end 60 | 61 | 62 | %---------------------------------------------------------------------- 63 | % Create the global stiffness matrix K 64 | %---------------------------------------------------------------------- 65 | % The number of entries that we need to compute to form the global 66 | % stiffness matrix 67 | numEntries = (3*numDOFsPerNode)^2 * numElements; 68 | 69 | % Initialize the I, J, value arrays 70 | I_temp = zeros(numEntries, 1); 71 | J_temp = zeros(numEntries, 1); 72 | value = zeros(numEntries, 1); 73 | 74 | % Counter for assembly 75 | count = 1; 76 | 77 | % Loop over the elements 78 | for e = 1 : numElements 79 | % Get the node indices 80 | node1Index = elements(e, 1); 81 | node2Index = elements(e, 2); 82 | node3Index = elements(e, 3); 83 | 84 | % Get the nodal positions 85 | x1 = nodes(node1Index, 1); 86 | y1 = nodes(node1Index, 2); 87 | x2 = nodes(node2Index, 1); 88 | y2 = nodes(node2Index, 2); 89 | x3 = nodes(node3Index, 1); 90 | y3 = nodes(node3Index, 2); 91 | 92 | % Get the element properties 93 | E = elements(e, 4); 94 | nu = elements(e, 5); 95 | 96 | %------------------------------------------------------------------ 97 | % Calculate the B matrix 98 | %------------------------------------------------------------------ 99 | A = (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3)/2; 100 | a0 = (x2*y3 - x3*y2)/(2*A); 101 | a1 = (y2 - y3)/(2*A); 102 | a2 = (x3 - x2)/(2*A); 103 | b0 = (x3*y1 - x1*y3)/(2*A); 104 | b1 = (y3 - y1)/(2*A); 105 | b2 = (x1 - x3)/(2*A); 106 | c0 = (x1*y2 - x2*y1)/(2*A); 107 | c1 = (y1 - y2)/(2*A); 108 | c2 = (x2 - x1)/(2*A); 109 | 110 | B = [a1 0 b1 0 c1 0; ... 111 | 0 a2 0 b2 0 c2; ... 112 | a2 a1 b2 b1 c2 c1]; 113 | 114 | %------------------------------------------------------------------ 115 | % Calculate the C matrix 116 | %------------------------------------------------------------------ 117 | % E = E / (1 - nu^2); 118 | % nu = nu / (1 - nu); 119 | C = [E/(1 - nu^2), E*nu/(1 - nu^2), 0; ... 120 | E*nu/(1 - nu^2), E/(1 - nu^2), 0; ... 121 | 0, 0, E/(2*(1 + nu))]; 122 | 123 | %------------------------------------------------------------------ 124 | % Form the element stiffness matrix 125 | %------------------------------------------------------------------ 126 | K_e = (B' * C * B) * (A*1); 127 | 128 | %------------------------------------------------------------------ 129 | % Global assembly 130 | %------------------------------------------------------------------ 131 | % Get the DOF indices 132 | index = [gcon(node1Index, 1); ... 133 | gcon(node1Index, 2); ... 134 | gcon(node2Index, 1); ... 135 | gcon(node2Index, 2); ... 136 | gcon(node3Index, 1); ... 137 | gcon(node3Index, 2)]; 138 | 139 | % Assign the entries 140 | for i = 1 : 3*numDOFsPerNode 141 | for j = 1 : 3*numDOFsPerNode 142 | % Use these lines if K is declared as a sparse matrix 143 | I_temp(count) = index(i); 144 | J_temp(count) = index(j); 145 | value(count) = K_e(i, j); 146 | count = count + 1; 147 | end 148 | end 149 | end 150 | if (numEntries ~= count - 1) 151 | fprintf('Warning: Check the code.\n'); 152 | end 153 | 154 | K = sparse(I_temp, J_temp, value, numDOFs, numDOFs); 155 | clear K_e I_temp J_temp value index index1 index2; 156 | 157 | 158 | %---------------------------------------------------------------------- 159 | % Solve for the unknown displacements and forces 160 | %---------------------------------------------------------------------- 161 | % Solve for the unknown displacements 162 | u(index_f) = K(index_f, index_f) \ (f(index_f) - K(index_f, index_u) * u(index_u)); 163 | 164 | % Solve for the unknown forces 165 | f(index_u) = K(index_u, index_f) * u(index_f) + K(index_u, index_u) * u(index_u); 166 | 167 | 168 | %---------------------------------------------------------------------- 169 | % Post-process 170 | %---------------------------------------------------------------------- 171 | draw_plate_original(nodes, elements, u, gcon); 172 | end -------------------------------------------------------------------------------- /plate_problem/convertAssemblyFile.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: Isaac J. Lee 3 | % E-mail: ijlee2@ices.utexas.edu 4 | % 5 | % This routine reads the assembly files provided by Dr. Landis, and 6 | % converts them into the .mat file format that we had used for truss 7 | % and frame problems. The .mat file contains four arrays called nodes, 8 | % elements, BCs_displacement, and BCs_force. 9 | % 10 | % The .bin files are assumed to be in the same directory as this routine, 11 | % and the .mat file will be created in this directory. 12 | % 13 | % To run this routine, type into Matlab's command window, 14 | % convertAssemblyFile(problem) 15 | % where 16 | % problem = 1, 2, 3, or 4 17 | %-------------------------------------------------------------------------- 18 | function convertAssemblyFile(problem) 19 | clc; 20 | 21 | switch problem 22 | case 1 23 | fileName = '6'; 24 | case 2 25 | fileName = '12'; 26 | case 3 27 | fileName = '24'; 28 | case 4 29 | fileName = 'R'; 30 | end 31 | 32 | 33 | %---------------------------------------------------------------------- 34 | % Create the nodes array 35 | % (x, y) 36 | %---------------------------------------------------------------------- 37 | fileID = fopen(strcat('nodes', fileName), 'r'); 38 | numNodes = str2num(fgetl(fileID)); 39 | numDOFsPerNode = 2; 40 | numDOFs = numDOFsPerNode*numNodes; 41 | 42 | % Initialize the nodes array 43 | nodes = zeros(numNodes, 2); 44 | 45 | for i = 1 : numNodes 46 | temp = str2num(fgetl(fileID)); 47 | 48 | % x-coordinate 49 | nodes(i, 1) = temp(2); 50 | 51 | % y-coordinate 52 | nodes(i, 2) = temp(3); 53 | end 54 | 55 | fclose(fileID); 56 | 57 | 58 | %---------------------------------------------------------------------- 59 | % Create the elements array 60 | % (node 1 index, node 2 index, node 3 index, E, nu) 61 | %---------------------------------------------------------------------- 62 | fileID = fopen(strcat('elements', fileName), 'r'); 63 | temp = str2num(fgetl(fileID)); 64 | numElements = temp(1); 65 | % E = temp(2); 66 | E = 50; 67 | nu = temp(3); 68 | 69 | % Initialize the elements array 70 | elements = zeros(numElements, 5); 71 | 72 | for i = 1 : numElements 73 | temp = str2num(fgetl(fileID)); 74 | 75 | % node 1 index 76 | elements(i, 1) = temp(2); 77 | 78 | % node 2 index 79 | elements(i, 2) = temp(3); 80 | 81 | % node 3 index 82 | elements(i, 3) = temp(4); 83 | end 84 | 85 | % Young's modulus 86 | elements(:, 4) = E * ones(numElements, 1); 87 | 88 | % Poisson's ratio 89 | elements(:, 5) = nu * ones(numElements, 1); 90 | 91 | fclose(fileID); 92 | 93 | 94 | %---------------------------------------------------------------------- 95 | % Create the BCs_displacement array 96 | % (node index, dof index, value) 97 | %---------------------------------------------------------------------- 98 | fileID = fopen(strcat('displacements', fileName), 'r'); 99 | numBCs_displacement = str2num(fgetl(fileID)); 100 | 101 | % Initialize the BCs_displacement array 102 | BCs_displacement = zeros(numBCs_displacement, 3); 103 | 104 | for i = 1 : numBCs_displacement 105 | temp = str2num(fgetl(fileID)); 106 | 107 | % node index 108 | BCs_displacement(i, 1) = temp(1); 109 | 110 | % dof index 111 | BCs_displacement(i, 2) = temp(2); 112 | 113 | % value 114 | BCs_displacement(i, 3) = temp(3); 115 | end 116 | 117 | fclose(fileID); 118 | 119 | 120 | %---------------------------------------------------------------------- 121 | % Create the BCs_force array 122 | % (node index, dof index, value) 123 | %---------------------------------------------------------------------- 124 | fileID = fopen(strcat('forces', fileName), 'r'); 125 | numBCs_force = str2num(fgetl(fileID)); 126 | 127 | % Initialize the BCs_force array 128 | BCs_force = zeros(numDOFs - numBCs_displacement, 3); 129 | 130 | % The forces.bin file only lists the nodal forces with nonzero values. 131 | % However, it is easier if we list all nodal forces, and set to zero 132 | % if there was no applied force at a node in a given direction. 133 | count = 1; 134 | for i = 1 : numNodes 135 | for j = 1 : numDOFsPerNode 136 | % Consider applying a zero nodal force only if we did not 137 | % prescribe a displacement BC already 138 | if (sum(ismember(BCs_displacement(:, [1 2]), [i j], 'rows')) == 0) 139 | BCs_force(count, 1) = i; 140 | BCs_force(count, 2) = j; 141 | BCs_force(count, 3) = 0; 142 | 143 | count = count + 1; 144 | end 145 | end 146 | end 147 | 148 | if ((numDOFs - numBCs_displacement) ~= (count - 1)) 149 | fprintf('Warning: Please check this part of the code.\n'); 150 | end 151 | 152 | % Prescribe the nodal forces with nonzero values 153 | for i = 1 : numBCs_force 154 | temp = str2num(fgetl(fileID)); 155 | 156 | % Find the right row 157 | count = find(ismember(BCs_force(:, [1 2]), [temp(1) temp(2)], 'rows') == 1); 158 | 159 | BCs_force(count, 3) = temp(3); 160 | end 161 | 162 | fclose(fileID); 163 | 164 | 165 | %---------------------------------------------------------------------- 166 | % Create the .mat assembly file 167 | %---------------------------------------------------------------------- 168 | save(strcat('assembly', fileName, '.mat'), 'nodes', 'elements', 'BCs_displacement', 'BCs_force', '-v6'); 169 | end -------------------------------------------------------------------------------- /plate_problem/displacement_plate06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/displacement_plate06.png -------------------------------------------------------------------------------- /plate_problem/displacement_plate12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/displacement_plate12.png -------------------------------------------------------------------------------- /plate_problem/displacement_plate24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/displacement_plate24.png -------------------------------------------------------------------------------- /plate_problem/displacement_plateR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/displacement_plateR.png -------------------------------------------------------------------------------- /plate_problem/displacements12: -------------------------------------------------------------------------------- 1 | 26 2 | 1 2 0.000000 3 | 301 1 0.000000 4 | 3 2 0.000000 5 | 302 1 0.000000 6 | 5 2 0.000000 7 | 303 1 0.000000 8 | 7 2 0.000000 9 | 304 1 0.000000 10 | 9 2 0.000000 11 | 305 1 0.000000 12 | 11 2 0.000000 13 | 306 1 0.000000 14 | 13 2 0.000000 15 | 307 1 0.000000 16 | 15 2 0.000000 17 | 308 1 0.000000 18 | 17 2 0.000000 19 | 309 1 0.000000 20 | 19 2 0.000000 21 | 310 1 0.000000 22 | 21 2 0.000000 23 | 311 1 0.000000 24 | 23 2 0.000000 25 | 312 1 0.000000 26 | 25 2 0.000000 27 | 313 1 0.000000 28 | -------------------------------------------------------------------------------- /plate_problem/displacements24: -------------------------------------------------------------------------------- 1 | 50 2 | 1 2 0.000000 3 | 1177 1 0.000000 4 | 3 2 0.000000 5 | 1178 1 0.000000 6 | 5 2 0.000000 7 | 1179 1 0.000000 8 | 7 2 0.000000 9 | 1180 1 0.000000 10 | 9 2 0.000000 11 | 1181 1 0.000000 12 | 11 2 0.000000 13 | 1182 1 0.000000 14 | 13 2 0.000000 15 | 1183 1 0.000000 16 | 15 2 0.000000 17 | 1184 1 0.000000 18 | 17 2 0.000000 19 | 1185 1 0.000000 20 | 19 2 0.000000 21 | 1186 1 0.000000 22 | 21 2 0.000000 23 | 1187 1 0.000000 24 | 23 2 0.000000 25 | 1188 1 0.000000 26 | 25 2 0.000000 27 | 1189 1 0.000000 28 | 27 2 0.000000 29 | 1190 1 0.000000 30 | 29 2 0.000000 31 | 1191 1 0.000000 32 | 31 2 0.000000 33 | 1192 1 0.000000 34 | 33 2 0.000000 35 | 1193 1 0.000000 36 | 35 2 0.000000 37 | 1194 1 0.000000 38 | 37 2 0.000000 39 | 1195 1 0.000000 40 | 39 2 0.000000 41 | 1196 1 0.000000 42 | 41 2 0.000000 43 | 1197 1 0.000000 44 | 43 2 0.000000 45 | 1198 1 0.000000 46 | 45 2 0.000000 47 | 1199 1 0.000000 48 | 47 2 0.000000 49 | 1200 1 0.000000 50 | 49 2 0.000000 51 | 1201 1 0.000000 52 | -------------------------------------------------------------------------------- /plate_problem/displacements6: -------------------------------------------------------------------------------- 1 | 14 2 | 1 2 0.000000 3 | 79 1 0.000000 4 | 3 2 0.000000 5 | 80 1 0.000000 6 | 5 2 0.000000 7 | 81 1 0.000000 8 | 7 2 0.000000 9 | 82 1 0.000000 10 | 9 2 0.000000 11 | 83 1 0.000000 12 | 11 2 0.000000 13 | 84 1 0.000000 14 | 13 2 0.000000 15 | 85 1 0.000000 16 | -------------------------------------------------------------------------------- /plate_problem/displacementsR: -------------------------------------------------------------------------------- 1 | 26 2 | 1 2 0.000000 3 | 301 1 0.000000 4 | 3 2 0.000000 5 | 302 1 0.000000 6 | 5 2 0.000000 7 | 303 1 0.000000 8 | 7 2 0.000000 9 | 304 1 0.000000 10 | 9 2 0.000000 11 | 305 1 0.000000 12 | 11 2 0.000000 13 | 306 1 0.000000 14 | 13 2 0.000000 15 | 307 1 0.000000 16 | 15 2 0.000000 17 | 308 1 0.000000 18 | 17 2 0.000000 19 | 309 1 0.000000 20 | 19 2 0.000000 21 | 310 1 0.000000 22 | 21 2 0.000000 23 | 311 1 0.000000 24 | 23 2 0.000000 25 | 312 1 0.000000 26 | 25 2 0.000000 27 | 313 1 0.000000 28 | -------------------------------------------------------------------------------- /plate_problem/elements6: -------------------------------------------------------------------------------- 1 | 144 1.00000 0.300000 2 | 1 1 3 2 3 | 2 1 2 14 4 | 3 3 16 2 5 | 4 14 2 16 6 | 5 3 5 4 7 | 6 3 4 16 8 | 7 5 18 4 9 | 8 16 4 18 10 | 9 5 7 6 11 | 10 5 6 18 12 | 11 7 20 6 13 | 12 18 6 20 14 | 13 7 9 8 15 | 14 7 8 20 16 | 15 9 22 8 17 | 16 20 8 22 18 | 17 9 11 10 19 | 18 9 10 22 20 | 19 11 24 10 21 | 20 22 10 24 22 | 21 11 13 12 23 | 22 11 12 24 24 | 23 13 26 12 25 | 24 24 12 26 26 | 25 14 16 15 27 | 26 14 15 27 28 | 27 16 29 15 29 | 28 27 15 29 30 | 29 16 18 17 31 | 30 16 17 29 32 | 31 18 31 17 33 | 32 29 17 31 34 | 33 18 20 19 35 | 34 18 19 31 36 | 35 20 33 19 37 | 36 31 19 33 38 | 37 20 22 21 39 | 38 20 21 33 40 | 39 22 35 21 41 | 40 33 21 35 42 | 41 22 24 23 43 | 42 22 23 35 44 | 43 24 37 23 45 | 44 35 23 37 46 | 45 24 26 25 47 | 46 24 25 37 48 | 47 26 39 25 49 | 48 37 25 39 50 | 49 27 29 28 51 | 50 27 28 40 52 | 51 29 42 28 53 | 52 40 28 42 54 | 53 29 31 30 55 | 54 29 30 42 56 | 55 31 44 30 57 | 56 42 30 44 58 | 57 31 33 32 59 | 58 31 32 44 60 | 59 33 46 32 61 | 60 44 32 46 62 | 61 33 35 34 63 | 62 33 34 46 64 | 63 35 48 34 65 | 64 46 34 48 66 | 65 35 37 36 67 | 66 35 36 48 68 | 67 37 50 36 69 | 68 48 36 50 70 | 69 37 39 38 71 | 70 37 38 50 72 | 71 39 52 38 73 | 72 50 38 52 74 | 73 40 42 41 75 | 74 40 41 53 76 | 75 42 55 41 77 | 76 53 41 55 78 | 77 42 44 43 79 | 78 42 43 55 80 | 79 44 57 43 81 | 80 55 43 57 82 | 81 44 46 45 83 | 82 44 45 57 84 | 83 46 59 45 85 | 84 57 45 59 86 | 85 46 48 47 87 | 86 46 47 59 88 | 87 48 61 47 89 | 88 59 47 61 90 | 89 48 50 49 91 | 90 48 49 61 92 | 91 50 63 49 93 | 92 61 49 63 94 | 93 50 52 51 95 | 94 50 51 63 96 | 95 52 65 51 97 | 96 63 51 65 98 | 97 53 55 54 99 | 98 53 54 66 100 | 99 55 68 54 101 | 100 66 54 68 102 | 101 55 57 56 103 | 102 55 56 68 104 | 103 57 70 56 105 | 104 68 56 70 106 | 105 57 59 58 107 | 106 57 58 70 108 | 107 59 72 58 109 | 108 70 58 72 110 | 109 59 61 60 111 | 110 59 60 72 112 | 111 61 74 60 113 | 112 72 60 74 114 | 113 61 63 62 115 | 114 61 62 74 116 | 115 63 76 62 117 | 116 74 62 76 118 | 117 63 65 64 119 | 118 63 64 76 120 | 119 65 78 64 121 | 120 76 64 78 122 | 121 66 68 67 123 | 122 66 67 79 124 | 123 68 80 67 125 | 124 79 67 80 126 | 125 68 70 69 127 | 126 68 69 80 128 | 127 70 81 69 129 | 128 80 69 81 130 | 129 70 72 71 131 | 130 70 71 81 132 | 131 72 82 71 133 | 132 81 71 82 134 | 133 72 74 73 135 | 134 72 73 82 136 | 135 74 83 73 137 | 136 82 73 83 138 | 137 74 76 75 139 | 138 74 75 83 140 | 139 76 84 75 141 | 140 83 75 84 142 | 141 76 78 77 143 | 142 76 77 84 144 | 143 78 85 77 145 | 144 84 77 85 146 | -------------------------------------------------------------------------------- /plate_problem/forces12: -------------------------------------------------------------------------------- 1 | 7 2 | 300 2 0.401923788646684 3 | 275 2 0.423841597178549 4 | 250 2 0.464101615137755 5 | 225 2 0.529670138408798 6 | 200 2 0.633974596215561 7 | 175 2 0.349009518031560 8 | 313 2 0.197478746381094 9 | -------------------------------------------------------------------------------- /plate_problem/forces24: -------------------------------------------------------------------------------- 1 | 13 2 | 1176 2 0.197478746381094 3 | 1127 2 0.200053356846629 4 | 1078 2 0.204445042265590 5 | 1029 2 0.210812837225577 6 | 980 2 0.219396554912958 7 | 931 2 0.230536750751893 8 | 882 2 0.244705060224796 9 | 833 2 0.262549817831992 10 | 784 2 0.284965078184002 11 | 735 2 0.313196737610187 12 | 686 2 0.349009518031560 13 | 637 2 0.184535305510865 14 | 1201 2 9.831519422285766E-002 15 | -------------------------------------------------------------------------------- /plate_problem/forces6: -------------------------------------------------------------------------------- 1 | 4 2 | 78 2 0.866025403784439 3 | 65 2 1.09807621135332 4 | 52 2 0.633974596215561 5 | 85 2 0.401923788646684 6 | -------------------------------------------------------------------------------- /plate_problem/forcesR: -------------------------------------------------------------------------------- 1 | 7 2 | 300 2 0.401923788646684 3 | 275 2 0.423841597178549 4 | 250 2 0.464101615137755 5 | 225 2 0.529670138408798 6 | 200 2 0.633974596215561 7 | 175 2 0.349009518031560 8 | 313 2 0.197478746381094 9 | -------------------------------------------------------------------------------- /plate_problem/nodes6: -------------------------------------------------------------------------------- 1 | 85 2 | 1 1.00000000000000 0.000000000000000 3 | 2 1.15882444736298 0.152562132760670 4 | 3 1.33333333333333 0.000000000000000 5 | 4 1.49358361934132 0.196634013841907 6 | 5 1.66666666666667 0.000000000000000 7 | 6 1.82834279131966 0.240705894923144 8 | 7 2.00000000000000 0.000000000000000 9 | 8 2.16310196329800 0.284777776004381 10 | 9 2.33333333333333 0.000000000000000 11 | 10 2.49786113527634 0.328849657085618 12 | 11 2.66666666666667 0.000000000000000 13 | 12 2.83262030725468 0.372921538166855 14 | 13 3.00000000000000 0.000000000000000 15 | 14 0.965925826289068 0.258819045102521 16 | 15 1.09688957503402 0.454346538404750 17 | 16 1.30493818574175 0.349657133042035 18 | 17 1.44290966007947 0.597672750484070 19 | 18 1.64395054519442 0.440495220981549 20 | 19 1.78892974512493 0.740998962563390 21 | 20 1.98296290464710 0.531333308921063 22 | 21 2.13494983017039 0.884325174642709 23 | 22 2.32197526409978 0.622171396860578 24 | 23 2.48096991521584 1.02765138672203 25 | 24 2.66098762355245 0.713009484800092 26 | 25 2.82699000026130 1.17097759880135 27 | 26 3.00000000000000 0.803847577293368 28 | 27 0.866025403784439 0.500000000000000 29 | 28 0.977240554621107 0.749863051308302 30 | 29 1.22168782751292 0.705341796080271 31 | 30 1.34501498328085 1.03206629590747 32 | 31 1.57735025124139 0.910683592160543 33 | 32 1.71278941194059 1.31426954050663 34 | 33 1.93301267496987 1.11602538824081 35 | 34 2.08056384060033 1.59647278510579 36 | 35 2.28867509869835 1.32136718432109 37 | 36 2.44833826926008 1.87867602970496 38 | 37 2.64433752242683 1.52670898040136 39 | 38 2.81611269791982 2.16087927430412 40 | 39 3.00000000000000 1.73205080756888 41 | 40 0.707106781186548 0.707106781186547 42 | 41 0.749863051308302 0.977240554621106 43 | 42 1.08925562838270 1.08925562838270 44 | 43 1.03206629590747 1.34501498328085 45 | 44 1.47140447557886 1.47140447557886 46 | 45 1.31426954050663 1.71278941194059 47 | 46 1.85355332277502 1.85355332277502 48 | 47 1.59647278510579 2.08056384060033 49 | 48 2.23570216997118 2.23570216997118 50 | 49 1.87867602970496 2.44833826926008 51 | 50 2.61785101716733 2.61785101716733 52 | 51 2.16087927430412 2.81611269791982 53 | 52 3.00000000000000 3.00000000000000 54 | 53 0.500000000000000 0.866025403784439 55 | 54 0.454346538404750 1.09688957503402 56 | 55 0.705341796080272 1.22168782751292 57 | 56 0.597672750484070 1.44290966007947 58 | 57 0.910683592160543 1.57735025124139 59 | 58 0.740998962563390 1.78892974512493 60 | 59 1.11602538824081 1.93301267496987 61 | 60 0.884325174642710 2.13494983017039 62 | 61 1.32136718432109 2.28867509869835 63 | 62 1.02765138672203 2.48096991521584 64 | 63 1.52670898040136 2.64433752242683 65 | 64 1.17097759880135 2.82699000026130 66 | 65 1.73205080756888 3.00000000000000 67 | 66 0.258819045102521 0.965925826289068 68 | 67 0.152562132760670 1.15882444736298 69 | 68 0.349657133042035 1.30493818574175 70 | 69 0.196634013841907 1.49358361934132 71 | 70 0.440495220981550 1.64395054519442 72 | 71 0.240705894923144 1.82834279131966 73 | 72 0.531333308921064 1.98296290464710 74 | 73 0.284777776004381 2.16310196329800 75 | 74 0.622171396860578 2.32197526409978 76 | 75 0.328849657085618 2.49786113527634 77 | 76 0.713009484800093 2.66098762355245 78 | 77 0.372921538166855 2.83262030725468 79 | 78 0.803847577293369 3.00000000000000 80 | 79 0.000000000000000 1.00000000000000 81 | 80 0.000000000000000 1.33333333333333 82 | 81 0.000000000000000 1.66666666666667 83 | 82 0.000000000000000 2.00000000000000 84 | 83 0.000000000000000 2.33333333333333 85 | 84 0.000000000000000 2.66666666666667 86 | 85 0.000000000000000 3.00000000000000 87 | -------------------------------------------------------------------------------- /plate_problem/stress_xx_plate06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_xx_plate06.png -------------------------------------------------------------------------------- /plate_problem/stress_xx_plate12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_xx_plate12.png -------------------------------------------------------------------------------- /plate_problem/stress_xx_plate24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_xx_plate24.png -------------------------------------------------------------------------------- /plate_problem/stress_xx_plateR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_xx_plateR.png -------------------------------------------------------------------------------- /plate_problem/stress_xy_plate06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_xy_plate06.png -------------------------------------------------------------------------------- /plate_problem/stress_xy_plate12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_xy_plate12.png -------------------------------------------------------------------------------- /plate_problem/stress_xy_plate24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_xy_plate24.png -------------------------------------------------------------------------------- /plate_problem/stress_xy_plateR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_xy_plateR.png -------------------------------------------------------------------------------- /plate_problem/stress_yy_plate06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_yy_plate06.png -------------------------------------------------------------------------------- /plate_problem/stress_yy_plate12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_yy_plate12.png -------------------------------------------------------------------------------- /plate_problem/stress_yy_plate24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_yy_plate24.png -------------------------------------------------------------------------------- /plate_problem/stress_yy_plateR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/plate_problem/stress_yy_plateR.png -------------------------------------------------------------------------------- /truss analysis/Documentation/Documentation.aux: -------------------------------------------------------------------------------- 1 | \relax 2 | \ifx\hyper@anchor\@undefined 3 | \global \let \oldcontentsline\contentsline 4 | \gdef \contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}} 5 | \global \let \oldnewlabel\newlabel 6 | \gdef \newlabel#1#2{\newlabelxx{#1}#2} 7 | \gdef \newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} 8 | \AtEndDocument{\let \contentsline\oldcontentsline 9 | \let \newlabel\oldnewlabel} 10 | \else 11 | \global \let \hyper@last\relax 12 | \fi 13 | 14 | \select@language{english} 15 | \@writefile{toc}{\select@language{english}} 16 | \@writefile{lof}{\select@language{english}} 17 | \@writefile{lot}{\select@language{english}} 18 | \@writefile{toc}{\contentsline {section}{\tocsection {}{1}{How to set up a truss}}{1}{section.1}} 19 | \newlabel{sec:1}{{1}{1}{How to set up a truss\relax }{section.1}{}} 20 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.1}{Define the nodes}}{1}{subsection.1.1}} 21 | \newlabel{sec:1.1}{{1.1}{1}{Define the nodes\relax }{subsection.1.1}{}} 22 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.2}{Define the elements}}{1}{subsection.1.2}} 23 | \newlabel{sec:1.2}{{1.2}{1}{Define the elements\relax }{subsection.1.2}{}} 24 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.3}{Define the boundary conditions (BCs)}}{2}{subsection.1.3}} 25 | \newlabel{sec:1.3}{{1.3}{2}{Define the boundary conditions (BCs)\relax }{subsection.1.3}{}} 26 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.4}{Display options}}{2}{subsection.1.4}} 27 | \newlabel{sec:1.4}{{1.4}{2}{Display options\relax }{subsection.1.4}{}} 28 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.5}{Save your workspace, come back later}}{3}{subsection.1.5}} 29 | \newlabel{sec:1.5}{{1.5}{3}{Save your workspace, come back later\relax }{subsection.1.5}{}} 30 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.6}{Create the assembly file}}{3}{subsection.1.6}} 31 | \newlabel{sec:1.6}{{1.6}{3}{Create the assembly file\relax }{subsection.1.6}{}} 32 | \newlabel{tocindent-1}{0pt} 33 | \newlabel{tocindent0}{0pt} 34 | \newlabel{tocindent1}{17.77344pt} 35 | \newlabel{tocindent2}{0pt} 36 | \newlabel{tocindent3}{25.54932pt} 37 | \@writefile{toc}{\contentsline {section}{\tocsection {}{2}{Some useful Matlab routines}}{4}{section.2}} 38 | \newlabel{sec:2}{{2}{4}{Some useful Matlab routines\relax }{section.2}{}} 39 | -------------------------------------------------------------------------------- /truss analysis/Documentation/Documentation.dvi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss analysis/Documentation/Documentation.dvi -------------------------------------------------------------------------------- /truss analysis/Documentation/Documentation.out: -------------------------------------------------------------------------------- 1 | \BOOKMARK [1][-]{section.1}{1. How to set up a truss}{} 2 | \BOOKMARK [2][-]{subsection.1.1}{1.1. Define the nodes}{section.1} 3 | \BOOKMARK [2][-]{subsection.1.2}{1.2. Define the elements}{section.1} 4 | \BOOKMARK [2][-]{subsection.1.3}{1.3. Define the boundary conditions \(BCs\)}{section.1} 5 | \BOOKMARK [2][-]{subsection.1.4}{1.4. Display options}{section.1} 6 | \BOOKMARK [2][-]{subsection.1.5}{1.5. Save your workspace, come back later}{section.1} 7 | \BOOKMARK [2][-]{subsection.1.6}{1.6. Create the assembly file}{section.1} 8 | \BOOKMARK [1][-]{section.2}{2. Some useful Matlab routines}{} 9 | -------------------------------------------------------------------------------- /truss analysis/Documentation/Documentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss analysis/Documentation/Documentation.pdf -------------------------------------------------------------------------------- /truss analysis/assembly_truss.m: -------------------------------------------------------------------------------- 1 | function [u, f, strain_axial, force_axial, gcon] = assembly_truss() 2 | clc; 3 | format long; 4 | 5 | % Load the assembly file 6 | load('temp_assembly'); 7 | 8 | % Find the number of nodes, etc. 9 | numNodes = size(nodes, 1); 10 | numElements = size(elements, 1); 11 | numBCs_displacement = size(BCs_displacement, 1); 12 | numBCs_force = size(BCs_force, 1); 13 | 14 | % Find the number of degrees of freedom (DOFs) for a truss 15 | % Note, numBCs_displacement + numBCs_force = numDOFs 16 | numDOFs = 2*numNodes; 17 | 18 | 19 | %---------------------------------------------------------------------- 20 | % Set up the global connectivity array called gcon, which returns the 21 | % global DOF index when given the node index and the local DOF index. 22 | % 23 | % Initially, gcon is a (numNodes) x 2 double array with these entries: 24 | % 25 | % local dof index 26 | % 27 | % 1 2 28 | % 29 | % node 1 1 2 30 | % index 2 3 4 31 | % 3 5 6 32 | % ... ... ... 33 | % numNodes (2*numNodes - 1) (2*numNodes) 34 | % 35 | % We plan to have the bottom entries of the DOF vector u correspond 36 | % to the DOFs that are already known (given as the displacement BCs). 37 | % So we do not actually create gcon with the entries above just yet, 38 | % but assume its existence. 39 | % 40 | % First, create a vector that tags all global DOF indices corresponding 41 | % to the displacement BCs. As the number of displacement BCs is likely 42 | % few in comparison to the total number of DOFs, we let the vector be 43 | % a sparse vector. 44 | %---------------------------------------------------------------------- 45 | tag = sparse(BCs_displacement(:, 1), BCs_displacement(:, 2), ones(numBCs_displacement, 1), numNodes, 2); 46 | tag = reshape(tag', numDOFs, 1); 47 | 48 | %---------------------------------------------------------------------- 49 | % tag is now a vector of zeros and ones, where the ones correspond to 50 | % to the displacement BCs. Sort this vector in ascending order, and 51 | % keep track of the permutation that was done. 52 | %---------------------------------------------------------------------- 53 | [temp, permutation] = sort(tag); 54 | 55 | %---------------------------------------------------------------------- 56 | % Create the gcon array 57 | %---------------------------------------------------------------------- 58 | gcon(permutation) = (1 : numDOFs)'; 59 | gcon = reshape(gcon, 2, numNodes)'; 60 | 61 | % Indices corresponding to the unknown displacements (known forces) 62 | index_u = (1 : numBCs_force)'; 63 | 64 | % Vector of indices of the unknown forces (known displacements) 65 | index_f = ((numBCs_force + 1) : numDOFs)'; 66 | 67 | 68 | %---------------------------------------------------------------------- 69 | % Create the global stiffness matrix K 70 | %---------------------------------------------------------------------- 71 | % Each element matrix is 4 x 4, so there are (16*numElements) many elements 72 | % that we will need to compute to find the global stiffness matrix K 73 | numEntries = 16*numElements; 74 | 75 | % Initialize the I, J, value arrays 76 | I = zeros(numEntries, 1); 77 | J = zeros(numEntries, 1); 78 | value = zeros(numEntries, 1); 79 | 80 | % Temporary variables useful for assembly 81 | i = (1 : 16)'; 82 | vecones = ones(4, 1); 83 | 84 | %---------------------------------------------------------------------- 85 | % Loop over the elements 86 | %---------------------------------------------------------------------- 87 | for e = 1 : numElements 88 | % Get the node indices 89 | nodeIndex1 = elements(e, 1); 90 | nodeIndex2 = elements(e, 2); 91 | 92 | % Get the global DOF indices 93 | globalDOFIndex = [gcon(nodeIndex1, 1); ... 94 | gcon(nodeIndex1, 2); ... 95 | gcon(nodeIndex2, 1); ... 96 | gcon(nodeIndex2, 2)]; 97 | 98 | % Get the global coordinates of the nodes 99 | x1 = nodes(nodeIndex1, 1); 100 | y1 = nodes(nodeIndex1, 2); 101 | x2 = nodes(nodeIndex2, 1); 102 | y2 = nodes(nodeIndex2, 2); 103 | 104 | % Get the material properties 105 | E = elements(e, 3); 106 | A = elements(e, 4); 107 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 108 | 109 | % Calculate the cosine and sine values 110 | costheta = (x2 - x1)/L; 111 | sintheta = (y2 - y1)/L; 112 | 113 | %------------------------------------------------------------------ 114 | % Form the element matrix 115 | %------------------------------------------------------------------ 116 | temp = [costheta * costheta, costheta * sintheta; ... 117 | costheta * sintheta, sintheta * sintheta]; 118 | K_e = E*A/L * [ temp, -temp; ... 119 | -temp, temp]; 120 | 121 | %------------------------------------------------------------------ 122 | % Global assembly 123 | %------------------------------------------------------------------ 124 | I(i) = kron(globalDOFIndex, vecones); 125 | J(i) = kron(vecones, globalDOFIndex); 126 | value(i) = reshape(K_e, 16, 1); 127 | i = i + 16; 128 | end 129 | 130 | K = sparse(I, J, value, numDOFs, numDOFs); 131 | clear I J value K_e temp vecones; 132 | 133 | %---------------------------------------------------------------------- 134 | % Solve for the unknown displacements and forces 135 | %---------------------------------------------------------------------- 136 | % Initialize the solution vector and the RHS external force vector 137 | u = zeros(numDOFs, 1); 138 | f = zeros(numDOFs, 1); 139 | 140 | % Prescribe the displacements 141 | u(index_f) = BCs_displacement(:, 3); 142 | 143 | % Prescribe the nodal forces 144 | f(index_u) = BCs_force(:, 3); 145 | 146 | % Solve for the unknown displacements 147 | u(index_u) = K(index_u, index_u) \ (f(index_u) - K(index_u, index_f) * u(index_f)); 148 | 149 | % Solve for the unknown nodal forces 150 | f(index_f) = K(index_f, :) * u; 151 | 152 | 153 | %---------------------------------------------------------------------- 154 | % Post-process 155 | %---------------------------------------------------------------------- 156 | strain_axial = zeros(numElements, 1); 157 | force_axial = zeros(numElements, 1); 158 | 159 | figure; 160 | 161 | % Draw the undeformed structure first 162 | for i = 1 : numElements 163 | % Get the node indices 164 | nodeIndex1 = elements(i, 1); 165 | nodeIndex2 = elements(i, 2); 166 | 167 | % Get the global coordinates of the nodes 168 | x1 = nodes(nodeIndex1, 1); 169 | y1 = nodes(nodeIndex1, 2); 170 | x2 = nodes(nodeIndex2, 1); 171 | y2 = nodes(nodeIndex2, 2); 172 | 173 | % Draw the undeformed element 174 | line([x1 x2], [y1 y2], 'Color', [0.8 0.9 0.75], 'LineWidth', 2); hold on; 175 | 176 | plot(x1, y1, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 177 | plot(x2, y2, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 178 | end 179 | 180 | % Draw the deformed structure 181 | for i = 1 : numElements 182 | % Get the node indices 183 | nodeIndex1 = elements(i, 1); 184 | nodeIndex2 = elements(i, 2); 185 | 186 | % Get the global DOF indices 187 | globalDOFIndex = [gcon(nodeIndex1, 1); ... 188 | gcon(nodeIndex1, 2); ... 189 | gcon(nodeIndex2, 1); ... 190 | gcon(nodeIndex2, 2)]; 191 | 192 | % Get the global coordinates of the nodes 193 | x1 = nodes(nodeIndex1, 1); 194 | y1 = nodes(nodeIndex1, 2); 195 | x2 = nodes(nodeIndex2, 1); 196 | y2 = nodes(nodeIndex2, 2); 197 | 198 | % Get the material properties 199 | E = elements(i, 3); 200 | A = elements(i, 4); 201 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 202 | 203 | % Calculate the cosine and sine values 204 | costheta = (x2 - x1)/L; 205 | sintheta = (y2 - y1)/L; 206 | 207 | % Get the global displacements of the nodes 208 | scale_factor = 1; 209 | ux1 = scale_factor * u(globalDOFIndex(1)); 210 | uy1 = scale_factor * u(globalDOFIndex(2)); 211 | ux2 = scale_factor * u(globalDOFIndex(3)); 212 | uy2 = scale_factor * u(globalDOFIndex(4)); 213 | 214 | % Calculate the axial strain 215 | strain_axial(i) = (ux2 - ux1)/L * costheta + (uy2 - uy1)/L * sintheta; 216 | 217 | % Calculate the axial force 218 | force_axial(i) = E*A * strain_axial(i); 219 | 220 | % Draw the deformed element 221 | line([x1 + ux1, x2 + ux2], [y1 + uy1, y2 + uy2], 'Color', [0.7 0.3 0.3], 'LineWidth', 2); hold on; 222 | 223 | plot(x1 + ux1, y1 + uy1, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 224 | plot(x2 + ux2, y2 + uy2, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 225 | end 226 | end -------------------------------------------------------------------------------- /truss analysis/sample.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss analysis/sample.mat -------------------------------------------------------------------------------- /truss analysis/sample_assembly.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss analysis/sample_assembly.mat -------------------------------------------------------------------------------- /truss analysis/sample_assembly_BCs_displacement.txt: -------------------------------------------------------------------------------- 1 | 4 2 | 1 1 0.000000000000000 3 | 5 2 0.000000000000000 4 | 6 1 2.000000000000000 5 | 6 2 -1.000000000000000 6 | -------------------------------------------------------------------------------- /truss analysis/sample_assembly_BCs_force.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 1 2 0.000000000000000 3 | 2 1 0.000000000000000 4 | 2 2 3.000000000000000 5 | 3 1 1.000000000000000 6 | 3 2 2.000000000000000 7 | 4 1 2.000000000000000 8 | 4 2 -3.000000000000000 9 | 5 1 0.000000000000000 10 | -------------------------------------------------------------------------------- /truss analysis/sample_assembly_elements.txt: -------------------------------------------------------------------------------- 1 | 11 2 | 1 6 1.000000000000000 1.000000000000000 3 | 2 6 1.000000000000000 1.000000000000000 4 | 2 3 1.000000000000000 1.000000000000000 5 | 1 3 1.000000000000000 1.000000000000000 6 | 4 3 1.000000000000000 1.000000000000000 7 | 4 1 1.000000000000000 2.000000000000000 8 | 5 1 1.000000000000000 2.000000000000000 9 | 5 4 1.000000000000000 2.000000000000000 10 | 1 2 1.000000000000000 2.000000000000000 11 | 3 5 1.000000000000000 1.000000000000000 12 | 3 6 1.000000000000000 1.000000000000000 13 | -------------------------------------------------------------------------------- /truss analysis/sample_assembly_nodes.txt: -------------------------------------------------------------------------------- 1 | 6 2 | 1.000000000000000 1.000000000000000 3 | 1.000000000000000 5.000000000000000 4 | 3.000000000000000 5.000000000000000 5 | 7.000000000000000 4.000000000000000 6 | 5.000000000000000 -1.000000000000000 7 | -1.000000000000000 3.000000000000000 8 | -------------------------------------------------------------------------------- /truss analysis/sample_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss analysis/sample_plot.png -------------------------------------------------------------------------------- /truss_2d/Documentation/Documentation.aux: -------------------------------------------------------------------------------- 1 | \relax 2 | \ifx\hyper@anchor\@undefined 3 | \global \let \oldcontentsline\contentsline 4 | \gdef \contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}} 5 | \global \let \oldnewlabel\newlabel 6 | \gdef \newlabel#1#2{\newlabelxx{#1}#2} 7 | \gdef \newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} 8 | \AtEndDocument{\let \contentsline\oldcontentsline 9 | \let \newlabel\oldnewlabel} 10 | \else 11 | \global \let \hyper@last\relax 12 | \fi 13 | 14 | \select@language{english} 15 | \@writefile{toc}{\select@language{english}} 16 | \@writefile{lof}{\select@language{english}} 17 | \@writefile{lot}{\select@language{english}} 18 | \@writefile{toc}{\contentsline {section}{\tocsection {}{1}{How to set up a truss}}{1}{section.1}} 19 | \newlabel{sec:1}{{1}{1}{How to set up a truss\relax }{section.1}{}} 20 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.1}{Define the nodes}}{1}{subsection.1.1}} 21 | \newlabel{sec:1.1}{{1.1}{1}{Define the nodes\relax }{subsection.1.1}{}} 22 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.2}{Define the elements}}{1}{subsection.1.2}} 23 | \newlabel{sec:1.2}{{1.2}{1}{Define the elements\relax }{subsection.1.2}{}} 24 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.3}{Define the boundary conditions (BCs)}}{2}{subsection.1.3}} 25 | \newlabel{sec:1.3}{{1.3}{2}{Define the boundary conditions (BCs)\relax }{subsection.1.3}{}} 26 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.4}{Display options}}{2}{subsection.1.4}} 27 | \newlabel{sec:1.4}{{1.4}{2}{Display options\relax }{subsection.1.4}{}} 28 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.5}{Save your workspace, come back later}}{3}{subsection.1.5}} 29 | \newlabel{sec:1.5}{{1.5}{3}{Save your workspace, come back later\relax }{subsection.1.5}{}} 30 | \@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{1.6}{Create the assembly file}}{3}{subsection.1.6}} 31 | \newlabel{sec:1.6}{{1.6}{3}{Create the assembly file\relax }{subsection.1.6}{}} 32 | \newlabel{tocindent-1}{0pt} 33 | \newlabel{tocindent0}{0pt} 34 | \newlabel{tocindent1}{17.77344pt} 35 | \newlabel{tocindent2}{0pt} 36 | \newlabel{tocindent3}{25.54932pt} 37 | \@writefile{toc}{\contentsline {section}{\tocsection {}{2}{Some useful Matlab routines}}{4}{section.2}} 38 | \newlabel{sec:2}{{2}{4}{Some useful Matlab routines\relax }{section.2}{}} 39 | -------------------------------------------------------------------------------- /truss_2d/Documentation/Documentation.dvi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss_2d/Documentation/Documentation.dvi -------------------------------------------------------------------------------- /truss_2d/Documentation/Documentation.out: -------------------------------------------------------------------------------- 1 | \BOOKMARK [1][-]{section.1}{1. How to set up a truss}{} 2 | \BOOKMARK [2][-]{subsection.1.1}{1.1. Define the nodes}{section.1} 3 | \BOOKMARK [2][-]{subsection.1.2}{1.2. Define the elements}{section.1} 4 | \BOOKMARK [2][-]{subsection.1.3}{1.3. Define the boundary conditions \(BCs\)}{section.1} 5 | \BOOKMARK [2][-]{subsection.1.4}{1.4. Display options}{section.1} 6 | \BOOKMARK [2][-]{subsection.1.5}{1.5. Save your workspace, come back later}{section.1} 7 | \BOOKMARK [2][-]{subsection.1.6}{1.6. Create the assembly file}{section.1} 8 | \BOOKMARK [1][-]{section.2}{2. Some useful Matlab routines}{} 9 | -------------------------------------------------------------------------------- /truss_2d/Documentation/Documentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss_2d/Documentation/Documentation.pdf -------------------------------------------------------------------------------- /truss_2d/assembly_2dtruss.m: -------------------------------------------------------------------------------- 1 | function [u, f, strain_axial, force_axial, gcon] = assembly_2dtruss() 2 | clc; 3 | format long; 4 | 5 | % Load the assembly file 6 | load('untitled_assembly'); 7 | 8 | % Find the number of nodes, etc. 9 | numNodes = size(nodes, 1); 10 | numElements = size(elements, 1); 11 | numBCs_displacement = size(BCs_displacement, 1); 12 | numBCs_force = size(BCs_force, 1); 13 | 14 | % Find the number of degrees of freedom (DOFs) for a truss 15 | % Note, numBCs_displacement + numBCs_force = numDOFs 16 | numDOFs = 2*numNodes; 17 | 18 | 19 | %---------------------------------------------------------------------- 20 | % Set up the global connectivity array called gcon, which returns the 21 | % global DOF index when given the node index and the local DOF index. 22 | % 23 | % Initially, gcon is a (numNodes) x 2 double array with these entries: 24 | % 25 | % local dof index 26 | % 27 | % 1 2 28 | % 29 | % node 1 1 2 30 | % index 2 3 4 31 | % 3 5 6 32 | % ... ... ... 33 | % numNodes (2*numNodes - 1) (2*numNodes) 34 | % 35 | % We plan to have the bottom entries of the DOF vector u correspond 36 | % to the DOFs that are already known (given as the displacement BCs). 37 | % So we do not actually create gcon with the entries above just yet, 38 | % but assume its existence. 39 | % 40 | % First, create a vector that tags all global DOF indices corresponding 41 | % to the displacement BCs. As the number of displacement BCs is likely 42 | % few in comparison to the total number of DOFs, we let the vector be 43 | % a sparse vector. 44 | %---------------------------------------------------------------------- 45 | tag = sparse(BCs_displacement(:, 1), BCs_displacement(:, 2), ones(numBCs_displacement, 1), numNodes, 2); 46 | tag = reshape(tag', numDOFs, 1); 47 | 48 | %---------------------------------------------------------------------- 49 | % tag is now a vector of zeros and ones, where the ones correspond to 50 | % to the displacement BCs. Sort this vector in ascending order, and 51 | % keep track of the permutation that was done. 52 | %---------------------------------------------------------------------- 53 | [temp, permutation] = sort(tag); 54 | 55 | %---------------------------------------------------------------------- 56 | % Create the gcon array 57 | %---------------------------------------------------------------------- 58 | gcon(permutation) = (1 : numDOFs)'; 59 | gcon = reshape(gcon, 2, numNodes)'; 60 | 61 | % Indices corresponding to the unknown displacements (known forces) 62 | index_u = (1 : numBCs_force)'; 63 | 64 | % Vector of indices of the unknown forces (known displacements) 65 | index_f = ((numBCs_force + 1) : numDOFs)'; 66 | 67 | 68 | %---------------------------------------------------------------------- 69 | % Create the global stiffness matrix K 70 | %---------------------------------------------------------------------- 71 | % Each element matrix is 4 x 4, so there are (16*numElements) many elements 72 | % that we will need to compute to find the global stiffness matrix K 73 | numEntries = 16*numElements; 74 | 75 | % Initialize the I, J, value arrays 76 | I = zeros(numEntries, 1); 77 | J = zeros(numEntries, 1); 78 | value = zeros(numEntries, 1); 79 | 80 | % Temporary variables useful for assembly 81 | i = (1 : 16)'; 82 | vecones = ones(4, 1); 83 | 84 | %---------------------------------------------------------------------- 85 | % Loop over the elements 86 | %---------------------------------------------------------------------- 87 | for e = 1 : numElements 88 | % Get the node indices 89 | nodeIndex1 = elements(e, 1); 90 | nodeIndex2 = elements(e, 2); 91 | 92 | % Get the global DOF indices 93 | globalDOFIndex = [gcon(nodeIndex1, 1); ... 94 | gcon(nodeIndex1, 2); ... 95 | gcon(nodeIndex2, 1); ... 96 | gcon(nodeIndex2, 2)]; 97 | 98 | % Get the global coordinates of the nodes 99 | x1 = nodes(nodeIndex1, 1); 100 | y1 = nodes(nodeIndex1, 2); 101 | x2 = nodes(nodeIndex2, 1); 102 | y2 = nodes(nodeIndex2, 2); 103 | 104 | % Get the material properties 105 | E = elements(e, 3); 106 | A = elements(e, 4); 107 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 108 | 109 | % Calculate the cosine and sine values 110 | costheta = (x2 - x1)/L; 111 | sintheta = (y2 - y1)/L; 112 | 113 | %------------------------------------------------------------------ 114 | % Form the element matrix 115 | %------------------------------------------------------------------ 116 | temp = [costheta * costheta, costheta * sintheta; ... 117 | costheta * sintheta, sintheta * sintheta]; 118 | K_e = E*A/L * [ temp, -temp; ... 119 | -temp, temp]; 120 | 121 | %------------------------------------------------------------------ 122 | % Global assembly 123 | %------------------------------------------------------------------ 124 | I(i) = kron(globalDOFIndex, vecones); 125 | J(i) = kron(vecones, globalDOFIndex); 126 | value(i) = reshape(K_e, 16, 1); 127 | i = i + 16; 128 | end 129 | 130 | K = sparse(I, J, value, numDOFs, numDOFs); 131 | clear I J value K_e temp vecones; 132 | 133 | %---------------------------------------------------------------------- 134 | % Solve for the unknown displacements and forces 135 | %---------------------------------------------------------------------- 136 | % Initialize the solution vector and the RHS external force vector 137 | u = zeros(numDOFs, 1); 138 | f = zeros(numDOFs, 1); 139 | 140 | % Prescribe the displacements 141 | u(index_f) = BCs_displacement(:, 3); 142 | 143 | % Prescribe the nodal forces 144 | f(index_u) = BCs_force(:, 3); 145 | 146 | % Solve for the unknown displacements 147 | u(index_u) = K(index_u, index_u) \ (f(index_u) - K(index_u, index_f) * u(index_f)); 148 | 149 | % Solve for the unknown nodal forces 150 | f(index_f) = K(index_f, :) * u; 151 | 152 | 153 | %---------------------------------------------------------------------- 154 | % Post-process 155 | %---------------------------------------------------------------------- 156 | strain_axial = zeros(numElements, 1); 157 | force_axial = zeros(numElements, 1); 158 | 159 | figure; 160 | 161 | % Draw the undeformed structure first 162 | for i = 1 : numElements 163 | % Get the node indices 164 | nodeIndex1 = elements(i, 1); 165 | nodeIndex2 = elements(i, 2); 166 | 167 | % Get the global coordinates of the nodes 168 | x1 = nodes(nodeIndex1, 1); 169 | y1 = nodes(nodeIndex1, 2); 170 | x2 = nodes(nodeIndex2, 1); 171 | y2 = nodes(nodeIndex2, 2); 172 | 173 | % Draw the undeformed element 174 | line([x1 x2], [y1 y2], 'Color', [0.8 0.9 0.75], 'LineWidth', 2); hold on; 175 | 176 | plot(x1, y1, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 177 | plot(x2, y2, 's', 'Color', [0.7 0.7 0.7], 'MarkerFaceColor', [0.8 0.9 0.75]); hold on; 178 | end 179 | 180 | % Draw the deformed structure 181 | for i = 1 : numElements 182 | % Get the node indices 183 | nodeIndex1 = elements(i, 1); 184 | nodeIndex2 = elements(i, 2); 185 | 186 | % Get the global DOF indices 187 | globalDOFIndex = [gcon(nodeIndex1, 1); ... 188 | gcon(nodeIndex1, 2); ... 189 | gcon(nodeIndex2, 1); ... 190 | gcon(nodeIndex2, 2)]; 191 | 192 | % Get the global coordinates of the nodes 193 | x1 = nodes(nodeIndex1, 1); 194 | y1 = nodes(nodeIndex1, 2); 195 | x2 = nodes(nodeIndex2, 1); 196 | y2 = nodes(nodeIndex2, 2); 197 | 198 | % Get the material properties 199 | E = elements(i, 3); 200 | A = elements(i, 4); 201 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 202 | 203 | % Calculate the cosine and sine values 204 | costheta = (x2 - x1)/L; 205 | sintheta = (y2 - y1)/L; 206 | 207 | % Get the global displacements of the nodes 208 | scale_factor = 1; 209 | ux1 = scale_factor * u(globalDOFIndex(1)); 210 | uy1 = scale_factor * u(globalDOFIndex(2)); 211 | ux2 = scale_factor * u(globalDOFIndex(3)); 212 | uy2 = scale_factor * u(globalDOFIndex(4)); 213 | 214 | % Calculate the axial strain 215 | strain_axial(i) = (ux2 - ux1)/L * costheta + (uy2 - uy1)/L * sintheta; 216 | 217 | % Calculate the axial force 218 | force_axial(i) = E*A * strain_axial(i); 219 | 220 | % Draw the deformed element 221 | line([x1 + ux1, x2 + ux2], [y1 + uy1, y2 + uy2], 'Color', [0.7 0.3 0.3], 'LineWidth', 2); hold on; 222 | 223 | plot(x1 + ux1, y1 + uy1, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 224 | plot(x2 + ux2, y2 + uy2, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.7 0.3 0.3]); hold on; 225 | end 226 | end 227 | -------------------------------------------------------------------------------- /truss_3d/3dtruss_problem1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss_3d/3dtruss_problem1.mat -------------------------------------------------------------------------------- /truss_3d/3dtruss_problem2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss_3d/3dtruss_problem2.mat -------------------------------------------------------------------------------- /truss_3d/3dtruss_problem3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss_3d/3dtruss_problem3.mat -------------------------------------------------------------------------------- /truss_3d/3dtruss_problem4.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss_3d/3dtruss_problem4.mat -------------------------------------------------------------------------------- /truss_3d/3dtruss_problem5.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/truss_3d/3dtruss_problem5.mat -------------------------------------------------------------------------------- /truss_3d/assembly_3dtruss.m: -------------------------------------------------------------------------------- 1 | function [u, f, strain_axial, force_axial, gcon] = assembly_3dtruss() 2 | clc; 3 | format long; 4 | 5 | % Load the assembly file 6 | load('3dtruss_problem4'); 7 | 8 | % Find the number of nodes, etc. 9 | numNodes = size(nodes, 1); 10 | numElements = size(elements, 1); 11 | numBCs_displacement = size(BCs_displacement, 1); 12 | numBCs_force = size(BCs_force, 1); 13 | 14 | % Find the number of degrees of freedom (DOFs) for a truss 15 | % Note, numBCs_displacement + numBCs_force = numDOFs 16 | numDOFs = 3*numNodes; 17 | 18 | 19 | %---------------------------------------------------------------------- 20 | % Set up the global connectivity array called gcon, which returns the 21 | % global DOF index when given the node index and the local DOF index. 22 | % 23 | % Initially, gcon is a (numNodes) x 3 double array with these entries: 24 | % 25 | % local dof index 26 | % 27 | % 1 2 3 28 | % 29 | % node 1 1 2 3 30 | % index 2 4 5 6 31 | % 3 7 8 9 32 | % ... ... ... 33 | % numNodes (3*numNodes - 2) (3*numNodes - 1) (3*numNodes) 34 | % 35 | % We plan to have the bottom entries of the DOF vector u correspond 36 | % to the DOFs that are already known (given as the displacement BCs). 37 | % So we do not actually create gcon with the entries above just yet, 38 | % but assume its existence. 39 | % 40 | % First, create a vector that tags all global DOF indices corresponding 41 | % to the displacement BCs. As the number of displacement BCs is likely 42 | % few in comparison to the total number of DOFs, we let the vector be 43 | % a sparse vector. 44 | %---------------------------------------------------------------------- 45 | tag = sparse(BCs_displacement(:, 1), BCs_displacement(:, 2), ones(numBCs_displacement, 1), numNodes, 3); 46 | tag = reshape(tag', numDOFs, 1); 47 | 48 | %---------------------------------------------------------------------- 49 | % tag is now a vector of zeros and ones, where the ones correspond to 50 | % to the displacement BCs. Sort this vector in ascending order, and 51 | % keep track of the permutation that was done. 52 | %---------------------------------------------------------------------- 53 | [temp, permutation] = sort(tag); 54 | 55 | %---------------------------------------------------------------------- 56 | % Create the gcon array 57 | %---------------------------------------------------------------------- 58 | gcon(permutation) = (1 : numDOFs)'; 59 | gcon = reshape(gcon, 3, numNodes)'; 60 | 61 | % Indices corresponding to the unknown displacements (known forces) 62 | index_u = (1 : numBCs_force)'; 63 | 64 | % Vector of indices of the unknown forces (known displacements) 65 | index_f = ((numBCs_force + 1) : numDOFs)'; 66 | 67 | 68 | %---------------------------------------------------------------------- 69 | % Create the global stiffness matrix K 70 | %---------------------------------------------------------------------- 71 | % Each element matrix is 6 x 6, so there are (36*numElements) many elements 72 | % that we will need to compute to find the global stiffness matrix K 73 | numEntries = 36*numElements; 74 | 75 | % Initialize the I, J, value arrays 76 | I = zeros(numEntries, 1); 77 | J = zeros(numEntries, 1); 78 | value = zeros(numEntries, 1); 79 | 80 | % Temporary variables useful for assembly 81 | i = (1 : 36)'; 82 | vecones = ones(6, 1); 83 | 84 | %---------------------------------------------------------------------- 85 | % Loop over the elements 86 | %---------------------------------------------------------------------- 87 | for e = 1 : numElements 88 | % Get the node indices 89 | nodeIndex1 = elements(e, 1); 90 | nodeIndex2 = elements(e, 2); 91 | 92 | % Get the global DOF indices 93 | globalDOFIndex = [gcon(nodeIndex1, 1); ... 94 | gcon(nodeIndex1, 2); ... 95 | gcon(nodeIndex1, 3); ... 96 | gcon(nodeIndex2, 1); ... 97 | gcon(nodeIndex2, 2); ... 98 | gcon(nodeIndex2, 3)]; 99 | 100 | % Get the global coordinates of the nodes 101 | x1 = nodes(nodeIndex1, 1); 102 | y1 = nodes(nodeIndex1, 2); 103 | z1 = nodes(nodeIndex1, 3); 104 | x2 = nodes(nodeIndex2, 1); 105 | y2 = nodes(nodeIndex2, 2); 106 | z2 = nodes(nodeIndex2, 3); 107 | 108 | % Get the material properties 109 | E = elements(e, 3); 110 | A = elements(e, 4); 111 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2); 112 | 113 | % Calculate the directional cosines 114 | costhetaAx = (x2 - x1)/L; 115 | costhetaAy = (y2 - y1)/L; 116 | costhetaAz = (z2 - z1)/L; 117 | 118 | %------------------------------------------------------------------ 119 | % Form the element matrix 120 | %------------------------------------------------------------------ 121 | temp = [costhetaAx*costhetaAx, costhetaAx*costhetaAy, costhetaAx*costhetaAz; ... 122 | costhetaAy*costhetaAx, costhetaAy*costhetaAy, costhetaAy*costhetaAz; ... 123 | costhetaAz*costhetaAx, costhetaAz*costhetaAy, costhetaAz*costhetaAz]; 124 | K_e = E*A/L * [ temp, -temp; ... 125 | -temp, temp]; 126 | 127 | %------------------------------------------------------------------ 128 | % Global assembly 129 | %------------------------------------------------------------------ 130 | I(i) = kron(globalDOFIndex, vecones); 131 | J(i) = kron(vecones, globalDOFIndex); 132 | value(i) = reshape(K_e, 36, 1); 133 | i = i + 36; 134 | end 135 | 136 | K = sparse(I, J, value, numDOFs, numDOFs); 137 | clear I J value K_e temp vecones; 138 | 139 | %---------------------------------------------------------------------- 140 | % Solve for the unknown displacements and forces 141 | %---------------------------------------------------------------------- 142 | % Initialize the solution vector and the RHS external force vector 143 | u = zeros(numDOFs, 1); 144 | f = zeros(numDOFs, 1); 145 | 146 | % Prescribe the displacements 147 | u(index_f) = BCs_displacement(:, 3); 148 | 149 | % Prescribe the nodal forces 150 | f(index_u) = BCs_force(:, 3); 151 | 152 | % Solve for the unknown displacements 153 | u(index_u) = K(index_u, index_u) \ (f(index_u) - K(index_u, index_f) * u(index_f)); 154 | 155 | % Solve for the unknown nodal forces 156 | f(index_f) = K(index_f, :) * u; 157 | 158 | 159 | %---------------------------------------------------------------------- 160 | % Post-process 161 | %---------------------------------------------------------------------- 162 | strain_axial = zeros(numElements, 1); 163 | force_axial = zeros(numElements, 1); 164 | 165 | for i = 1 : numElements 166 | % Get the node indices 167 | nodeIndex1 = elements(i, 1); 168 | nodeIndex2 = elements(i, 2); 169 | 170 | % Get the global DOF indices 171 | globalDOFIndex = [gcon(nodeIndex1, 1); ... 172 | gcon(nodeIndex1, 2); ... 173 | gcon(nodeIndex1, 3); ... 174 | gcon(nodeIndex2, 1); ... 175 | gcon(nodeIndex2, 2); ... 176 | gcon(nodeIndex2, 3)]; 177 | 178 | % Get the global coordinates of the nodes 179 | x1 = nodes(nodeIndex1, 1); 180 | y1 = nodes(nodeIndex1, 2); 181 | z1 = nodes(nodeIndex1, 3); 182 | x2 = nodes(nodeIndex2, 1); 183 | y2 = nodes(nodeIndex2, 2); 184 | z2 = nodes(nodeIndex2, 3); 185 | 186 | % Get the material properties 187 | E = elements(i, 3); 188 | A = elements(i, 4); 189 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2); 190 | 191 | % Calculate the cosine and sine values 192 | costhetaAx = (x2 - x1)/L; 193 | costhetaAy = (y2 - y1)/L; 194 | costhetaAz = (z2 - z1)/L; 195 | 196 | % Get the global displacements of the nodes 197 | ux1 = u(globalDOFIndex(1)); 198 | uy1 = u(globalDOFIndex(2)); 199 | uz1 = u(globalDOFIndex(3)); 200 | ux2 = u(globalDOFIndex(4)); 201 | uy2 = u(globalDOFIndex(5)); 202 | uz2 = u(globalDOFIndex(6)); 203 | 204 | % Calculate the axial strain 205 | strain_axial(i) = (ux2 - ux1)/L * costhetaAx + (uy2 - uy1)/L * costhetaAy + (uz2 - uz1)/L * costhetaAz; 206 | 207 | % Calculate the axial force 208 | force_axial(i) = E*A * strain_axial(i); 209 | end 210 | 211 | u(permutation) = u; 212 | f(permutation) = f; 213 | end -------------------------------------------------------------------------------- /updated/demo1_gui_truss_analysis/bridge.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo1_gui_truss_analysis/bridge.mat -------------------------------------------------------------------------------- /updated/demo2_analyze_2dframe.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: 3 | % 4 | % Isaac J. Lee (crunchingnumbers.live) 5 | % 6 | % Summary: 7 | % 8 | % This routine solves the problem of a bridge frame subject to a load 9 | % on its bottom using finite element method. In particular, we consider 10 | % the Hermite cubic polynomials to approximate the displacement field. 11 | % 12 | % Instructions: 13 | % 14 | % Type the following onto Matlab's command window: 15 | % 16 | % demo2_analyze_2dframe 17 | % 18 | %-------------------------------------------------------------------------- 19 | function demo2_analyze_2dframe() 20 | clc; 21 | close all; 22 | 23 | 24 | %---------------------------------------------------------------------- 25 | % Load the assembly file 26 | %---------------------------------------------------------------------- 27 | addpath('./demo2_analyze_truss_frame/'); 28 | 29 | load('demo2_analyze_truss_frame/assembly_bridge'); 30 | 31 | 32 | % Find the number of nodes, etc. from the assembly file 33 | numNodes = size(nodes, 1); 34 | numElements = size(elements, 1); 35 | numBCs_displacement = size(BCs_displacement, 1); 36 | numBCs_force = size(BCs_force, 1); 37 | 38 | % Find the number of degrees of freedom (DOFs) for 2D frame problem 39 | numDOFsPerNode = 3; 40 | numDOFs = numDOFsPerNode * numNodes; 41 | 42 | if (numBCs_displacement + numBCs_force ~= numDOFs) 43 | error('Error: Please check the BCs.'); 44 | end 45 | 46 | 47 | %---------------------------------------------------------------------- 48 | % --------------------------------------------------------------------- 49 | % Set the global connectivity array called gcon, which returns the 50 | % global DOF index when given the node index and the local DOF index. 51 | % 52 | % Had no displacement or rotation BCs been specified, gcon would 53 | % contain these entries: 54 | % 55 | % local dof index 56 | % 57 | % 1 (u_x) 2 (u_y) 3 (theta) 58 | % 59 | % node 1 1 2 3 60 | % index 2 4 5 6 61 | % 3 7 8 9 62 | % ... ... ... 63 | % numNodes (3*numNodes - 2) (3*numNodes - 1) (3*numNodes) 64 | % 65 | % We set gcon so that all the known displacements will be on the 66 | % bottom side of u and all the known forces on the top side of f. 67 | % While we populate the gcon array, we prescribe the known values 68 | % into the vectors u and f. 69 | % --------------------------------------------------------------------- 70 | %---------------------------------------------------------------------- 71 | % Initialize the gcon (global connectivity) array 72 | gcon = zeros(numNodes, numDOFsPerNode); 73 | 74 | % Initialize the solution and the RHS vectors 75 | u = zeros(numDOFs, 1); 76 | f = zeros(numDOFs, 1); 77 | 78 | % index_f stores all the indices corresponding to the known forces, 79 | % and index_u all the indices corresponding to the known displacements. 80 | index_f = 1 : numBCs_force; 81 | index_u = (numBCs_force + 1) : numDOFs; 82 | 83 | % Prescribe the forces 84 | count = 1; 85 | for i = 1 : numBCs_force 86 | gcon(BCs_force(i, 1), BCs_force(i, 2)) = count; 87 | f(count) = BCs_force(i, 3); 88 | count = count + 1; 89 | end 90 | 91 | % Prescribe the displacements 92 | for i = 1 : numBCs_displacement 93 | gcon(BCs_displacement(i, 1), BCs_displacement(i, 2)) = count; 94 | u(count) = BCs_displacement(i, 3); 95 | count = count + 1; 96 | end 97 | 98 | 99 | %---------------------------------------------------------------------- 100 | % --------------------------------------------------------------------- 101 | % Create the global stiffness matrix K 102 | % --------------------------------------------------------------------- 103 | %---------------------------------------------------------------------- 104 | % The number of entries that we need to compute to form the global 105 | % stiffness matrix (Hermite cubic polynomial element has 2 nodes) 106 | numDOFsPerElement = 2 * numDOFsPerNode; 107 | numEntries = numDOFsPerElement^2 * numElements; 108 | 109 | % Initialize the I, J, value arrays 110 | I = zeros(numEntries, 1); 111 | J = zeros(numEntries, 1); 112 | value = zeros(numEntries, 1); 113 | 114 | % Counter for assembly 115 | count = 1; 116 | 117 | 118 | %---------------------------------------------------------------------- 119 | % Loop over the elements 120 | %---------------------------------------------------------------------- 121 | for e = 1 : numElements 122 | % Get the node indices 123 | node1Index = elements(e, 1); 124 | node2Index = elements(e, 2); 125 | 126 | % Get the nodal positions 127 | x1 = nodes(node1Index, 1); 128 | y1 = nodes(node1Index, 2); 129 | x2 = nodes(node2Index, 1); 130 | y2 = nodes(node2Index, 2); 131 | 132 | % Get the element properties 133 | E = elements(e, 3); 134 | A = elements(e, 4); 135 | Ii = elements(e, 5); 136 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 137 | 138 | % Calculate the directional cosines 139 | costhetaAx = (x2 - x1)/L; 140 | costhetaAy = (y2 - y1)/L; 141 | costhetaTx = -costhetaAy; 142 | costhetaTy = costhetaAx; 143 | 144 | % Calculate the local-to-global coordinate transformation matrix 145 | Q = [costhetaAx, costhetaAy, 0; 146 | costhetaTx, costhetaTy, 0; 147 | 0, 0, 1]; 148 | 149 | 150 | %------------------------------------------------------------------ 151 | % Form the element matrix 152 | %------------------------------------------------------------------ 153 | % Element matrix in local coordinates 154 | K_e = [ E*A/L, 0, 0, -E*A/L, 0, 0; ... 155 | 0, 12*E*Ii/L^3, 6*E*Ii/L^2, 0, -12*E*Ii/L^3, 6*E*Ii/L^2; ... 156 | 0, 6*E*Ii/L^2, 4*E*Ii/L, 0, -6*E*Ii/L^2, 2*E*Ii/L; ... 157 | -E*A/L, 0, 0, E*A/L, 0, 0; ... 158 | 0, -12*E*Ii/L^3, -6*E*Ii/L^2, 0, 12*E*Ii/L^3, -6*E*Ii/L^2; ... 159 | 0, 6*E*Ii/L^2, 2*E*Ii/L, 0, -6*E*Ii/L^2, 4*E*Ii/L]; 160 | 161 | % Apply coordinate transformation 162 | K_e(1:3, 1:3) = Q' * K_e(1:3, 1:3) * Q; 163 | K_e(1:3, 4:6) = Q' * K_e(1:3, 4:6) * Q; 164 | K_e(4:6, 1:3) = Q' * K_e(4:6, 1:3) * Q; 165 | K_e(4:6, 4:6) = Q' * K_e(4:6, 4:6) * Q; 166 | 167 | 168 | %------------------------------------------------------------------ 169 | % Global assembly 170 | %------------------------------------------------------------------ 171 | % Get the DOF indices 172 | index = [gcon(node1Index, 1); ... 173 | gcon(node1Index, 2); ... 174 | gcon(node1Index, 3); ... 175 | gcon(node2Index, 1); ... 176 | gcon(node2Index, 2); ... 177 | gcon(node2Index, 3)]; 178 | 179 | % Assign the entries 180 | for i = 1 : numDOFsPerElement 181 | for j = 1 : numDOFsPerElement 182 | % Use these lines if K is declared as a sparse matrix 183 | I(count) = index(i); 184 | J(count) = index(j); 185 | value(count) = K_e(i, j); 186 | 187 | count = count + 1; 188 | end 189 | end 190 | end 191 | 192 | if (numEntries ~= count - 1) 193 | error('Error: Check the code.'); 194 | end 195 | 196 | K = sparse(I, J, value, numDOFs, numDOFs); 197 | clear K_e I J value index; 198 | 199 | 200 | 201 | %---------------------------------------------------------------------- 202 | % --------------------------------------------------------------------- 203 | % Solve for the unknown displacements and forces 204 | % --------------------------------------------------------------------- 205 | %---------------------------------------------------------------------- 206 | % Solve for the unknown displacements 207 | u(index_f) = K(index_f, index_f) \ (f(index_f) - K(index_f, index_u) * u(index_u)); 208 | 209 | % Solve for the unknown forces 210 | % f(index_u) = K(index_u, index_f) * u(index_f) + K(index_u, index_u) * u(index_u); 211 | 212 | 213 | %---------------------------------------------------------------------- 214 | % Post-process 215 | %---------------------------------------------------------------------- 216 | draw_frame(nodes, elements, u, gcon); 217 | end -------------------------------------------------------------------------------- /updated/demo2_analyze_2dtruss.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: 3 | % 4 | % Isaac J. Lee (crunchingnumbers.live) 5 | % 6 | % Summary: 7 | % 8 | % This routine solves the problem of a bridge truss subject to a load 9 | % on its bottom using finite element method. In particular, we consider 10 | % the linear polynomials to approximate the displacement field. 11 | % 12 | % Instructions: 13 | % 14 | % Type the following onto Matlab's command window: 15 | % 16 | % demo2_analyze_2dtruss 17 | % 18 | %-------------------------------------------------------------------------- 19 | function demo2_analyze_2dtruss() 20 | clc; 21 | close all; 22 | 23 | 24 | %---------------------------------------------------------------------- 25 | % Load the assembly file 26 | %---------------------------------------------------------------------- 27 | addpath('./demo2_analyze_truss_frame/'); 28 | 29 | load('demo2_analyze_truss_frame/assembly_bridge'); 30 | 31 | 32 | % Eliminate the rotation BCs 33 | BCs_displacement(BCs_displacement(:, 2) == 3, :) = []; 34 | 35 | % Eliminate the moment BCs 36 | BCs_force(BCs_force(:, 2) == 3, :) = []; 37 | 38 | 39 | % Find the number of nodes, etc. from the assembly file 40 | numNodes = size(nodes, 1); 41 | numElements = size(elements, 1); 42 | numBCs_displacement = size(BCs_displacement, 1); 43 | numBCs_force = size(BCs_force, 1); 44 | 45 | % Find the number of degrees of freedom (DOFs) for 2D truss problem 46 | numDOFsPerNode = 2; 47 | numDOFs = numDOFsPerNode * numNodes; 48 | 49 | if (numBCs_displacement + numBCs_force ~= numDOFs) 50 | error('Error: Please check the BCs.'); 51 | end 52 | 53 | 54 | %---------------------------------------------------------------------- 55 | % --------------------------------------------------------------------- 56 | % Set the global connectivity array called gcon, which returns the 57 | % global DOF index when given the node index and the local DOF index. 58 | % 59 | % Had no displacement BCs been specified, gcon would contain these 60 | % entries: 61 | % 62 | % local dof index 63 | % 64 | % 1 2 65 | % 66 | % node 1 1 2 67 | % index 2 3 4 68 | % 3 5 6 69 | % ... ... ... 70 | % numNodes (2*numNodes - 1) (2*numNodes) 71 | % 72 | % We set gcon so that all the known displacements will be on the 73 | % bottom side of u and all the known forces on the top side of f. 74 | % While we populate the gcon array, we prescribe the known values 75 | % into the vectors u and f. 76 | % --------------------------------------------------------------------- 77 | %---------------------------------------------------------------------- 78 | % Initialize the gcon (global connectivity) array 79 | gcon = zeros(numNodes, numDOFsPerNode); 80 | 81 | % Initialize the solution and the RHS vectors 82 | u = zeros(numDOFs, 1); 83 | f = zeros(numDOFs, 1); 84 | 85 | % index_f stores all the indices corresponding to the known forces, 86 | % and index_u all the indices corresponding to the known displacements. 87 | index_f = 1 : numBCs_force; 88 | index_u = (numBCs_force + 1) : numDOFs; 89 | 90 | % Prescribe the forces 91 | count = 1; 92 | for i = 1 : numBCs_force 93 | gcon(BCs_force(i, 1), BCs_force(i, 2)) = count; 94 | f(count) = BCs_force(i, 3); 95 | count = count + 1; 96 | end 97 | 98 | % Prescribe the displacements 99 | for i = 1 : numBCs_displacement 100 | gcon(BCs_displacement(i, 1), BCs_displacement(i, 2)) = count; 101 | u(count) = BCs_displacement(i, 3); 102 | count = count + 1; 103 | end 104 | 105 | 106 | 107 | %---------------------------------------------------------------------- 108 | % --------------------------------------------------------------------- 109 | % Create the global stiffness matrix K 110 | % --------------------------------------------------------------------- 111 | %---------------------------------------------------------------------- 112 | % The number of entries that we need to compute to form the global 113 | % stiffness matrix (linear polynomial element has 2 nodes) 114 | numDOFsPerElement = 2 * numDOFsPerNode; 115 | numEntries = numDOFsPerElement^2 * numElements; 116 | 117 | % Initialize the I, J, value arrays 118 | I = zeros(numEntries, 1); 119 | J = zeros(numEntries, 1); 120 | value = zeros(numEntries, 1); 121 | 122 | % Counter for assembly 123 | count = 1; 124 | 125 | 126 | %---------------------------------------------------------------------- 127 | % Loop over the elements 128 | %---------------------------------------------------------------------- 129 | for e = 1 : numElements 130 | % Get the node indices 131 | node1Index = elements(e, 1); 132 | node2Index = elements(e, 2); 133 | 134 | % Get the nodal positions 135 | x1 = nodes(node1Index, 1); 136 | y1 = nodes(node1Index, 2); 137 | x2 = nodes(node2Index, 1); 138 | y2 = nodes(node2Index, 2); 139 | 140 | % Get the element properties 141 | E = elements(e, 3); 142 | A = elements(e, 4); 143 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 144 | 145 | % Calculate the cosine and sine values 146 | costheta = (x2 - x1)/L; 147 | sintheta = (y2 - y1)/L; 148 | 149 | 150 | %------------------------------------------------------------------ 151 | % Form the element matrix 152 | %------------------------------------------------------------------ 153 | temp = [costheta * costheta, costheta * sintheta; ... 154 | costheta * sintheta, sintheta * sintheta]; 155 | 156 | K_e = E*A/L * [ temp, -temp; ... 157 | -temp, temp]; 158 | 159 | 160 | %------------------------------------------------------------------ 161 | % Global assembly 162 | %------------------------------------------------------------------ 163 | % Get the DOF indices 164 | index = [gcon(node1Index, 1); ... 165 | gcon(node1Index, 2); ... 166 | gcon(node2Index, 1); ... 167 | gcon(node2Index, 2)]; 168 | 169 | % Assign the entries 170 | for i = 1 : numDOFsPerElement 171 | for j = 1 : numDOFsPerElement 172 | % Use these lines if K is declared as a sparse matrix 173 | I(count) = index(i); 174 | J(count) = index(j); 175 | value(count) = K_e(i, j); 176 | 177 | count = count + 1; 178 | end 179 | end 180 | end 181 | 182 | if (numEntries ~= count - 1) 183 | error('Error: Check the code.'); 184 | end 185 | 186 | K = sparse(I, J, value, numDOFs, numDOFs); 187 | clear K_e I J value index; 188 | 189 | 190 | 191 | %---------------------------------------------------------------------- 192 | % --------------------------------------------------------------------- 193 | % Solve for the unknown displacements and forces 194 | % --------------------------------------------------------------------- 195 | %---------------------------------------------------------------------- 196 | % Solve for the unknown displacements 197 | u(index_f) = K(index_f, index_f) \ (f(index_f) - K(index_f, index_u) * u(index_u)); 198 | 199 | % Solve for the unknown forces 200 | % f(index_u) = K(index_u, index_f) * u(index_f) + K(index_u, index_u) * u(index_u); 201 | 202 | 203 | %---------------------------------------------------------------------- 204 | % Post-process 205 | %---------------------------------------------------------------------- 206 | draw_truss(nodes, elements, u, gcon); 207 | end 208 | -------------------------------------------------------------------------------- /updated/demo2_analyze_truss_frame/assembly_bridge.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo2_analyze_truss_frame/assembly_bridge.mat -------------------------------------------------------------------------------- /updated/demo2_analyze_truss_frame/draw_frame.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: 3 | % 4 | % Isaac J. Lee (crunchingnumbers.live) 5 | % 6 | % Summary: 7 | % 8 | % This postprocessing routine shows how a frame is deformed due to 9 | % applied displacements and loads. 10 | % 11 | % Instructions: 12 | % 13 | % Call this routine after the frame solution has been found: 14 | % 15 | % draw_frame 16 | % 17 | %-------------------------------------------------------------------------- 18 | function draw_frame(nodes, elements, u, gcon) 19 | % Create a new figure 20 | figure('Units' , 'normalized', ... 21 | 'OuterPosition' , [0 0 1 1], ... 22 | 'Color' , [1 1 1], ... 23 | 'InvertHardcopy' , 'off', ... 24 | 'MenuBar' , 'none', ... 25 | 'NumberTitle' , 'off', ... 26 | 'Resize' , 'on', ... 27 | 'PaperUnits' , 'points', ... 28 | 'PaperPosition' , [0 0 800 600], ... 29 | 'PaperPositionMode', 'auto'); 30 | 31 | 32 | % Find the number of elements 33 | numElements = size(elements, 1); 34 | 35 | % Number of points between two nodes 36 | numPoints = 1000; 37 | 38 | 39 | % Draw the undeformed structure first 40 | for i = 1 : numElements 41 | % Get the node indices 42 | nodeIndex1 = elements(i, 1); 43 | nodeIndex2 = elements(i, 2); 44 | 45 | % Get the nodal positions in the global coordinates 46 | x1 = nodes(nodeIndex1, 1); 47 | y1 = nodes(nodeIndex1, 2); 48 | x2 = nodes(nodeIndex2, 1); 49 | y2 = nodes(nodeIndex2, 2); 50 | 51 | % Set the initial positions 52 | x = linspace(x1, x2, numPoints + 1); 53 | y = linspace(y1, y2, numPoints + 1); 54 | 55 | % Draw the undeformed element 56 | plot(x, y, 'Color', [0.80 0.90 0.75], 'LineWidth', 3.5); hold on; 57 | 58 | % Draw the nodes 59 | plot(x1, y1, 's', 'Color', [0.70 0.70 0.70], 'MarkerFaceColor', [0.40 0.90 0.60], 'MarkerSize', 12); hold on; 60 | plot(x2, y2, 's', 'Color', [0.70 0.70 0.70], 'MarkerFaceColor', [0.40 0.90 0.60], 'MarkerSize', 12); hold on; 61 | end 62 | 63 | 64 | % Draw the deformed structure next 65 | for i = 1 : numElements 66 | % Get the node indices 67 | nodeIndex1 = elements(i, 1); 68 | nodeIndex2 = elements(i, 2); 69 | 70 | % Get the nodal positions in the global coordinates 71 | x1 = nodes(nodeIndex1, 1); 72 | y1 = nodes(nodeIndex1, 2); 73 | x2 = nodes(nodeIndex2, 1); 74 | y2 = nodes(nodeIndex2, 2); 75 | 76 | % Initialize the final positions 77 | x = linspace(x1, x2, numPoints + 1)'; 78 | y = linspace(y1, y2, numPoints + 1)'; 79 | 80 | % Get the bar's length 81 | L = sqrt((x2 - x1)^2 + (y2 - y1)^2); 82 | 83 | % Calculate the cosine and sine values 84 | costhetaAx = (x2 - x1)/L; 85 | costhetaAy = (y2 - y1)/L; 86 | costhetaTx = -costhetaAy; 87 | costhetaTy = costhetaAx; 88 | 89 | % Get the DOF indices 90 | index = [gcon(nodeIndex1, 1); ... 91 | gcon(nodeIndex1, 2); ... 92 | gcon(nodeIndex1, 3); ... 93 | gcon(nodeIndex2, 1); ... 94 | gcon(nodeIndex2, 2); ... 95 | gcon(nodeIndex2, 3)]; 96 | 97 | % Get the nodal displacements in the global coordinates 98 | u1x = u(index(1)); 99 | u1y = u(index(2)); 100 | theta1 = u(index(3)); 101 | u2x = u(index(4)); 102 | u2y = u(index(5)); 103 | theta2 = u(index(6)); 104 | 105 | % Calculuate the nodal displacements in the local coordinates 106 | % (the rotation DOFs remain the same) 107 | u1A = u1x * costhetaAx + u1y * costhetaAy; 108 | u1T = u1x * costhetaTx + u1y * costhetaTy; 109 | u2A = u2x * costhetaAx + u2y * costhetaAy; 110 | u2T = u2x * costhetaTx + u2y * costhetaTy; 111 | 112 | % For convenience, normalize the axial coordinate 113 | x_local = linspace(0, L, numPoints + 1)'; 114 | x_local = x_local / L; 115 | 116 | % Find the axial displacement of the bar 117 | u_h = u1A*(1 - x_local) + u2A*x_local; 118 | 119 | % Find the transversal displacement of the bar 120 | v_h = u1T*(2*x_local.^3 - 3*x_local.^2 + 1) + theta1*(x_local.^3 - 2*x_local.^2 + x_local)/L + u2T*(-2*x_local.^3 + 3*x_local.^2) + theta2*(x_local.^3 - x_local.^2)/L; 121 | 122 | % Find the x- and y-displacements of the bar 123 | ux_h = u_h * costhetaAx + v_h * costhetaTx; 124 | uy_h = u_h * costhetaAy + v_h * costhetaTy; 125 | 126 | % Find the final positions 127 | x = x + ux_h; 128 | y = y + uy_h; 129 | 130 | % Draw the deformed element 131 | plot(x, y, 'Color', [0.70 0.30 0.30], 'LineWidth', 3.5); hold on; 132 | 133 | % Draw the nodes 134 | plot(x1 + ux_h(1) , y1 + uy_h(1) , 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.95 0.60 0.70], 'MarkerSize', 12); hold on; 135 | plot(x2 + ux_h(end), y2 + uy_h(end), 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.95 0.60 0.70], 'MarkerSize', 12); hold on; 136 | end 137 | 138 | 139 | axis([-4 39 -2.5 12.5]); 140 | 141 | set(gca, 'FontSize', 32, 'XTick', linspace(0, 35, 8), 'YTick', linspace(0, 10, 3)); 142 | 143 | % print('-dpng' , '-r300', 'plot_displacement_frame.png'); 144 | end -------------------------------------------------------------------------------- /updated/demo2_analyze_truss_frame/draw_truss.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: 3 | % 4 | % Isaac J. Lee (crunchingnumbers.live) 5 | % 6 | % Summary: 7 | % 8 | % This postprocessing routine shows how a truss is deformed due to 9 | % applied displacements and loads. 10 | % 11 | % Instructions: 12 | % 13 | % Call this routine after the truss solution has been found: 14 | % 15 | % draw_truss 16 | % 17 | %-------------------------------------------------------------------------- 18 | function draw_truss(nodes, elements, u, gcon) 19 | % Create a new figure 20 | figure('Units' , 'normalized', ... 21 | 'OuterPosition' , [0 0 1 1], ... 22 | 'Color' , [1 1 1], ... 23 | 'InvertHardcopy' , 'off', ... 24 | 'MenuBar' , 'none', ... 25 | 'NumberTitle' , 'off', ... 26 | 'Resize' , 'on', ... 27 | 'PaperUnits' , 'points', ... 28 | 'PaperPosition' , [0 0 800 600], ... 29 | 'PaperPositionMode', 'auto'); 30 | 31 | 32 | % Find the number of elements 33 | numElements = size(elements, 1); 34 | 35 | % Draw the undeformed structure first 36 | for i = 1 : numElements 37 | % Get the node indices 38 | nodeIndex1 = elements(i, 1); 39 | nodeIndex2 = elements(i, 2); 40 | 41 | % Get the nodal positions in the global coordinates 42 | x1 = nodes(nodeIndex1, 1); 43 | y1 = nodes(nodeIndex1, 2); 44 | x2 = nodes(nodeIndex2, 1); 45 | y2 = nodes(nodeIndex2, 2); 46 | 47 | % Draw the undeformed element 48 | line([x1 x2], [y1 y2], 'Color', [0.80 0.90 0.75], 'LineWidth', 3.5); hold on; 49 | 50 | % Draw the nodes 51 | plot(x1, y1, 's', 'Color', [0.70 0.70 0.70], 'MarkerFaceColor', [0.40 0.90 0.60], 'MarkerSize', 12); hold on; 52 | plot(x2, y2, 's', 'Color', [0.70 0.70 0.70], 'MarkerFaceColor', [0.40 0.90 0.60], 'MarkerSize', 12); hold on; 53 | end 54 | 55 | 56 | % Draw the deformed structure next 57 | for i = 1 : numElements 58 | % Get the node indices 59 | nodeIndex1 = elements(i, 1); 60 | nodeIndex2 = elements(i, 2); 61 | 62 | % Get the nodal positions in the global coordinates 63 | x1 = nodes(nodeIndex1, 1); 64 | y1 = nodes(nodeIndex1, 2); 65 | x2 = nodes(nodeIndex2, 1); 66 | y2 = nodes(nodeIndex2, 2); 67 | 68 | % Get the DOF indices 69 | index = [gcon(nodeIndex1, 1); ... 70 | gcon(nodeIndex1, 2); ... 71 | gcon(nodeIndex2, 1); ... 72 | gcon(nodeIndex2, 2)]; 73 | 74 | % Get the nodal displacements in the global coordinates 75 | u1x = u(index(1)); 76 | u1y = u(index(2)); 77 | u2x = u(index(3)); 78 | u2y = u(index(4)); 79 | 80 | % Draw the deformed element 81 | line([x1 + u1x, x2 + u2x], [y1 + u1y, y2 + u2y], 'Color', [0.70 0.30 0.30], 'LineWidth', 3.5); hold on; 82 | 83 | % Draw the nodes 84 | plot(x1 + u1x, y1 + u1y, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.95 0.60 0.70], 'MarkerSize', 12); hold on; 85 | plot(x2 + u2x, y2 + u2y, 's', 'Color', [0 0 0], 'MarkerFaceColor', [0.95 0.60 0.70], 'MarkerSize', 12); hold on; 86 | end 87 | 88 | 89 | axis([-4 39 -2.5 12.5]); 90 | 91 | set(gca, 'FontSize', 32, 'XTick', linspace(0, 35, 8), 'YTick', linspace(0, 10, 3)); 92 | 93 | % print('-dpng' , '-r300', 'plot_displacement_truss.png'); 94 | end -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/analyze_1dbar_p1.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: 3 | % 4 | % Isaac J. Lee (crunchingnumbers.live) 5 | % 6 | % Summary: 7 | % 8 | % This routine solves the bar (pile) problem with a Winkler foundation 9 | % using a linear polynomial basis. 10 | % 11 | % Instructions: 12 | % 13 | % Call this routine from the driver file demo3_driver_1dbar_p1: 14 | % 15 | % analyze_1dbar_p1(problem_size) 16 | % 17 | % where problem_size is '01', '02', '04', or '08'. 18 | % 19 | %-------------------------------------------------------------------------- 20 | function analyze_1dbar_p1(problem_size) 21 | %---------------------------------------------------------------------- 22 | % Load the assembly file 23 | %---------------------------------------------------------------------- 24 | load(strcat('./demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p1_numElements', problem_size)); 25 | 26 | 27 | % Find the number of nodes, etc. from the assembly file 28 | numNodes = size(nodes, 1); 29 | numElements = size(elements, 1); 30 | numBCs_displacement = size(BCs_displacement, 1); 31 | numBCs_force = size(BCs_force, 1); 32 | 33 | % Set the number of degrees of freedom (DOFs) for 1D elasticity 34 | numDOFsPerNode = 1; 35 | numDOFs = numDOFsPerNode * numNodes; 36 | 37 | if (numBCs_displacement + numBCs_force ~= numDOFs) 38 | error('Error: Please check the BCs.'); 39 | end 40 | 41 | 42 | 43 | %---------------------------------------------------------------------- 44 | % --------------------------------------------------------------------- 45 | % Set the gcon array so that all the known displacements will be on 46 | % the bottom side of u and all the known forces on the top side of f. 47 | % While we populate the gcon array, we prescribe the known values 48 | % into the vectors u and f. 49 | % --------------------------------------------------------------------- 50 | %---------------------------------------------------------------------- 51 | % Initialize the gcon (global connectivity) array 52 | gcon = zeros(numNodes, numDOFsPerNode); 53 | 54 | % Initialize the solution and the RHS vectors 55 | u = zeros(numDOFs, 1); 56 | f = zeros(numDOFs, 1); 57 | 58 | % index_f stores all the indices corresponding to the known forces, 59 | % and index_u all the indices corresponding to the known displacements. 60 | index_f = 1 : numBCs_force; 61 | index_u = (numBCs_force + 1) : numDOFs; 62 | 63 | % Prescribe the forces 64 | count = 1; 65 | for i = 1 : numBCs_force 66 | gcon(BCs_force(i, 1), BCs_force(i, 2)) = count; 67 | f(count) = BCs_force(i, 3); 68 | count = count + 1; 69 | end 70 | 71 | % Prescribe the displacements 72 | for i = 1 : numBCs_displacement 73 | gcon(BCs_displacement(i, 1), BCs_displacement(i, 2)) = count; 74 | u(count) = BCs_displacement(i, 3); 75 | count = count + 1; 76 | end 77 | 78 | 79 | 80 | %---------------------------------------------------------------------- 81 | % --------------------------------------------------------------------- 82 | % Set the quadrature rule (3-point Gauss quadrature) and evaluate 83 | % the basis functions and their derivatives at the quadrature points 84 | % --------------------------------------------------------------------- 85 | %---------------------------------------------------------------------- 86 | z = [-sqrt(3/5); 0; sqrt(3/5)]; 87 | w = [5/9; 8/9; 5/9]; 88 | numQuadraturePoints = length(z); 89 | 90 | eval_N = @(xi) [0.5 * (1 - xi), ... 91 | 0.5 * (1 + xi)]; 92 | eval_B = @(xi) [-0.5 * ones(length(xi), 1), ... 93 | 0.5 * ones(length(xi), 1)]; 94 | 95 | % Evaluate at the quadrature points 96 | N = eval_N(z); 97 | B = eval_B(z); 98 | 99 | 100 | 101 | %---------------------------------------------------------------------- 102 | % --------------------------------------------------------------------- 103 | % Create the stiffness matrix K and the load vector f 104 | % --------------------------------------------------------------------- 105 | %---------------------------------------------------------------------- 106 | % Initialize the stiffness matrix 107 | K = zeros(numDOFs); 108 | 109 | numNodesPerElement = 2; 110 | numDOFsPerElement = numNodesPerElement * numDOFsPerNode; 111 | 112 | 113 | %---------------------------------------------------------------------- 114 | % Specify the distributed load 115 | %---------------------------------------------------------------------- 116 | P_0 = abs(BCs_force(1, 3)); 117 | L = nodes(numNodes, 1); 118 | eval_distributed_load = @(x) P_0 / L; 119 | 120 | 121 | %---------------------------------------------------------------------- 122 | % Loop over the elements 123 | %---------------------------------------------------------------------- 124 | for e = 1 : numElements 125 | % Get the node indices 126 | node1Index = elements(e, 1); 127 | node2Index = elements(e, 2); 128 | 129 | % Get the nodal positions 130 | x1 = nodes(node1Index, 1); 131 | x2 = nodes(node2Index, 1); 132 | x_e = [x1; x2]; 133 | 134 | % Get the element properties (constant) 135 | E = elements(e, 3); 136 | A = elements(e, 4); 137 | k = E*A / L^2; 138 | 139 | 140 | % Evaluate the elasticity matrix (constant) 141 | C = [E]; 142 | 143 | % Initialize the element stiffness matrix and element load vector 144 | K_e = zeros(numNodesPerElement); 145 | f_e = zeros(numNodesPerElement, 1); 146 | 147 | 148 | %------------------------------------------------------------------ 149 | % Loop over the quadrature points 150 | %------------------------------------------------------------------ 151 | for i = 1 : numQuadraturePoints 152 | % Get the values of the basis functions and their derivatives 153 | % at the quadrature point 154 | N_e = N(i, :); 155 | B_e = B(i, :); 156 | 157 | % Find the point x in the physical domain that corresponds to 158 | % the quadrature point 159 | x = N_e * x_e; 160 | 161 | % Evaluate the Jacobian at the quadrature point 162 | J = B_e * x_e; 163 | 164 | % Evaluate the distributed load at the quadrature point 165 | distributed_load = eval_distributed_load(x); 166 | 167 | 168 | %-------------------------------------------------------------- 169 | % Form the element stiffness matrix 170 | %-------------------------------------------------------------- 171 | K_e = K_e + w(i) * ((A / J) * (B_e' * C * B_e) + (k * J) * (N_e' * N_e)); 172 | 173 | 174 | %-------------------------------------------------------------- 175 | % Form the element load vector 176 | %-------------------------------------------------------------- 177 | f_e = f_e + w(i) * ((distributed_load * J) * N_e'); 178 | end 179 | 180 | 181 | %------------------------------------------------------------------ 182 | % Global assembly 183 | %------------------------------------------------------------------ 184 | % Get the global DOF indices 185 | index = [gcon(node1Index, 1); ... 186 | gcon(node2Index, 1)]; 187 | 188 | % Assign the entries 189 | for i = 1 : numDOFsPerElement 190 | for j = 1 : numDOFsPerElement 191 | K(index(i), index(j)) = K(index(i), index(j)) + K_e(i, j); 192 | end 193 | 194 | f(index(i)) = f(index(i)) + f_e(i); 195 | end 196 | end 197 | 198 | 199 | 200 | %---------------------------------------------------------------------- 201 | % --------------------------------------------------------------------- 202 | % Solve for the unknown displacements and forces 203 | % --------------------------------------------------------------------- 204 | %---------------------------------------------------------------------- 205 | % Solve for the unknown displacements 206 | u(index_f) = K(index_f, index_f) \ (f(index_f) - K(index_f, index_u) * u(index_u)); 207 | 208 | % Solve for the unknown forces 209 | f(index_u) = K(index_u, index_f) * u(index_f) + K(index_u, index_u) * u(index_u); 210 | 211 | 212 | save(strcat('./demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p1_numElements', problem_size), 'u', 'f', 'gcon', '-v7.3'); 213 | end -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/analyze_1dbar_p2.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: 3 | % 4 | % Isaac J. Lee (crunchingnumbers.live) 5 | % 6 | % Summary: 7 | % 8 | % This routine solves the bar (pile) problem with a Winkler foundation 9 | % using a quadratic polynomial basis. 10 | % 11 | % Instructions: 12 | % 13 | % Call this routine from the driver file demo3_driver_1dbar_p2: 14 | % 15 | % analyze_1dbar_p2(problem_size) 16 | % 17 | % where problem_size is '01', '02', '04', or '08'. 18 | % 19 | %-------------------------------------------------------------------------- 20 | function analyze_1dbar_p2(problem_size) 21 | %---------------------------------------------------------------------- 22 | % Load the assembly file 23 | %---------------------------------------------------------------------- 24 | load(strcat('./demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p2_numElements', problem_size)); 25 | 26 | 27 | % Find the number of nodes, etc. from the assembly file 28 | numNodes = size(nodes, 1); 29 | numElements = size(elements, 1); 30 | numBCs_displacement = size(BCs_displacement, 1); 31 | numBCs_force = size(BCs_force, 1); 32 | 33 | % Set the number of degrees of freedom (DOFs) for 1D elasticity 34 | numDOFsPerNode = 1; 35 | numDOFs = numDOFsPerNode * numNodes; 36 | 37 | if (numBCs_displacement + numBCs_force ~= numDOFs) 38 | error('Error: Please check the BCs.'); 39 | end 40 | 41 | 42 | 43 | %---------------------------------------------------------------------- 44 | % --------------------------------------------------------------------- 45 | % Set the gcon array so that all the known displacements will be on 46 | % the bottom side of u and all the known forces on the top side of f. 47 | % While we populate the gcon array, we prescribe the known values 48 | % into the vectors u and f. 49 | % --------------------------------------------------------------------- 50 | %---------------------------------------------------------------------- 51 | % Initialize the gcon (global connectivity) array 52 | gcon = zeros(numNodes, numDOFsPerNode); 53 | 54 | % Initialize the solution and the RHS vectors 55 | u = zeros(numDOFs, 1); 56 | f = zeros(numDOFs, 1); 57 | 58 | % index_f stores all the indices corresponding to the known forces, 59 | % and index_u all the indices corresponding to the known displacements. 60 | index_f = 1 : numBCs_force; 61 | index_u = (numBCs_force + 1) : numDOFs; 62 | 63 | % Prescribe the forces 64 | count = 1; 65 | for i = 1 : numBCs_force 66 | gcon(BCs_force(i, 1), BCs_force(i, 2)) = count; 67 | f(count) = BCs_force(i, 3); 68 | count = count + 1; 69 | end 70 | 71 | % Prescribe the displacements 72 | for i = 1 : numBCs_displacement 73 | gcon(BCs_displacement(i, 1), BCs_displacement(i, 2)) = count; 74 | u(count) = BCs_displacement(i, 3); 75 | count = count + 1; 76 | end 77 | 78 | 79 | 80 | %---------------------------------------------------------------------- 81 | % --------------------------------------------------------------------- 82 | % Set the quadrature rule (3-point Gauss quadrature) and evaluate 83 | % the basis functions and their derivatives at the quadrature points 84 | % --------------------------------------------------------------------- 85 | %---------------------------------------------------------------------- 86 | z = [-sqrt(3/5); 0; sqrt(3/5)]; 87 | w = [5/9; 8/9; 5/9]; 88 | numQuadraturePoints = length(z); 89 | 90 | eval_N = @(xi) [0.5 * xi .* (xi - 1), ... 91 | 1 - xi.^2, ... 92 | 0.5 * xi .* (xi + 1)]; 93 | eval_B = @(xi) [xi - 0.5, ... 94 | -2 * xi, ... 95 | xi + 0.5]; 96 | 97 | % Evaluate at the quadrature points 98 | N = eval_N(z); 99 | B = eval_B(z); 100 | 101 | 102 | 103 | %---------------------------------------------------------------------- 104 | % --------------------------------------------------------------------- 105 | % Create the stiffness matrix K and the load vector f 106 | % --------------------------------------------------------------------- 107 | %---------------------------------------------------------------------- 108 | % Initialize the stiffness matrix 109 | K = zeros(numDOFs); 110 | 111 | numNodesPerElement = 3; 112 | numDOFsPerElement = numNodesPerElement * numDOFsPerNode; 113 | 114 | 115 | %---------------------------------------------------------------------- 116 | % Specify the distributed load 117 | %---------------------------------------------------------------------- 118 | P_0 = abs(BCs_force(1, 3)); 119 | L = nodes(numNodes, 1); 120 | eval_distributed_load = @(x) P_0 / L; 121 | 122 | 123 | %---------------------------------------------------------------------- 124 | % Loop over the elements 125 | %---------------------------------------------------------------------- 126 | for e = 1 : numElements 127 | % Get the node indices 128 | node1Index = elements(e, 1); 129 | node2Index = elements(e, 2); 130 | node3Index = elements(e, 3); 131 | 132 | % Get the nodal positions 133 | x1 = nodes(node1Index, 1); 134 | x2 = nodes(node2Index, 1); 135 | x3 = nodes(node3Index, 1); 136 | x_e = [x1; x2; x3]; 137 | 138 | % Get the element properties (constant) 139 | E = elements(e, 4); 140 | A = elements(e, 5); 141 | k = E*A / L^2; 142 | 143 | 144 | % Evaluate the elasticity matrix (constant) 145 | C = [E]; 146 | 147 | % Initialize the element stiffness matrix and element load vector 148 | K_e = zeros(numNodesPerElement); 149 | f_e = zeros(numNodesPerElement, 1); 150 | 151 | 152 | %------------------------------------------------------------------ 153 | % Loop over the quadrature points 154 | %------------------------------------------------------------------ 155 | for i = 1 : numQuadraturePoints 156 | % Get the values of the basis functions and their derivatives 157 | % at the quadrature point 158 | N_e = N(i, :); 159 | B_e = B(i, :); 160 | 161 | % Find the point x in the physical domain that corresponds to 162 | % the quadrature point 163 | x = N_e * x_e; 164 | 165 | % Evaluate the Jacobian at the quadrature point 166 | J = B_e * x_e; 167 | 168 | % Evaluate the distributed load at the quadrature point 169 | distributed_load = eval_distributed_load(x); 170 | 171 | 172 | %-------------------------------------------------------------- 173 | % Form the element stiffness matrix 174 | %-------------------------------------------------------------- 175 | K_e = K_e + w(i) * ((A / J) * (B_e' * C * B_e) + (k * J) * (N_e' * N_e)); 176 | 177 | 178 | %-------------------------------------------------------------- 179 | % Form the element load vector 180 | %-------------------------------------------------------------- 181 | f_e = f_e + w(i) * ((distributed_load * J) * N_e'); 182 | end 183 | 184 | 185 | %------------------------------------------------------------------ 186 | % Global assembly 187 | %------------------------------------------------------------------ 188 | % Get the global DOF indices 189 | index = [gcon(node1Index, 1); ... 190 | gcon(node2Index, 1); ... 191 | gcon(node3Index, 1)]; 192 | 193 | % Assign the entries 194 | for i = 1 : numDOFsPerElement 195 | for j = 1 : numDOFsPerElement 196 | K(index(i), index(j)) = K(index(i), index(j)) + K_e(i, j); 197 | end 198 | 199 | f(index(i)) = f(index(i)) + f_e(i); 200 | end 201 | end 202 | 203 | 204 | 205 | %---------------------------------------------------------------------- 206 | % --------------------------------------------------------------------- 207 | % Solve for the unknown displacements and forces 208 | % --------------------------------------------------------------------- 209 | %---------------------------------------------------------------------- 210 | % Solve for the unknown displacements 211 | u(index_f) = K(index_f, index_f) \ (f(index_f) - K(index_f, index_u) * u(index_u)); 212 | 213 | % Solve for the unknown forces 214 | f(index_u) = K(index_u, index_f) * u(index_f) + K(index_u, index_u) * u(index_u); 215 | 216 | 217 | save(strcat('./demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p2_numElements', problem_size), 'u', 'f', 'gcon', '-v7.3'); 218 | end -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p1_numElements01.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p1_numElements01.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p1_numElements02.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p1_numElements02.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p1_numElements04.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p1_numElements04.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p1_numElements08.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p1_numElements08.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p2_numElements01.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p2_numElements01.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p2_numElements02.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p2_numElements02.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p2_numElements04.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p2_numElements04.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p2_numElements08.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p2_numElements08.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p1_numElements01.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p1_numElements01.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p1_numElements02.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p1_numElements02.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p1_numElements04.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p1_numElements04.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p1_numElements08.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p1_numElements08.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p2_numElements01.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p2_numElements01.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p2_numElements02.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p2_numElements02.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p2_numElements04.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p2_numElements04.mat -------------------------------------------------------------------------------- /updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p2_numElements08.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p2_numElements08.mat -------------------------------------------------------------------------------- /updated/demo3_driver_1dbar_p1.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: 3 | % 4 | % Isaac J. Lee (crunchingnumbers.live) 5 | % 6 | % Summary: 7 | % 8 | % This driver calls the assembly routine to solve the bar problem with 9 | % a Winkler foundation with 1, 2, 4, 8 elements using a linear basis. 10 | % It then plots the FE displacement and force fields for comparison. 11 | % 12 | % Instructions: 13 | % 14 | % Type the following onto Matlab's command window: 15 | % 16 | % demo3_driver_1dbar_p1 17 | % 18 | %-------------------------------------------------------------------------- 19 | function demo3_driver_1dbar_p1() 20 | clc; 21 | close all; 22 | 23 | 24 | warning('off', 'MATLAB:legend:IgnoringExtraEntries'); 25 | 26 | addpath('./demo3_analyze_1dbar_winkler/'); 27 | 28 | figure('Units' , 'normalized', ... 29 | 'OuterPosition' , [0 0 1 1], ... 30 | 'Color' , [1 1 1], ... 31 | 'InvertHardcopy' , 'off', ... 32 | 'MenuBar' , 'none', ... 33 | 'NumberTitle' , 'off', ... 34 | 'Resize' , 'on', ... 35 | 'PaperUnits' , 'points', ... 36 | 'PaperPosition' , [0 0 800 600], ... 37 | 'PaperPositionMode', 'auto'); 38 | 39 | 40 | %---------------------------------------------------------------------- 41 | % Set parameters for plotting 42 | %---------------------------------------------------------------------- 43 | numPoints = 1000; 44 | problem_size = {'01'; '02'; '04'; '08'}; 45 | problem_color = [0.70, 0.35, 0.45; ... 46 | 0.80, 0.75, 0.30; ... 47 | 0.40, 0.75, 0.55; ... 48 | 0.40, 0.70, 0.90]; 49 | problem_legend = {' 1 element' ; ... 50 | ' 2 elements'; ... 51 | ' 4 elements'; ... 52 | ' 8 elements'}; 53 | 54 | 55 | %---------------------------------------------------------------------- 56 | % Evaluate the basis functions and their derivatives in the parent 57 | % domain 58 | %---------------------------------------------------------------------- 59 | xi = linspace(-1, 1, numPoints + 1)'; 60 | 61 | eval_N = @(xi) [0.5 * (1 - xi), ... 62 | 0.5 * (1 + xi)]; 63 | eval_B = @(xi) [-0.5 * ones(length(xi), 1), ... 64 | 0.5 * ones(length(xi), 1)]; 65 | 66 | N_e = eval_N(xi); 67 | B_e = eval_B(xi); 68 | 69 | 70 | 71 | %---------------------------------------------------------------------- 72 | % --------------------------------------------------------------------- 73 | % Begin solving the problem 74 | % --------------------------------------------------------------------- 75 | %---------------------------------------------------------------------- 76 | for i = 1 : length(problem_size) 77 | %------------------------------------------------------------------ 78 | % Solve the bar problem 79 | %------------------------------------------------------------------ 80 | analyze_1dbar_p1(problem_size{i}); 81 | 82 | 83 | %------------------------------------------------------------------ 84 | % Once we have solved the problem, we load the assembly and 85 | % solution files 86 | %------------------------------------------------------------------ 87 | load(strcat('./demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p1_numElements', problem_size{i}), 'nodes', 'elements'); 88 | load(strcat('./demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p1_numElements', problem_size{i}), 'u', 'gcon'); 89 | 90 | 91 | %------------------------------------------------------------------ 92 | % Loop over the elements 93 | %------------------------------------------------------------------ 94 | for e = 1 : size(elements, 1) 95 | % Get the node indices 96 | node1Index = elements(e, 1); 97 | node2Index = elements(e, 2); 98 | 99 | % Get the nodal positions 100 | x1 = nodes(node1Index, 1); 101 | x2 = nodes(node2Index, 1); 102 | x_e = [x1; x2]; 103 | 104 | % Get the element properties (constant) 105 | E = elements(e, 3); 106 | A = elements(e, 4); 107 | 108 | % Get the nodal displacements 109 | u1 = u(gcon(node1Index, 1)); 110 | u2 = u(gcon(node2Index, 1)); 111 | u_e = [u1; u2]; 112 | 113 | 114 | % Find the corresponding points in the physical domain 115 | x = N_e * x_e; 116 | 117 | % Evaluate the Jacobian at the points 118 | J = B_e * x_e; 119 | 120 | % Evaluate the displacement and force fields 121 | u_h = N_e * u_e; 122 | f_h = E*A * (B_e * u_e) ./ J; 123 | 124 | 125 | %-------------------------------------------------------------- 126 | % Plot the displacement field on the element 127 | %-------------------------------------------------------------- 128 | subplot(1, 2, 1); 129 | 130 | h(i, e) = ... 131 | plot(x, u_h, '-', 'Color', problem_color(i, :), 'LineWidth', 3.5); 132 | 133 | hold on; 134 | 135 | h_markers(i, e) = ... 136 | plot([x1 x2], [u_h(1) u_h(end)], 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 10); 137 | 138 | hold on; 139 | 140 | 141 | %-------------------------------------------------------------- 142 | % Plot the internal force field on the element 143 | %-------------------------------------------------------------- 144 | subplot(1, 2, 2); 145 | 146 | h(i + 4, e) = ... 147 | plot(x, f_h, '-', 'Color', problem_color(i, :), 'LineWidth', 3.5); 148 | 149 | hold on; 150 | 151 | h_markers(i + 4, e) = ... 152 | plot([x1 x2], [f_h(1) f_h(end)], 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 10); 153 | 154 | hold on; 155 | end 156 | 157 | 158 | %------------------------------------------------------------------ 159 | % Plot the displacement field 160 | %------------------------------------------------------------------ 161 | subplot(1, 2, 1); 162 | 163 | % Make the color of the previous plots opaque 164 | if (i > 1) 165 | newColor = 0.2 * get(h(i - 1, 1), 'Color') + 0.8 * [1 1 1]; 166 | 167 | for e = 1 : 2^(i - 2) 168 | set(h(i - 1, e) , 'Color', newColor); 169 | set(h_markers(i - 1, e), 'Color', [0.8 0.8 0.8], 'MarkerFaceColor', newColor); 170 | end 171 | end 172 | 173 | title('Displacement (p = 1)', 'FontSize', 60); 174 | xlabel('x (m)' , 'FontSize', 48); 175 | ylabel('u_h (\mum) ', 'FontSize', 48, 'Rotation', 0); 176 | legend(h(1:i, 1), problem_legend{1:i}, 'FontSize', 32, 'Location', 'SouthWest'); 177 | axis([0 4 0e-5 2e-5]); 178 | axis square; 179 | grid on; 180 | set(gca, 'FontSize', 26, ... 181 | 'XTick', linspace(0, 4, 5), ... 182 | 'YTick', linspace(0e-5, 2e-5, 5), ... 183 | 'YTickLabel', num2cell(linspace(0, 0.2, 5))); 184 | 185 | 186 | %------------------------------------------------------------------ 187 | % Plot the internal force field 188 | %------------------------------------------------------------------ 189 | subplot(1, 2, 2); 190 | 191 | % Make the color of the previous plots opaque 192 | if (i > 1) 193 | newColor = 0.2 * get(h(i + 3, 1), 'Color') + 0.8 * [1 1 1]; 194 | 195 | for e = 1 : 2^(i - 2) 196 | set(h(i + 3, e) , 'Color', newColor); 197 | set(h_markers(i + 3, e), 'Color', [0.8 0.8 0.8], 'MarkerFaceColor', newColor); 198 | end 199 | end 200 | 201 | title('Internal force (p = 1)', 'FontSize', 60); 202 | xlabel('x (m)' , 'FontSize', 48); 203 | ylabel('F_h (MN) ', 'FontSize', 48, 'Rotation', 0); 204 | legend(h((1:i) + 4, 1), problem_legend{1:i}, 'FontSize', 32, 'Location', 'SouthWest'); 205 | axis([0 4 -1.6e5 -0.8e5]); 206 | axis square; 207 | grid on; 208 | set(gca, 'FontSize', 28, ... 209 | 'XTick', linspace(0, 4, 5), ... 210 | 'YTick', linspace(-1.6e5, -0.8e5, 5), ... 211 | 'YTickLabel', num2cell(linspace(-0.16, -0.08, 5))); 212 | 213 | 214 | pause; 215 | end 216 | 217 | 218 | % print('-dpng' , '-r300', 'plot_fields_p1.png'); 219 | end -------------------------------------------------------------------------------- /updated/demo3_driver_1dbar_p2.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: 3 | % 4 | % Isaac J. Lee (crunchingnumbers.live) 5 | % 6 | % Summary: 7 | % 8 | % This driver calls the assembly routine to solve the bar problem with 9 | % a Winkler foundation with 1, 2, 4, 8 elements using a quadratic basis. 10 | % It then plots the FE displacement and force fields for comparison. 11 | % 12 | % Instructions: 13 | % 14 | % Type the following onto Matlab's command window: 15 | % 16 | % demo3_driver_1dbar_p2 17 | % 18 | %-------------------------------------------------------------------------- 19 | function demo3_driver_1dbar_p2() 20 | clc; 21 | close all; 22 | 23 | 24 | warning('off', 'MATLAB:legend:IgnoringExtraEntries'); 25 | 26 | addpath('./demo3_analyze_1dbar_winkler/'); 27 | 28 | figure('Units' , 'normalized', ... 29 | 'OuterPosition' , [0 0 1 1], ... 30 | 'Color' , [1 1 1], ... 31 | 'InvertHardcopy' , 'off', ... 32 | 'MenuBar' , 'none', ... 33 | 'NumberTitle' , 'off', ... 34 | 'Resize' , 'on', ... 35 | 'PaperUnits' , 'points', ... 36 | 'PaperPosition' , [0 0 800 600], ... 37 | 'PaperPositionMode', 'auto'); 38 | 39 | 40 | %---------------------------------------------------------------------- 41 | % Set parameters for plotting 42 | %---------------------------------------------------------------------- 43 | numPoints = 1000; 44 | problem_size = {'01'; '02'; '04'; '08'}; 45 | problem_color = [0.70, 0.35, 0.45; ... 46 | 0.80, 0.75, 0.30; ... 47 | 0.40, 0.75, 0.55; ... 48 | 0.40, 0.70, 0.90]; 49 | problem_legend = {' 1 element' ; ... 50 | ' 2 elements'; ... 51 | ' 4 elements'; ... 52 | ' 8 elements'}; 53 | 54 | 55 | %---------------------------------------------------------------------- 56 | % Evaluate the basis functions and their derivatives in the parent 57 | % domain 58 | %---------------------------------------------------------------------- 59 | xi = linspace(-1, 1, numPoints + 1)'; 60 | 61 | eval_N = @(xi) [0.5 * xi .* (xi - 1), ... 62 | 1 - xi.^2, ... 63 | 0.5 * xi .* (xi + 1)]; 64 | eval_B = @(xi) [xi - 0.5, ... 65 | -2 * xi, ... 66 | xi + 0.5]; 67 | 68 | N_e = eval_N(xi); 69 | B_e = eval_B(xi); 70 | 71 | 72 | %---------------------------------------------------------------------- 73 | % --------------------------------------------------------------------- 74 | % Begin solving the problem 75 | % --------------------------------------------------------------------- 76 | %---------------------------------------------------------------------- 77 | for i = 1 : length(problem_size) 78 | %------------------------------------------------------------------ 79 | % Solve the bar problem 80 | %------------------------------------------------------------------ 81 | analyze_1dbar_p2(problem_size{i}); 82 | 83 | 84 | %------------------------------------------------------------------ 85 | % Once we have solved the problem, we load the assembly and 86 | % solution files 87 | %------------------------------------------------------------------ 88 | load(strcat('./demo3_analyze_1dbar_winkler/assembly_files/assembly_1dbar_p2_numElements', problem_size{i}), 'nodes', 'elements'); 89 | load(strcat('./demo3_analyze_1dbar_winkler/solution_files/solution_1dbar_p2_numElements', problem_size{i}), 'u', 'gcon'); 90 | 91 | 92 | %------------------------------------------------------------------ 93 | % Loop over the elements 94 | %------------------------------------------------------------------ 95 | for e = 1 : size(elements, 1) 96 | % Get the node indices 97 | node1Index = elements(e, 1); 98 | node2Index = elements(e, 2); 99 | node3Index = elements(e, 3); 100 | 101 | % Get the nodal positions 102 | x1 = nodes(node1Index, 1); 103 | x2 = nodes(node2Index, 1); 104 | x3 = nodes(node3Index, 1); 105 | x_e = [x1; x2; x3]; 106 | 107 | % Get the element properties (constant) 108 | E = elements(e, 4); 109 | A = elements(e, 5); 110 | 111 | % Get the nodal displacements 112 | u1 = u(gcon(node1Index, 1)); 113 | u2 = u(gcon(node2Index, 1)); 114 | u3 = u(gcon(node3Index, 1)); 115 | u_e = [u1; u2; u3]; 116 | 117 | 118 | % Find the corresponding points in the physical domain 119 | x = N_e * x_e; 120 | 121 | % Evaluate the Jacobian at the points 122 | J = B_e * x_e; 123 | 124 | % Evaluate the displacement and force fields 125 | u_h = N_e * u_e; 126 | f_h = E*A * (B_e * u_e) ./ J; 127 | 128 | 129 | %-------------------------------------------------------------- 130 | % Plot the displacement field on the element 131 | %-------------------------------------------------------------- 132 | subplot(1, 2, 1); 133 | 134 | h(i, e) = ... 135 | plot(x, u_h, '-', 'Color', problem_color(i, :), 'LineWidth', 3.5); 136 | 137 | hold on; 138 | 139 | h_markers(i, e) = ... 140 | plot([x1 x3], [u_h(1) u_h(end)], 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 10); 141 | 142 | hold on; 143 | 144 | 145 | %-------------------------------------------------------------- 146 | % Plot the internal force field on the element 147 | %-------------------------------------------------------------- 148 | subplot(1, 2, 2); 149 | 150 | h(i + 4, e) = ... 151 | plot(x, f_h, '-', 'Color', problem_color(i, :), 'LineWidth', 3.5); 152 | 153 | hold on; 154 | 155 | h_markers(i + 4, e) = ... 156 | plot([x1 x3], [f_h(1) f_h(end)], 's', 'Color', [0 0 0], 'MarkerFaceColor', problem_color(i, :), 'MarkerSize', 10); 157 | 158 | hold on; 159 | end 160 | 161 | 162 | %------------------------------------------------------------------ 163 | % Plot the displacement field 164 | %------------------------------------------------------------------ 165 | subplot(1, 2, 1); 166 | 167 | % Make the color of the previous plots opaque 168 | if (i > 1) 169 | newColor = 0.2 * get(h(i - 1, 1), 'Color') + 0.8 * [1 1 1]; 170 | 171 | for e = 1 : 2^(i - 2) 172 | set(h(i - 1, e) , 'Color', newColor); 173 | set(h_markers(i - 1, e), 'Color', [0.8 0.8 0.8], 'MarkerFaceColor', newColor); 174 | end 175 | end 176 | 177 | title('Displacement (p = 2)', 'FontSize', 60); 178 | xlabel('x (m)' , 'FontSize', 48); 179 | ylabel('u_h (\mum) ', 'FontSize', 48, 'Rotation', 0); 180 | legend(h(1:i), problem_legend{1:i}, 'FontSize', 32, 'Location', 'SouthWest'); 181 | axis([0 4 0e-5 2e-5]); 182 | axis square; 183 | grid on; 184 | set(gca, 'FontSize', 26, ... 185 | 'XTick', linspace(0, 4, 5), ... 186 | 'YTick', linspace(0e-5, 2e-5, 5), ... 187 | 'YTickLabel', num2cell(linspace(0, 0.2, 5))); 188 | 189 | 190 | %------------------------------------------------------------------ 191 | % Plot the internal force field 192 | %------------------------------------------------------------------ 193 | subplot(1, 2, 2); 194 | 195 | % Make the color of the previous plots opaque 196 | if (i > 1) 197 | newColor = 0.2 * get(h(i + 3, 1), 'Color') + 0.8 * [1 1 1]; 198 | 199 | for e = 1 : 2^(i - 2) 200 | set(h(i + 3, e) , 'Color', newColor); 201 | set(h_markers(i + 3, e), 'Color', [0.8 0.8 0.8], 'MarkerFaceColor', newColor); 202 | end 203 | end 204 | 205 | title('Internal force (p = 2)', 'FontSize', 60); 206 | xlabel('x (m)' , 'FontSize', 48); 207 | ylabel('F_h (MN) ', 'FontSize', 48, 'Rotation', 0); 208 | legend(h((1:i) + 4), problem_legend{1:i}, 'FontSize', 32, 'Location', 'SouthWest'); 209 | axis([0 4 -1.6e5 -0.8e5]); 210 | axis square; 211 | grid on; 212 | set(gca, 'FontSize', 28, ... 213 | 'XTick', linspace(0, 4, 5), ... 214 | 'YTick', linspace(-1.6e5, -0.8e5, 5), ... 215 | 'YTickLabel', num2cell(linspace(-0.16, -0.08, 5))); 216 | 217 | 218 | pause; 219 | end 220 | 221 | 222 | % print('-dpng' , '-r300', 'plot_fields_p2.png'); 223 | end -------------------------------------------------------------------------------- /updated/demo4_analyze_2dplate.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % Author: 3 | % 4 | % Isaac J. Lee (crunchingnumbers.live) 5 | % 6 | % Summary: 7 | % 8 | % This routine solves the problem of a plate with a circular hole in 9 | % tension using finite element method. In particular, we consider the 10 | % linear triangular elements to approximate the displacement field. 11 | % 12 | % Instructions: 13 | % 14 | % Type the following onto Matlab's command window: 15 | % 16 | % demo4_analyze_2dplate 17 | % 18 | %-------------------------------------------------------------------------- 19 | function demo4_analyze_2dplate() 20 | clc; 21 | close all; 22 | 23 | 24 | %---------------------------------------------------------------------- 25 | % Load the assembly file 26 | %---------------------------------------------------------------------- 27 | addpath('./demo4_analyze_2dplate/'); 28 | 29 | load('demo4_analyze_2dplate/assembly_numElements12R'); 30 | 31 | 32 | % Find the number of nodes, etc. from the assembly file 33 | numNodes = size(nodes, 1); 34 | numElements = size(elements, 1); 35 | numBCs_displacement = size(BCs_displacement, 1); 36 | numBCs_force = size(BCs_force, 1); 37 | 38 | % Find the number of degrees of freedom (DOFs) for 2D elasticity 39 | numDOFsPerNode = 2; 40 | numDOFs = numDOFsPerNode * numNodes; 41 | 42 | if (numBCs_displacement + numBCs_force ~= numDOFs) 43 | error('Error: Please check the BCs.'); 44 | end 45 | 46 | 47 | %---------------------------------------------------------------------- 48 | % --------------------------------------------------------------------- 49 | % Set the gcon array so that all the known displacements will be on 50 | % the bottom side of u and all the known forces on the top side of f. 51 | % While we populate the gcon array, we prescribe the known values 52 | % into the vectors u and f. 53 | % --------------------------------------------------------------------- 54 | %---------------------------------------------------------------------- 55 | % Initialize the gcon (global connectivity) array 56 | gcon = zeros(numNodes, numDOFsPerNode); 57 | 58 | % Initialize the solution and the RHS vectors 59 | u = zeros(numDOFs, 1); 60 | f = zeros(numDOFs, 1); 61 | 62 | % index_f stores all the indices corresponding to the known forces, 63 | % and index_u all the indices corresponding to the known displacements. 64 | index_f = 1 : numBCs_force; 65 | index_u = (numBCs_force + 1) : numDOFs; 66 | 67 | % Prescribe the forces 68 | count = 1; 69 | for i = 1 : numBCs_force 70 | gcon(BCs_force(i, 1), BCs_force(i, 2)) = count; 71 | f(count) = BCs_force(i, 3); 72 | count = count + 1; 73 | end 74 | 75 | % Prescribe the displacements 76 | for i = 1 : numBCs_displacement 77 | gcon(BCs_displacement(i, 1), BCs_displacement(i, 2)) = count; 78 | u(count) = BCs_displacement(i, 3); 79 | count = count + 1; 80 | end 81 | 82 | 83 | %---------------------------------------------------------------------- 84 | % --------------------------------------------------------------------- 85 | % Create the global stiffness matrix K 86 | % --------------------------------------------------------------------- 87 | %---------------------------------------------------------------------- 88 | % The number of entries that we need to compute to form the global 89 | % stiffness matrix (linear triangular element has 3 nodes) 90 | numDOFsPerElement = 3 * numDOFsPerNode; 91 | numEntries = numDOFsPerElement^2 * numElements; 92 | 93 | % Initialize the I, J, value arrays 94 | I = zeros(numEntries, 1); 95 | J = zeros(numEntries, 1); 96 | value = zeros(numEntries, 1); 97 | 98 | % Counter for assembly 99 | count = 1; 100 | 101 | 102 | %---------------------------------------------------------------------- 103 | % Loop over the elements 104 | %---------------------------------------------------------------------- 105 | for e = 1 : numElements 106 | % Get the node indices 107 | node1Index = elements(e, 1); 108 | node2Index = elements(e, 2); 109 | node3Index = elements(e, 3); 110 | 111 | % Get the nodal positions 112 | x1 = nodes(node1Index, 1); 113 | y1 = nodes(node1Index, 2); 114 | x2 = nodes(node2Index, 1); 115 | y2 = nodes(node2Index, 2); 116 | x3 = nodes(node3Index, 1); 117 | y3 = nodes(node3Index, 2); 118 | 119 | % Get the element properties 120 | E = elements(e, 4); 121 | nu = elements(e, 5); 122 | 123 | 124 | %------------------------------------------------------------------ 125 | % Calculate the B matrix 126 | %------------------------------------------------------------------ 127 | % Compute the Jacobian 128 | A = (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) / 2; 129 | twoA_inv = 0.5 / A; 130 | 131 | % a0 = twoA_inv * (x2*y3 - x3*y2); 132 | a1 = twoA_inv * (y2 - y3); 133 | a2 = twoA_inv * (x3 - x2); 134 | % b0 = twoA_inv * (x3*y1 - x1*y3); 135 | b1 = twoA_inv * (y3 - y1); 136 | b2 = twoA_inv * (x1 - x3); 137 | % c0 = twoA_inv * (x1*y2 - x2*y1); 138 | c1 = twoA_inv * (y1 - y2); 139 | c2 = twoA_inv * (x2 - x1); 140 | 141 | B = [a1 0 b1 0 c1 0; ... 142 | 0 a2 0 b2 0 c2; ... 143 | a2 a1 b2 b1 c2 c1]; 144 | 145 | 146 | %------------------------------------------------------------------ 147 | % Calculate the C matrix 148 | %------------------------------------------------------------------ 149 | % E = E / (1 - nu^2); 150 | % nu = nu / (1 - nu); 151 | constant1 = E / (1 - nu^2); 152 | 153 | C = [ constant1, nu * constant1, 0; ... 154 | nu * constant1, constant1, 0; ... 155 | 0, 0, E / (2 + 2*nu)]; 156 | 157 | 158 | %------------------------------------------------------------------ 159 | % Form the element stiffness matrix 160 | %------------------------------------------------------------------ 161 | % Thickness of the plate is t = 1 unit; otherwise, multiply by A*t 162 | K_e = (B' * C * B) * A; 163 | 164 | 165 | %------------------------------------------------------------------ 166 | % Global assembly 167 | %------------------------------------------------------------------ 168 | % Get the DOF indices 169 | index = [gcon(node1Index, 1); ... 170 | gcon(node1Index, 2); ... 171 | gcon(node2Index, 1); ... 172 | gcon(node2Index, 2); ... 173 | gcon(node3Index, 1); ... 174 | gcon(node3Index, 2)]; 175 | 176 | % Assign the entries 177 | for i = 1 : numDOFsPerElement 178 | for j = 1 : numDOFsPerElement 179 | % Use these lines if K is declared as a sparse matrix 180 | I(count) = index(i); 181 | J(count) = index(j); 182 | value(count) = K_e(i, j); 183 | 184 | count = count + 1; 185 | end 186 | end 187 | end 188 | 189 | if (numEntries ~= count - 1) 190 | error('Error: Check the code.'); 191 | end 192 | 193 | K = sparse(I, J, value, numDOFs, numDOFs); 194 | clear K_e I J value index; 195 | 196 | 197 | 198 | %---------------------------------------------------------------------- 199 | % --------------------------------------------------------------------- 200 | % Solve for the unknown displacements and forces 201 | % --------------------------------------------------------------------- 202 | %---------------------------------------------------------------------- 203 | % Solve for the unknown displacements 204 | u(index_f) = K(index_f, index_f) \ (f(index_f) - K(index_f, index_u) * u(index_u)); 205 | 206 | % Solve for the unknown forces 207 | % f(index_u) = K(index_u, index_f) * u(index_f) + K(index_u, index_u) * u(index_u); 208 | 209 | 210 | %---------------------------------------------------------------------- 211 | % Post-process 212 | %---------------------------------------------------------------------- 213 | draw_plate(nodes, elements, u, gcon); 214 | end -------------------------------------------------------------------------------- /updated/demo4_analyze_2dplate/assembly_numElements06.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo4_analyze_2dplate/assembly_numElements06.mat -------------------------------------------------------------------------------- /updated/demo4_analyze_2dplate/assembly_numElements12.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo4_analyze_2dplate/assembly_numElements12.mat -------------------------------------------------------------------------------- /updated/demo4_analyze_2dplate/assembly_numElements12R.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo4_analyze_2dplate/assembly_numElements12R.mat -------------------------------------------------------------------------------- /updated/demo4_analyze_2dplate/assembly_numElements24.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/demo4_analyze_2dplate/assembly_numElements24.mat -------------------------------------------------------------------------------- /updated/problem_description_demo3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ijlee2/Finite-Element-Analysis/f0644da91141b676c36b9d63367a125968d15b55/updated/problem_description_demo3.pdf --------------------------------------------------------------------------------