├── .gitignore ├── README.md ├── _config.yml ├── fem_1d ├── compute_error_fem_1d.m ├── fem_1d.pdf ├── fem_1d_exercise1.m ├── fem_1d_exercise1.p ├── fem_1d_exercise2.m ├── fem_1d_exercise2.p ├── fem_1d_exercise3.m ├── fem_1d_exercise3.p ├── fem_for_poisson_1d.m ├── fem_for_poisson_1d_ex2.m ├── fem_for_poisson_1d_ex2_sol.m ├── fem_for_poisson_1d_ex2_sol.p ├── fem_for_poisson_1d_ex3.m ├── fem_for_poisson_1d_ex3_sol.m ├── fem_for_poisson_1d_ex3_sol.p ├── get_matrices_1d.m ├── get_matrices_1d_sol.m ├── get_matrices_1d_sol.p ├── main_fem_for_poisson_1d.m └── mesh_fem_1d.m ├── fem_2d_rectangle ├── compute_error_fem_2d_rectangle.m ├── fem_2d_rectangle.pdf ├── fem_2d_rectangle_exercise1.m ├── fem_2d_rectangle_exercise1.p ├── fem_2d_rectangle_exercise2.m ├── fem_2d_rectangle_exercise2.p ├── fem_2d_rectangle_exercise3.m ├── fem_2d_rectangle_exercise3.p ├── fem_for_poisson_2d_rectangle.m ├── fem_for_poisson_2d_rectangle_ex2.m ├── fem_for_poisson_2d_rectangle_ex2_sol.m ├── fem_for_poisson_2d_rectangle_ex2_sol.p ├── fem_for_poisson_2d_rectangle_ex3.m ├── fem_for_poisson_2d_rectangle_ex3_sol.m ├── fem_for_poisson_2d_rectangle_ex3_sol.p ├── get_matrices_2d_rectangle.m ├── get_matrices_2d_rectangle_sol.m ├── get_matrices_2d_rectangle_sol.p ├── main_fem_for_poisson_2d_rectangle.m └── mesh_fem_2d_rectangle.m ├── fem_2d_triangle ├── compute_error_fem_2d_triangle.m ├── fem_2d_triangle.pdf ├── fem_2d_triangle_exercise1.m ├── fem_2d_triangle_exercise1.p ├── fem_2d_triangle_exercise2.m ├── fem_2d_triangle_exercise2.p ├── fem_2d_triangle_exercise3.m ├── fem_2d_triangle_exercise3.p ├── fem_for_poisson_2d_triangle.m ├── fem_for_poisson_2d_triangle_ex2.m ├── fem_for_poisson_2d_triangle_ex2_sol.m ├── fem_for_poisson_2d_triangle_ex2_sol.p ├── fem_for_poisson_2d_triangle_ex3.m ├── fem_for_poisson_2d_triangle_ex3_sol.m ├── fem_for_poisson_2d_triangle_ex3_sol.p ├── get_matrices_2d_triangle.m ├── get_matrices_2d_triangle_sol.m ├── get_matrices_2d_triangle_sol.p ├── main_fem_for_poisson_2d_triangle.m └── mesh_fem_2d_triangle.m └── test.PNG /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/matlab 3 | 4 | ### Matlab ### 5 | ##--------------------------------------------------- 6 | ## Remove autosaves generated by the Matlab editor 7 | ## We have git for backups! 8 | ##--------------------------------------------------- 9 | 10 | # Windows default autosave extension 11 | *.asv 12 | 13 | # OSX / *nix default autosave extension 14 | *.m~ 15 | 16 | # Compiled MEX binaries (all platforms) 17 | *.mex* 18 | 19 | # Simulink Code Generation 20 | slprj/ 21 | 22 | # Session info 23 | octave-workspace 24 | 25 | # Simulink autosave extension 26 | *.autosave 27 | 28 | 29 | # End of https://www.gitignore.io/api/matlab 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Basic Finite Element Method (FEM) Tutorial 2 | 3 | This repository contains FEM tutorial for beginners. It consists of a bunch of MATLAB codes to solve Poisson's problem. If you are not familiar with MATLAB, you can refer to [MATLAB tutorial](https://www.tutorialspoint.com/matlab). In each folder, {folder_name}.pdf leads you through implementing FEM codes for various finite element spaces. There are also several exercises to make sure you understand. 4 | 5 | ## Table Of Contents 6 | 7 | * [Finite Element Method in 1D](https://github.com/dw-shin/basic_fem_tutorial/tree/master/fem_1d) 8 | * [Finite Element Method in 2D with rectangular elements](https://github.com/dw-shin/basic_fem_tutorial/tree/master/fem_2d_rectangle) 9 | * [Finite Element Method in 2D with triangular elements](https://github.com/dw-shin/basic_fem_tutorial/tree/master/fem_2d_triangle) 10 | 11 | ## How to check your code 12 | When you are done with an exercise, run the code in command window. 13 | 14 | 15 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | title: Basic FEM Tutorial 2 | theme: jekyll-theme-cayman 3 | show_downloads: true 4 | -------------------------------------------------------------------------------- /fem_1d/compute_error_fem_1d.m: -------------------------------------------------------------------------------- 1 | function error = compute_error_fem_1d(c4n, ind4e, M_R, D_R, u, Du) 2 | % compute_error_fem_1d Semi H1 error 3 | % compute_error_fem_1d(c4n,ind4e,M_R,D_R,u,Du) computes the semi H1 error 4 | % between the exact solution and the FE solution. 5 | % 6 | % Parameters: 7 | % - c4n : coordinates for All nodes. 8 | % - n4db : nodes for Dirichlet boundary. 9 | % - M_R : Mass matrix on the reference interval 10 | % - D_R : Differentiation matrix on the reference interval 11 | % - u : numerical solution 12 | % - Du : Derivative of the exact solution for the model problem 13 | % 14 | % Returns: 15 | % - error : Semi H1 error between the exact solution and the FE solution. 16 | 17 | error = 0; 18 | for j = 1:size(ind4e,1) 19 | J = (c4n(ind4e(j,end)) - c4n(ind4e(j,1))) / 2; 20 | u_x = D_R*u(ind4e(j,:)) / J; 21 | De = Du(c4n(ind4e(j,:))) - u_x; 22 | error = error + J*De'*M_R*De; 23 | end 24 | error = sqrt(error); 25 | end -------------------------------------------------------------------------------- /fem_1d/fem_1d.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_1d/fem_1d.pdf -------------------------------------------------------------------------------- /fem_1d/fem_1d_exercise1.m: -------------------------------------------------------------------------------- 1 | % Exercise 1. Add the matrices for the cubic approximations (k=3) in 2 | % get_matrices_1d.m and check the convergence rate. 3 | % 4 | % After you modify get_matrices_1d.m, run this code in command window. 5 | % >> fem_1d_exercise1() -------------------------------------------------------------------------------- /fem_1d/fem_1d_exercise1.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_1d/fem_1d_exercise1.p -------------------------------------------------------------------------------- /fem_1d/fem_1d_exercise2.m: -------------------------------------------------------------------------------- 1 | % Exercise 2. Modify fem_for_poisson_1d_ex2.m to solve the Poisson problem with 2 | % non-homogeneous Dirichlet boundary condition, 3 | % 4 | % -u''(x) = f(x) in \Omega \\ 5 | % u(x) = u_D(x) on \partial\Omega. \\ 6 | % 7 | % After you modify fem\_for\_poisson\_1d_ex2.m, run this code in command window. 8 | % >> fem_1d_exercise2() 9 | % 10 | % 11 | % 12 | % 13 | % The following is the main code. If your code is right, the convergence 14 | % rate is k. 15 | % You can also compare the solution obtained from fem_for_poisson_1d_ex2.m 16 | % with that from fem_for_poisson_1d_ex2_sol.m 17 | % 18 | % k = 1; 19 | % iter = 6; 20 | % a = 0; 21 | % b = 1; 22 | % M = 2.^(1+(1:iter)); 23 | % f = @(x) 25*pi^2*sin(5*pi*x) - 2; 24 | % u_D = @(x) x.^2; 25 | % Du = @(x) 5*pi*cos(5*pi*x) + 2*x; 26 | % 27 | % h = 1./M; 28 | % count = zeros(3,1); 29 | % error = zeros(1,iter); 30 | % for j=1:iter 31 | % [c4n, n4e, n4db, ind4e] = mesh_fem_1d(a, b, M(j), k); 32 | % [M_R, S_R, D_R] = get_matrices_1d(k); 33 | % u = fem_for_poisson_1d_ex2(c4n, n4e, n4db, ind4e, M_R, S_R, f, u_D); 34 | % error(j) = compute_error_fem_1d(c4n, ind4e, M_R, D_R, u, Du); 35 | % end 36 | % convergence_rate = (log(error(2:end)) - log(error(1:end-1))) ./ (log(h(2:end)) - log(h(1:end-1))); 37 | % str1 = sprintf('Convergence rate for k = %d \n', k); 38 | % disp(str1) 39 | % disp(num2str(convergence_rate)) -------------------------------------------------------------------------------- /fem_1d/fem_1d_exercise2.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_1d/fem_1d_exercise2.p -------------------------------------------------------------------------------- /fem_1d/fem_1d_exercise3.m: -------------------------------------------------------------------------------- 1 | % Exercise 3. Modify fem_for_poisson_1d_ex3.m to solve the Poisson problem with 2 | % mixed boundary condition, 3 | % 4 | % -u''(x) = f(x) in \Omega \\ 5 | % u(x) = u_D(x) on \Gamma_D \\ 6 | % u'(x)n = u_N(x) on \Gamma_N. 7 | % 8 | % where \Gamma_D denotes the Dirichlet boundary, \Gamma_N denotes the 9 | % Neumann boundary, and n is the outward unit normal vector. 10 | % 11 | % After you modify fem_for_poisson_1d_ex3.m, run this code in command window. 12 | % >> fem_1d_exercise3() 13 | % 14 | % 15 | % 16 | % The following is the main code. If your code is right, the convergence 17 | % rate is k. 18 | % You can also compare the solution obtained from fem_for_poisson_1d_ex3.m 19 | % with that from fem_for_poisson_1d_ex3_sol.m 20 | % 21 | % k = 1; 22 | % iter = 6; 23 | % a = 0; 24 | % b = 1; 25 | % M = 2.^(1+(1:iter)); 26 | % f = @(x) 25*pi^2*sin(5*pi*x) - 2; 27 | % u_D = @(x) x.^2; 28 | % u_N = @(x) 5*pi*cos(5*pi*x) + 2*x; 29 | % Du = @(x) 5*pi*cos(5*pi*x) + 2*x; 30 | % 31 | % h = 1./M; 32 | % error = zeros(1,iter); 33 | % for j=1:iter 34 | % [c4n, n4e, n4db, ind4e] = mesh_fem_1d(a, b, M(j), k); 35 | % n4nb = n4db(2); 36 | % n4db = n4db(1); 37 | % [M_R, S_R, D_R] = get_matrices_1d(k); 38 | % u = fem_for_poisson_1d_ex3(c4n, n4e, n4db, n4nb, ind4e, M_R, S_R, f, u_D, u_N); 39 | % error(j) = compute_error_fem_1d(c4n, ind4e, M_R, D_R, u, Du); 40 | % end 41 | % convergence_rate = (log(error(2:end)) - log(error(1:end-1))) ./ (log(h(2:end)) - log(h(1:end-1))); 42 | % str1 = sprintf('Convergence rate for k = %d \n', k); 43 | % disp(str1) 44 | % disp(num2str(convergence_rate)) -------------------------------------------------------------------------------- /fem_1d/fem_1d_exercise3.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_1d/fem_1d_exercise3.p -------------------------------------------------------------------------------- /fem_1d/fem_for_poisson_1d.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, freenodes] = fem_for_poisson_1d(c4n, n4e, n4db, ... 2 | ind4e, M_R, S_R, f, u_D) 3 | %fem_for_poisson_1d FEM solver for Poisson problem in 1D 4 | % fem_for_poisson_1d(c4n,n4e,n4db,ind4e,M_R,S_R,f,u_D) solves the Poisson 5 | % problem. In order to use this code, mesh information (c4n, n4e, n4db, 6 | % ind4e), matrices (M_R, S_R), the source f, and the boundary condition 7 | % u_D. Then the results of this code are the numerical solution u, the 8 | % global stiffness matrix A, the global load vector b and the freenodes. 9 | % 10 | % Parameters: 11 | % - c4n : coordinates for All nodes. 12 | % - n4e : nodes for elements. 13 | % - n4db : nodes for Dirichlet boundary. 14 | % - ind4e : index for elements 15 | % - M_R : Mass matrix on the reference interval 16 | % - S_R : Stiffness matrix on the reference interval 17 | % - f : RHS in the Poisson problem 18 | % - u_D : Dirichlet boundary condition for the solution u 19 | % 20 | % Returns: 21 | % - u : numerical solution 22 | % - A : Global stiffness matrix 23 | % - b : Global right-hand side 24 | % - freenodes : free nodes 25 | 26 | number_of_nodes = size(c4n,1); 27 | A = sparse(number_of_nodes, number_of_nodes); 28 | b = zeros(number_of_nodes, 1); 29 | u = b; 30 | for j = 1:size(n4e,1) 31 | J = (c4n(n4e(j,2)) - c4n(n4e(j,1)))/2; 32 | A(ind4e(j,:), ind4e(j,:)) = A(ind4e(j,:), ind4e(j,:)) + S_R/J; 33 | b(ind4e(j,:)) = b(ind4e(j,:)) + J*M_R*f(c4n(ind4e(j,:))); 34 | end 35 | freenodes = setdiff(1:number_of_nodes, n4db); 36 | u(n4db) = u_D(c4n(n4db)); 37 | u(freenodes) = A(freenodes,freenodes)\b(freenodes); 38 | end -------------------------------------------------------------------------------- /fem_1d/fem_for_poisson_1d_ex2.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, freenodes] = fem_for_poisson_1d_ex2(c4n, n4e, ... 2 | n4db, ind4e, M_R, S_R, f, u_D) 3 | %fem_for_poisson_1d_ex2 FEM solver for Poisson problem in 1D 4 | % fem_for_poisson_1d_ex2(c4n,n4e,n4db,ind4e,M_R,S_R,f,u_D) solves the 5 | % Poisson problem. In order to use this code, mesh information (c4n, n4e, 6 | % n4db, ind4e), matrices (M_R, S_R), the source f, and the boundary 7 | % condition u_D. Then the results of this code are the numerical solution 8 | % u, the global stiffness matrix A, the global load vector b and the 9 | % freenodes. 10 | % 11 | % Parameters: 12 | % - c4n : coordinates for All nodes. 13 | % - n4e : nodes for elements. 14 | % - n4db : nodes for Dirichlet boundary. 15 | % - ind4e : index for elements 16 | % - M_R : Mass matrix on the reference interval 17 | % - S_R : Stiffness matrix on the reference interval 18 | % - f : RHS in the Poisson problem 19 | % - u_D : Dirichlet boundary condition for the solution u 20 | % 21 | % Returns: 22 | % - u : numerical solution 23 | % - A : Global stiffness matrix 24 | % - b : Global right-hand side 25 | % - freenodes : free nodes 26 | 27 | number_of_nodes = size(c4n,1); 28 | A = sparse(number_of_nodes, number_of_nodes); 29 | b = zeros(number_of_nodes, 1); 30 | u = b; 31 | for j = 1:size(n4e,1) 32 | J = (c4n(n4e(j,2)) - c4n(n4e(j,1)))/2; 33 | A(ind4e(j,:), ind4e(j,:)) = A(ind4e(j,:), ind4e(j,:)) + S_R/J; 34 | b(ind4e(j,:)) = b(ind4e(j,:)) + J*M_R*f(c4n(ind4e(j,:))); 35 | end 36 | freenodes = setdiff(1:number_of_nodes, n4db); 37 | u(n4db) = u_D(c4n(n4db)); 38 | 39 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 40 | % TODO: Add a few lines to treat non-homogeneous Dirichlet boundary 41 | % condition. 42 | 43 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 44 | 45 | u(freenodes) = A(freenodes,freenodes)\b(freenodes); 46 | end -------------------------------------------------------------------------------- /fem_1d/fem_for_poisson_1d_ex2_sol.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, freenodes] = fem_for_poisson_1d_ex2_sol(c4n, n4e, ... 2 | n4db, ind4e, M_R, S_R, f, u_D) 3 | %fem_for_poisson_1d_ex2_sol FEM solver for Poisson problem in 1D 4 | % fem_for_poisson_1d_ex3_sol(c4n,n4e,n4db,ind4e,M_R,S_R,f,u_D) solves the 5 | % Poisson problem. In order to use this code, mesh information (c4n, n4e, 6 | % n4db, ind4e), matrices (M_R, S_R), the source f, and the boundary 7 | % condition u_D. Then the results of this code are the numerical solution 8 | % u, the global stiffness matrix A, the global load vector b and the 9 | % freenodes. 10 | % 11 | % Parameters: 12 | % - c4n : coordinates for All nodes. 13 | % - n4e : nodes for elements. 14 | % - n4db : nodes for Dirichlet boundary. 15 | % - ind4e : index for elements 16 | % - M_R : Mass matrix on the reference interval 17 | % - S_R : Stiffness matrix on the reference interval 18 | % - f : RHS in the Poisson problem 19 | % - u_D : Dirichlet boundary condition for the solution u 20 | % 21 | % Returns: 22 | % - u : numerical solution 23 | % - A : Global stiffness matrix 24 | % - b : Global right-hand side 25 | % - freenodes : free nodes 26 | end -------------------------------------------------------------------------------- /fem_1d/fem_for_poisson_1d_ex2_sol.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_1d/fem_for_poisson_1d_ex2_sol.p -------------------------------------------------------------------------------- /fem_1d/fem_for_poisson_1d_ex3.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, freenodes] = fem_for_poisson_1d_ex3(c4n, n4e, ... 2 | n4db, n4nb, ind4e, M_R, S_R, f, u_D, u_N) 3 | %fem_for_poisson_1d_ex3 FEM solver for Poisson problem in 1D 4 | % fem_for_poisson_1d_ex3(c4n,n4e,n4db,n4nb,ind4e,M_R,S_R,f,u_D,u_N) 5 | % solves the Poisson problem. In order to use this code, mesh information 6 | % (c4n, n4e, n4db, ind4e), matrices (M_R, S_R), the source f, and the 7 | % boundary condition u_D. Then the results of this code are the numerical 8 | % solution u, the global stiffness matrix A, the global load vector b and 9 | % the freenodes. 10 | % 11 | % Parameters: 12 | % - c4n : coordinates for All nodes. 13 | % - n4e : nodes for elements. 14 | % - n4db : nodes for Dirichlet boundary. 15 | % - n4nb : nodes for Neumann boundary. 16 | % - ind4e : index for elements 17 | % - M_R : Mass matrix on the reference interval 18 | % - S_R : Stiffness matrix on the reference interval 19 | % - f : RHS in the Poisson problem 20 | % - u_D : Dirichlet boundary condition for the solution u 21 | % - u_N : Neumann boundary condition for the solution u 22 | % 23 | % Returns: 24 | % - u : numerical solution 25 | % - A : Global stiffness matrix 26 | % - b : Global right-hand side 27 | % - freenodes : free nodes 28 | 29 | number_of_nodes = size(c4n,1); 30 | A = sparse(number_of_nodes, number_of_nodes); 31 | b = zeros(number_of_nodes, 1); 32 | u = b; 33 | for j = 1:size(n4e,1) 34 | J = (c4n(n4e(j,2)) - c4n(n4e(j,1)))/2; 35 | A(ind4e(j,:), ind4e(j,:)) = A(ind4e(j,:), ind4e(j,:)) + S_R/J; 36 | b(ind4e(j,:)) = b(ind4e(j,:)) + J*M_R*f(c4n(ind4e(j,:))); 37 | end 38 | 39 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 40 | % TODO: Add a few lines to treat Neumann boundary condition. 41 | 42 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 43 | 44 | freenodes = setdiff(1:number_of_nodes, n4db); 45 | u(n4db) = u_D(c4n(n4db)); 46 | 47 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 48 | % TODO: Add a few lines to treat non-homogeneous Dirichlet boundary 49 | % condition. If you finished Exercise 2, the following lines can be copied 50 | % from fem_for_poisson_1d_ex2.m 51 | 52 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 53 | 54 | u(freenodes) = A(freenodes,freenodes)\b(freenodes); 55 | end -------------------------------------------------------------------------------- /fem_1d/fem_for_poisson_1d_ex3_sol.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, freenodes] = fem_for_poisson_1d_ex3_sol(c4n, n4e, ... 2 | n4db, n4nb, ind4e, M_R, S_R, f, u_D, u_N) 3 | %fem_for_poisson_1d_ex3_sol FEM solver for Poisson problem in 1D 4 | % fem_for_poisson_1d_ex3_sol(c4n,n4e,n4db,n4nb,ind4e,M_R,S_R,f,u_D,u_N) 5 | % solves the Poisson problem. In order to use this code, mesh information 6 | % (c4n, n4e, n4db, ind4e), matrices (M_R, S_R), the source f, and the 7 | % boundary condition u_D. Then the results of this code are the numerical 8 | % solution u, the global stiffness matrix A, the global load vector b and 9 | % the freenodes. 10 | % 11 | % Parameters: 12 | % - c4n : coordinates for All nodes. 13 | % - n4e : nodes for elements. 14 | % - n4db : nodes for Dirichlet boundary. 15 | % - n4nb : nodes for Neumann boundary. 16 | % - ind4e : index for elements 17 | % - M_R : Mass matrix on the reference interval 18 | % - S_R : Stiffness matrix on the reference interval 19 | % - f : RHS in the Poisson problem 20 | % - u_D : Dirichlet boundary condition for the solution u 21 | % - u_N : Neumann boundary condition for the solution u 22 | % 23 | % Returns: 24 | % - u : numerical solution 25 | % - A : Global stiffness matrix 26 | % - b : Global right-hand side 27 | % - freenodes : free nodes 28 | 29 | end -------------------------------------------------------------------------------- /fem_1d/fem_for_poisson_1d_ex3_sol.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_1d/fem_for_poisson_1d_ex3_sol.p -------------------------------------------------------------------------------- /fem_1d/get_matrices_1d.m: -------------------------------------------------------------------------------- 1 | function [M_R, S_R, D_R] = get_matrices_1d(k) 2 | %get_matrices_1d Matrices for Poisson using FEM in 1D 3 | % get_matrices_1d(k) generates the mass matrix M_R, the stiffness 4 | % matrix S_R and the differentiation matrix D_R for continuous k-th 5 | % order polynomial approximations on the reference interval. 6 | % 7 | % Parameters: 8 | % - k : polynomial order for the approximate solution 9 | % 10 | % Returns: 11 | % - M_R : Mass matrix on the reference interval 12 | % - S_R : Stiffness matrix on the reference interval 13 | % - D_R : Differentiation matrix on the reference interval 14 | 15 | if k==1 16 | M_R = [2 1; 1 2]/3; 17 | S_R = [1 -1; -1 1]/2; 18 | D_R = [-1 1; -1 1]/2; 19 | elseif k==2 20 | M_R = [4 2 -1; 2 16 2; -1 2 4]/15; 21 | S_R = [7 -8 1; -8 16 -8; 1 -8 7]/6; 22 | D_R = [-3 4 -1; -1 0 1; 1 -4 3]/2; 23 | else 24 | M_R = 0; S_R = 0; D_R = 0; 25 | end 26 | end -------------------------------------------------------------------------------- /fem_1d/get_matrices_1d_sol.m: -------------------------------------------------------------------------------- 1 | function [M_R, S_R, D_R] = get_matrices_1d_sol(k) 2 | %get_matrices_1d Matrices for Poisson using FEM in 1D 3 | % get_matrices_1d(k) generates the mass matrix M_R, the stiffness 4 | % matrix S_R and the differentiation matrix D_R for continuous k-th 5 | % order polynomial approximations on the reference interval. 6 | % 7 | % Parameters: 8 | % - k : polynomial order for the approximate solution 9 | % 10 | % Returns: 11 | % - M_R : Mass matrix on the reference interval 12 | % - S_R : Stiffness matrix on the reference interval 13 | % - D_R : Differentiation matrix on the reference interval 14 | 15 | end -------------------------------------------------------------------------------- /fem_1d/get_matrices_1d_sol.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_1d/get_matrices_1d_sol.p -------------------------------------------------------------------------------- /fem_1d/main_fem_for_poisson_1d.m: -------------------------------------------------------------------------------- 1 | iter = 10; 2 | a = 0; % left-end point of the domain 3 | b = 1; % right-end point of the domain 4 | k = 3; % polynomial order for the approximate solution 5 | M = 2.^(1+(1:iter)); % the number of elements 6 | f = @(x) 25*pi^2*sin(5*pi*x); % RHS in the Poisson problem 7 | u_D = @(x) x*0; % Dirichlet boundary condition for the solution u 8 | Du = @(x) 5*pi*cos(5*pi*x); % Derivative of the exact solution for the model problem 9 | 10 | error = zeros(1,iter); 11 | h = 1./M; 12 | for j=1:iter 13 | [c4n, n4e, n4db, ind4e] = mesh_fem_1d(a, b, M(j), k); 14 | [M_R, S_R, D_R] = get_matrices_1d(k); 15 | u = fem_for_poisson_1d(c4n, n4e, n4db, ind4e, M_R, S_R, f, u_D); 16 | error(j) = compute_error_fem_1d(c4n, ind4e, M_R, D_R, u, Du); 17 | end 18 | rateE = (log(error(2:end)) - log(error(1:end-1))) ./ (log(h(2:end)) - log(h(1:end-1))); 19 | disp(rateE) 20 | -------------------------------------------------------------------------------- /fem_1d/mesh_fem_1d.m: -------------------------------------------------------------------------------- 1 | function [c4n, n4e, n4db, ind4e] = mesh_fem_1d(a, b, M, k) 2 | %mesh_fem_1d Mesh geometry on 1 dimensional domain 3 | % mesh_fem_1d(a, b, M, k) generates an uniform mesh on the domain [a,b] 4 | % in 1D with mesh size h = 1/M. Also this code returns an index matrix 5 | % for continuous k-th order polynomial approximations. 6 | % 7 | % Parameters: 8 | % - a : left-end point for the domain 9 | % - b : right-end point for the domain 10 | % - M : the number of elements 11 | % - k : polynomial order for the approximate solution 12 | % 13 | % Returns 14 | % - c4n : coordinates for All nodes. 15 | % - n4e : nodes for elements. 16 | % - n4db : nodes for Dirichlet boundary. 17 | % - ind4e : index for elements 18 | 19 | nrNodes = k*M + 1; % the number of nodes on the mesh in terms of k and N 20 | c4n = linspace(a, b, nrNodes)'; 21 | n4e = [1:k:(nrNodes-1); (k+1):k:nrNodes]'; 22 | n4db = [1, nrNodes]'; 23 | ind4e = repmat(n4e(:,1), 1, k+1) + repmat((0:k), M, 1); 24 | end -------------------------------------------------------------------------------- /fem_2d_rectangle/compute_error_fem_2d_rectangle.m: -------------------------------------------------------------------------------- 1 | function error = compute_error_fem_2d_rectangle(c4n, n4e, ind4e, M_R, ... 2 | Dr_R, Ds_R, u, ux, uy) 3 | % compute_error_fem_2d_rectangle Semi H1 error (2D rectangular element) 4 | % compute_error_fem_2d_rectangle(c4n,n4e,ind4e,M_R,Dr_R,Ds_R,u,ux,uy) 5 | % computes the semi H1 error between the exact solution and the FE solution. 6 | % 7 | % Parameters: 8 | % - c4n : coordinates for nodes. 9 | % - n4e : nodes for elements. 10 | % - ind4e : indices for elements 11 | % - M_R : Mass matrix on the reference interval 12 | % - Dr_R : Differentiation matrix along r-direction on the reference 13 | % interval 14 | % - Ds_R : Differentiation matrix along s-direction on the reference 15 | % interval 16 | % - u : numerical solution 17 | % - ux : Derivative of the exact solution with respect to x for the 18 | % model problem 19 | % - uy : Derivative of the exact solution with respect to y for the 20 | % model problem 21 | % 22 | % Returns: 23 | % - error : Semi H1 error between the exact solution and the FE solution. 24 | 25 | error = 0; 26 | for j=1:size(ind4e,1) 27 | xr = (c4n(n4e(j,2),1)-c4n(n4e(j,1),1))/2; 28 | ys = (c4n(n4e(j,4),2)-c4n(n4e(j,1),2))/2; 29 | J = xr*ys; 30 | rx = ys/J; sy = xr/J; 31 | 32 | Dx_u = rx*Dr_R*u(ind4e(j,:)); 33 | Dy_u = sy*Ds_R*u(ind4e(j,:)); 34 | Dex = ux(c4n(ind4e(j,:),:)) - Dx_u; 35 | Dey = uy(c4n(ind4e(j,:),:)) - Dy_u; 36 | error = error + J*(Dex'*M_R*Dex + Dey'*M_R*Dey); 37 | end 38 | error = sqrt(error); 39 | end -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_2d_rectangle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_rectangle/fem_2d_rectangle.pdf -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_2d_rectangle_exercise1.m: -------------------------------------------------------------------------------- 1 | % Exercise 1. Add the matrices for the cubic approximations (k=3) in 2 | % get_matrices_2d_rectangle.m and check the convergence rate. 3 | % 4 | % After you modify get_matrices_2d_rectangle.m, run this code in command window. 5 | % >> fem_2d_rectangle_exercise1() -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_2d_rectangle_exercise1.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_rectangle/fem_2d_rectangle_exercise1.p -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_2d_rectangle_exercise2.m: -------------------------------------------------------------------------------- 1 | % Exercise 2. Modify fem_for_poisson_2d_rectangle_ex2.m to solve the Poisson 2 | % problem with non-homogeneous Dirichlet boundary condition, 3 | % 4 | % - div(grad u) = f(x) in \Omega \\ 5 | % u(x) = u_D(x) on \partial\Omega. \\ 6 | % 7 | % After you modify fem_for_poisson_2d_rectangle_ex2.m, run this code in command window. 8 | % >> fem_2d_rectangle_exercise2() 9 | % 10 | % 11 | % 12 | % 13 | % The following is the main code. If your code is right, the convergence 14 | % rate is k. 15 | % You can also compare the solution obtained from fem_for_poisson_2d_rectangle_ex2.m 16 | % with that from fem_for_poisson_2d_rectangle_ex2_sol.m 17 | % 18 | % iter = 5; 19 | % k = 3; 20 | % xl = 0; xr = 1; yl = 0; yr = 1; M = 2.^(1:iter); 21 | % f=@(x) 2*pi^2*sin(pi*x(:,1)).*sin(pi*x(:,2)) - 2; 22 | % u_D=@(x) x(:,1)*0 + x(:,1).^2; 23 | % ux=@(x) pi*cos(pi*x(:,1)).*sin(pi*x(:,2)) + 2*x(:,1); 24 | % uy=@(x) pi*sin(pi*x(:,1)).*cos(pi*x(:,2)); 25 | % 26 | % error=zeros(1,iter); 27 | % time=zeros(1,iter); 28 | % h=1./M; 29 | % for j=1:iter 30 | % [c4n,n4e,ind4e,n4db] = mesh_fem_2d_rectangle(xl,xr,yl,yr,M(j),M(j),k); 31 | % [M_R, Srr_R, Sss_R, Dr_R, Ds_R] = get_matrices_2d_rectangle(k); 32 | % u = fem_for_poisson_2d_rectangle_ex2(c4n,n4e,n4db,ind4e,M_R,Srr_R,Sss_R,f,u_D); 33 | % error(j) = compute_error_fem_2d_rectangle(c4n,n4e,ind4e,M_R,Dr_R,Ds_R,u,ux,uy); 34 | % disp(j) 35 | % end 36 | % convergence_rate = (log(error(2:end)) - log(error(1:end-1))) ./ (log(h(2:end)) - log(h(1:end-1))); 37 | % str1 = sprintf('Convergence rate for k = %d \n', k); 38 | % disp(str1) 39 | % disp(num2str(convergence_rate)) -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_2d_rectangle_exercise2.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_rectangle/fem_2d_rectangle_exercise2.p -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_2d_rectangle_exercise3.m: -------------------------------------------------------------------------------- 1 | % Exercise 3. Modify fem_for_poisson_2d_rectangle_ex3.m to solve the Poisson 2 | % problem with mixed boundary condition, 3 | % 4 | % - div(grad u) = f(x) in \Omega \\ 5 | % u(x) = u_D(x) on \Gamma_D \\ 6 | % grad u(x).n = u_N(x) on \Gamma_N. 7 | % 8 | % After you modify fem_for_poisson_2d_rectangle_ex3.m, run this code in 9 | % command window. 10 | % >> fem_2d_rectangle_exercise3() 11 | % 12 | % 13 | % 14 | % 15 | % The following is the main code. If your code is right, the convergence 16 | % rate is k. 17 | % You can also compare the solution obtained from fem_for_poisson_2d_rectangle_ex3.m 18 | % with that from fem_for_poisson_2d_rectangle_ex3_sol.m 19 | % 20 | % iter = 5; 21 | % k = 3; 22 | % xl = 0; xr = 1; yl = 0; yr = 1; M = 2.^(1:iter); 23 | % f=@(x) 2*pi^2*sin(pi*x(:,1)).*sin(pi*x(:,2)) - 2; 24 | % u_D=@(x) x(:,1)*0 + x(:,1).^2; 25 | % u_N=@(x) -pi*sin(pi*x(:,1)).*cos(pi*x(:,2)); 26 | % ux=@(x) pi*cos(pi*x(:,1)).*sin(pi*x(:,2)) + 2*x(:,1); 27 | % uy=@(x) pi*sin(pi*x(:,1)).*cos(pi*x(:,2)); 28 | % 29 | % error=zeros(1,iter); 30 | % time=zeros(1,iter); 31 | % h=1./M; 32 | % for j=1:iter 33 | % [c4n,n4e,ind4e,n4db] = mesh_fem_2d_rectangle(xl,xr,yl,yr,M(j),M(j),k); 34 | % n4nb = repmat(1:(k+1),M(j),1) + repmat((0:k:(k*M(j)-1))',1,k+1); 35 | % n4db = n4db([1,(k*M(j)+1):end]); 36 | % [M_R, Srr_R, Sss_R, Dr_R, Ds_R] = get_matrices_2d_rectangle(k); 37 | % M_R1D = get_matrices_1d(k); 38 | % u = fem_for_poisson_2d_rectangle_ex3(c4n, n4e, ... 39 | % n4db, n4nb, ind4e, M_R, Srr_R, Sss_R, M_R1D, f, u_D, u_N); 40 | % error(j) = compute_error_fem_2d_rectangle(c4n,n4e,ind4e,M_R,Dr_R,Ds_R,u,ux,uy); 41 | % disp(j) 42 | % end 43 | % convergence_rate = (log(error(2:end)) - log(error(1:end-1))) ./ (log(h(2:end)) - log(h(1:end-1))); 44 | % str1 = sprintf('Convergence rate for k = %d \n', k); 45 | % disp(str1) 46 | % disp(num2str(convergence_rate)) -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_2d_rectangle_exercise3.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_rectangle/fem_2d_rectangle_exercise3.p -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_for_poisson_2d_rectangle.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, freenodes] = fem_for_poisson_2d_rectangle(c4n, n4e, ... 2 | n4db, ind4e, M_R, Srr_R, Sss_R, f, u_D) 3 | % fem_for_poisson_2d_rectangle FEM solver for Poisson problem in 2D with 4 | % rectangular elements 5 | % 6 | % fem_for_poisson_2d_rectangle(c4n,n4e,n4db,ind4e,M_R,Srr_R,Sss_R,f,u_D) 7 | % solves the Poisson problem. In order to use this code, mesh information 8 | % (c4n, n4e, n4db, ind4e), matrices (M_R, Srr_R, Sss_R), the source f, 9 | % and the boundary condition u_D. Then the results of this code are the 10 | % numerical solution u, the global stiffness matrix A, the global load 11 | % vector b and the freenodes. 12 | % 13 | % Parameters: 14 | % - c4n : coordinates for nodes. 15 | % - n4e : nodes for elements. 16 | % - n4db : nodes for Dirichlet boundary. 17 | % - ind4e : indices for elements 18 | % - M_R : Mass matrix on the reference interval 19 | % - Srr_R : Stiffness matrix on the reference interval 20 | % - Sss_R : Stiffness matrix on the reference interval 21 | % - f : RHS in the Poisson problem 22 | % - u_D : Dirichlet boundary condition for the solution u 23 | % 24 | % Returns: 25 | % - u : numerical solution 26 | % - A : Global stiffness matrix 27 | % - b : Global right-hand side 28 | % - freenodes : free nodes 29 | 30 | number_of_nodes = size(c4n,1); 31 | A = sparse(number_of_nodes, number_of_nodes); 32 | b = zeros(number_of_nodes, 1); 33 | u = b; 34 | for j = 1:length(n4e) 35 | xr = (c4n(n4e(j,2),1)-c4n(n4e(j,1),1))/2; 36 | ys = (c4n(n4e(j,4),2)-c4n(n4e(j,1),2))/2; 37 | J = xr*ys; 38 | rx=ys/J; sy=xr/J; 39 | 40 | A(ind4e(j,:), ind4e(j,:)) = A(ind4e(j,:),ind4e(j,:)) ... 41 | + J*(rx^2*Srr_R + sy^2*Sss_R); 42 | b(ind4e(j,:)) = b(ind4e(j,:)) + J*M_R*f(c4n(ind4e(j,:),:)); 43 | end 44 | freenodes = setdiff(1:length(c4n), n4db); 45 | u(n4db) = u_D(c4n(n4db,:)); 46 | u(freenodes) = A(freenodes, freenodes)\b(freenodes); 47 | end -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_for_poisson_2d_rectangle_ex2.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, freenodes] = fem_for_poisson_2d_rectangle_ex2(c4n, n4e, ... 2 | n4db, ind4e, M_R, Srr_R, Sss_R, f, u_D) 3 | % fem_for_poisson_2d_rectangle_ex2 FEM solver for Poisson problem in 2D with 4 | % rectangular elements 5 | % 6 | % fem_for_poisson_2d_rectangle_ex2(c4n,n4e,n4db,ind4e,M_R,Srr_R,Sss_R,f,u_D) 7 | % solves the Poisson problem. In order to use this code, mesh information 8 | % (c4n, n4e, n4db, ind4e), matrices (M_R, Srr_R, Sss_R), the source f, 9 | % and the boundary condition u_D. Then the results of this code are the 10 | % numerical solution u, the global stiffness matrix A, the global load 11 | % vector b and the freenodes. 12 | % 13 | % Parameters: 14 | % - c4n : coordinates for nodes. 15 | % - n4e : nodes for elements. 16 | % - n4db : nodes for Dirichlet boundary. 17 | % - ind4e : indices for elements 18 | % - M_R : Mass matrix on the reference interval 19 | % - Srr_R : Stiffness matrix on the reference interval 20 | % - Sss_R : Stiffness matrix on the reference interval 21 | % - f : RHS in the Poisson problem 22 | % - u_D : Dirichlet boundary condition for the solution u 23 | % 24 | % Returns: 25 | % - u : numerical solution 26 | % - A : Global stiffness matrix 27 | % - b : Global right-hand side 28 | % - freenodes : free nodes 29 | 30 | number_of_nodes = size(c4n,1); 31 | A = sparse(number_of_nodes, number_of_nodes); 32 | b = zeros(number_of_nodes, 1); 33 | u = b; 34 | for j = 1:length(n4e) 35 | xr = (c4n(n4e(j,2),1)-c4n(n4e(j,1),1))/2; 36 | ys = (c4n(n4e(j,4),2)-c4n(n4e(j,1),2))/2; 37 | J = xr*ys; 38 | rx=ys/J; sy=xr/J; 39 | 40 | A(ind4e(j,:), ind4e(j,:)) = A(ind4e(j,:),ind4e(j,:)) ... 41 | + J*(rx^2*Srr_R + sy^2*Sss_R); 42 | b(ind4e(j,:)) = b(ind4e(j,:)) + J*M_R*f(c4n(ind4e(j,:),:)); 43 | end 44 | freenodes = setdiff(1:length(c4n), n4db); 45 | u(n4db) = u_D(c4n(n4db,:)); 46 | 47 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 48 | % TODO: Add a few lines to treat non-homogeneous Dirichlet boundary 49 | % condition. 50 | 51 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 52 | 53 | u(freenodes) = A(freenodes, freenodes)\b(freenodes); 54 | end -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_for_poisson_2d_rectangle_ex2_sol.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, freenodes] = fem_for_poisson_2d_rectangle_ex2_sol(c4n, n4e, ... 2 | n4db, ind4e, M_R, Srr_R, Sss_R, f, u_D) 3 | % fem_for_poisson_2d_rectangle_ex2_sol FEM solver for Poisson problem in 2D with 4 | % rectangular elements 5 | % 6 | % fem_for_poisson_2d_rectangle_ex2_sol(c4n,n4e,n4db,ind4e,M_R,Srr_R,Sss_R,f,u_D) 7 | % solves the Poisson problem. In order to use this code, mesh information 8 | % (c4n, n4e, n4db, ind4e), matrices (M_R, Srr_R, Sss_R), the source f, 9 | % and the boundary condition u_D. Then the results of this code are the 10 | % numerical solution u, the global stiffness matrix A, the global load 11 | % vector b and the freenodes. 12 | % 13 | % Parameters: 14 | % - c4n : coordinates for nodes. 15 | % - n4e : nodes for elements. 16 | % - n4db : nodes for Dirichlet boundary. 17 | % - ind4e : indices for elements 18 | % - M_R : Mass matrix on the reference interval 19 | % - Srr_R : Stiffness matrix on the reference interval 20 | % - Sss_R : Stiffness matrix on the reference interval 21 | % - f : RHS in the Poisson problem 22 | % - u_D : Dirichlet boundary condition for the solution u 23 | % 24 | % Returns: 25 | % - u : numerical solution 26 | % - A : Global stiffness matrix 27 | % - b : Global right-hand side 28 | % - freenodes : free nodes 29 | end -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_for_poisson_2d_rectangle_ex2_sol.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_rectangle/fem_for_poisson_2d_rectangle_ex2_sol.p -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_for_poisson_2d_rectangle_ex3.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, freenodes] = fem_for_poisson_2d_rectangle_ex3(c4n, n4e, ... 2 | n4db, n4nb, ind4e, M_R, Srr_R, Sss_R, M_R1D, f, u_D, u_N) 3 | % fem_for_poisson_2d_rectangle_ex3 FEM solver for Poisson problem in 2D with 4 | % rectangular elements 5 | % 6 | % fem_for_poisson_2d_rectangle_ex3(c4n,n4e,n4db,n4nb,ind4e,M_R, ... 7 | % Srr_R,Sss_R,M_R1D,f,u_D,u_N) solves the Poisson problem. In order to 8 | % use this code, mesh information (c4n, n4e, n4db, ind4e), matrices (M_R, 9 | % Srr_R, Sss_R), the source f, and the boundary condition u_D. Then the 10 | % results of this code are the numerical solution u, the global stiffness 11 | % matrix A, the global load vector b and the freenodes. 12 | % 13 | % Parameters: 14 | % - c4n : coordinates for nodes. 15 | % - n4e : nodes for elements. 16 | % - n4db : nodes for Dirichlet boundary. 17 | % - n4nb : nodes for Neumann boundary. 18 | % - ind4e : indices for elements 19 | % - M_R : Mass matrix on the reference rectangle 20 | % - Srr_R : Stiffness matrix on the reference rectangle 21 | % - Sss_R : Stiffness matrix on the reference rectangle 22 | % - M_R1D : Mass matrix on the reference interval in 1D 23 | % - f : RHS in the Poisson problem 24 | % - u_D : Dirichlet boundary condition for the solution u 25 | % - u_N : Neumann boundary condition for the solution u 26 | % 27 | % Returns: 28 | % - u : numerical solution 29 | % - A : Global stiffness matrix 30 | % - b : Global right-hand side 31 | % - freenodes : free nodes 32 | 33 | number_of_nodes = size(c4n,1); 34 | A = sparse(number_of_nodes, number_of_nodes); 35 | b = zeros(number_of_nodes, 1); 36 | u = b; 37 | for j = 1:size(n4e,1) 38 | xr = (c4n(n4e(j,2),1)-c4n(n4e(j,1),1))/2; 39 | ys = (c4n(n4e(j,4),2)-c4n(n4e(j,1),2))/2; 40 | J = xr*ys; 41 | rx=ys/J; sy=xr/J; 42 | 43 | A(ind4e(j,:), ind4e(j,:)) = A(ind4e(j,:),ind4e(j,:)) ... 44 | + J*(rx^2*Srr_R + sy^2*Sss_R); 45 | b(ind4e(j,:)) = b(ind4e(j,:)) + J*M_R*f(c4n(ind4e(j,:),:)); 46 | end 47 | 48 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 49 | % TODO: Add a few lines to treat Neumann boundary condition. 50 | % Hint: You can use Jacobian and Mass matrix in 1D. 51 | 52 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 53 | 54 | freenodes = setdiff(1:length(c4n), n4db); 55 | u(n4db) = u_D(c4n(n4db,:)); 56 | 57 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 58 | % TODO: Add a few lines to treat non-homogeneous Dirichlet boundary 59 | % condition. If you finished Exercise 2, the following lines can be copied 60 | % from fem_for_poisson_2d_rectangle_ex2.m 61 | 62 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 63 | 64 | u(freenodes) = A(freenodes, freenodes)\b(freenodes); 65 | end -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_for_poisson_2d_rectangle_ex3_sol.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, freenodes] = fem_for_poisson_2d_rectangle_ex3_sol(c4n, n4e, ... 2 | n4db, n4nb, ind4e, M_R, Srr_R, Sss_R, M_R1D, f, u_D, u_N) 3 | % fem_for_poisson_2d_rectangle_ex3_sol FEM solver for Poisson problem in 2D with 4 | % rectangular elements 5 | % 6 | % fem_for_poisson_2d_rectangle_ex3_sol(c4n,n4e,n4db,n4nb,ind4e,M_R, ... 7 | % Srr_R,Sss_R,M_R1D,f,u_D,u_N) solves the Poisson problem. In order to 8 | % use this code, mesh information (c4n, n4e, n4db, ind4e), matrices (M_R, 9 | % Srr_R, Sss_R), the source f, and the boundary condition u_D. Then the 10 | % results of this code are the numerical solution u, the global stiffness 11 | % matrix A, the global load vector b and the freenodes. 12 | % 13 | % Parameters: 14 | % - c4n : coordinates for nodes. 15 | % - n4e : nodes for elements. 16 | % - n4db : nodes for Dirichlet boundary. 17 | % - n4nb : nodes for Neumann boundary. 18 | % - ind4e : indices for elements 19 | % - M_R : Mass matrix on the reference rectangle 20 | % - Srr_R : Stiffness matrix on the reference rectangle 21 | % - Sss_R : Stiffness matrix on the reference rectangle 22 | % - M_R1D : Mass matrix on the reference interval in 1D 23 | % - f : RHS in the Poisson problem 24 | % - u_D : Dirichlet boundary condition for the solution u 25 | % - u_N : Neumann boundary condition for the solution u 26 | % 27 | % Returns: 28 | % - u : numerical solution 29 | % - A : Global stiffness matrix 30 | % - b : Global right-hand side 31 | % - freenodes : free nodes 32 | end -------------------------------------------------------------------------------- /fem_2d_rectangle/fem_for_poisson_2d_rectangle_ex3_sol.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_rectangle/fem_for_poisson_2d_rectangle_ex3_sol.p -------------------------------------------------------------------------------- /fem_2d_rectangle/get_matrices_2d_rectangle.m: -------------------------------------------------------------------------------- 1 | function [M_R, Srr_R, Sss_R, Dr_R, Ds_R] = get_matrices_2d_rectangle(k) 2 | % get_matrices_2d_rectangle Matrices for Poisson using FEM in 2D 3 | % get_matrices_2d_rectangle(k) generates the mass matrix M_R, the 4 | % stiffness matrices Srr_R and Sss_R, and the differentiation matrices 5 | % Dr_R and Ds_R for continuous k-th order polynomial approximations on 6 | % the reference rectangle. 7 | % 8 | % Parameters: 9 | % - k : polynomial order for the approximate solution 10 | % 11 | % Returns: 12 | % - M_R : Mass matrix on the reference interval 13 | % - Srr_R : Stiffness matrix on the reference interval 14 | % - Sss_R : Stiffness matrix on the reference interval 15 | % - Dr_R : Differentiation matrix with respect to r on the reference 16 | % rectangle 17 | % - Ds_R : Differentiation matrix with respect to s on the reference 18 | % rectangle 19 | 20 | if k==1 21 | M_R = [4 2 2 1; 2 4 1 2; 2 1 4 2; 1 2 2 4]/9; 22 | Srr_R = [2 -2 1 -1; -2 2 -1 1; 1 -1 2 -2; -1 1 -2 2]/6; 23 | Sss_R = [2 1 -2 -1; 1 2 -1 -2; -2 -1 2 1; -1 -2 1 2]/6; 24 | Dr_R = [-1 1 0 0; -1 1 0 0; 0 0 -1 1; 0 0 -1 1]/2; 25 | Ds_R = [-1 0 1 0; 0 -1 0 1; -1 0 1 0; 0 -1 0 1]/2; 26 | elseif k==2 27 | M_R = [16 8 -4 8 4 -2 -4 -2 1; 8 64 8 4 32 4 -2 -16 -2; 28 | -4 8 16 -2 4 8 1 -2 -4; 8 4 -2 64 32 -16 8 4 -2; 29 | 4 32 4 32 256 32 4 32 4; -2 4 8 -16 32 64 -2 4 8; 30 | -4 -2 1 8 4 -2 16 8 -4; -2 -16 -2 4 32 4 8 64 8; 31 | 1 -2 -4 -2 4 8 -4 8 16]/225; 32 | Srr_R = [28 -32 4 14 -16 2 -7 8 -1; -32 64 -32 -16 32 -16 8 -16 8; 33 | 4 -32 28 2 -16 14 -1 8 -7; 14 -16 2 112 -128 16 14 -16 2; 34 | -16 32 -16 -128 256 -128 -16 32 -16; 2 -16 14 16 -128 112 2 -16 14; 35 | -7 8 -1 14 -16 2 28 -32 4; 8 -16 8 -16 32 -16 -32 64 -32; 36 | -1 8 -7 2 -16 14 4 -32 28]/90; 37 | Sss_R = [28 14 -7 -32 -16 8 4 2 -1; 14 112 14 -16 -128 -16 2 16 2; 38 | -7 14 28 8 -16 -32 -1 2 4; -32 -16 8 64 32 -16 -32 -16 8; 39 | -16 -128 -16 32 256 32 -16 -128 -16; 8 -16 -32 -16 32 64 8 -16 -32; 40 | 4 2 -1 -32 -16 8 28 14 -7; 2 16 2 -16 -128 -16 14 112 14; 41 | -1 2 4 8 -16 -32 -7 14 28]/90; 42 | Dr_R = [-3 4 -1 0 0 0 0 0 0; -1 0 1 0 0 0 0 0 0; 1 -4 3 0 0 0 0 0 0; 43 | 0 0 0 -3 4 -1 0 0 0; 0 0 0 -1 0 1 0 0 0; 0 0 0 1 -4 3 0 0 0; 44 | 0 0 0 0 0 0 -3 4 -1; 0 0 0 0 0 0 -1 0 1; 0 0 0 0 0 0 1 -4 3]/2; 45 | Ds_R = [-3 0 0 4 0 0 -1 0 0; 0 -3 0 0 4 0 0 -1 0; 0 0 -3 0 0 4 0 0 -1; 46 | -1 0 0 0 0 0 1 0 0; 0 -1 0 0 0 0 0 1 0; 0 0 -1 0 0 0 0 0 1; 47 | 1 0 0 -4 0 0 3 0 0; 0 1 0 0 -4 0 0 3 0; 0 0 1 0 0 -4 0 0 3]/2; 48 | else 49 | M_R = 0; Srr_R = 0; Sss_R = 0; Dr_R = 0; Ds_R = 0; 50 | end 51 | end -------------------------------------------------------------------------------- /fem_2d_rectangle/get_matrices_2d_rectangle_sol.m: -------------------------------------------------------------------------------- 1 | function [M_R, Srr_R, Sss_R, Dr_R, Ds_R] = get_matrices_2d_rectangle_sol(k) 2 | % get_matrices_2d_rectangle Matrices for Poisson using FEM in 2D 3 | % get_matrices_2d_rectangle(k) generates the mass matrix M_R, the 4 | % stiffness matrices Srr_R and Sss_R, and the differentiation matrices 5 | % Dr_R and Ds_R for continuous k-th order polynomial approximations on 6 | % the reference rectangle. 7 | % 8 | % Parameters: 9 | % - k : polynomial order for the approximate solution 10 | % 11 | % Returns: 12 | % - M_R : Mass matrix on the reference interval 13 | % - Srr_R : Stiffness matrix on the reference interval 14 | % - Sss_R : Stiffness matrix on the reference interval 15 | % - Dr_R : Differentiation matrix with respect to r on the reference 16 | % rectangle 17 | % - Ds_R : Differentiation matrix with respect to s on the reference 18 | % rectangle 19 | end -------------------------------------------------------------------------------- /fem_2d_rectangle/get_matrices_2d_rectangle_sol.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_rectangle/get_matrices_2d_rectangle_sol.p -------------------------------------------------------------------------------- /fem_2d_rectangle/main_fem_for_poisson_2d_rectangle.m: -------------------------------------------------------------------------------- 1 | clear 2 | tic 3 | iter = 6; 4 | k = 1; 5 | xl = 0; xr = 1; yl = 0; yr = 1; M = 2.^(1:iter); 6 | f=@(x) 2*pi^2*sin(pi*x(:,1)).*sin(pi*x(:,2)); 7 | u_D=@(x) x(:,1)*0; 8 | ux=@(x) pi*cos(pi*x(:,1)).*sin(pi*x(:,2)); 9 | uy=@(x) pi*sin(pi*x(:,1)).*cos(pi*x(:,2)); 10 | 11 | error=zeros(1,iter); 12 | time=zeros(1,iter); 13 | h=1./M; 14 | for j=1:iter 15 | [c4n,n4e,ind4e,n4db] = mesh_fem_2d_rectangle(xl,xr,yl,yr,M(j),M(j),k); 16 | [M_R, Srr_R, Sss_R, Dr_R, Ds_R] = get_matrices_2d_rectangle(k); 17 | u = fem_for_poisson_2d_rectangle(c4n,n4e,n4db,ind4e,M_R,Srr_R,Sss_R,f,u_D); 18 | error(j) = compute_error_fem_2d_rectangle(c4n,n4e,ind4e,M_R,Dr_R,Ds_R,u,ux,uy); 19 | disp(j) 20 | end 21 | rateE=(log(error(2:end))-log(error(1:end-1)))./(log(h(2:end))-log(h(1:end-1))); 22 | disp(rateE) 23 | 24 | % clearvars -except h error time 25 | toc -------------------------------------------------------------------------------- /fem_2d_rectangle/mesh_fem_2d_rectangle.m: -------------------------------------------------------------------------------- 1 | function [c4n, n4e, ind4e, inddb] = mesh_fem_2d_rectangle(xl, xr, yl, yr, Mx, My, k) 2 | % mesh_fem_2d_rectangle Mesh geometry on 2D rectangular domain 3 | % mesh_fem_2d_rectangle(xl, xr, yl, yr, Mx, My, k) generates an 4 | % uniform mesh on the domain [xl,xr]x[yl,yr] in 2D with Mx elements 5 | % along x-direction and My elements along y-direction. Also this code 6 | % returns an index matrix for continuous k-th order polynomial 7 | % approximations. 8 | % 9 | % Parameters: 10 | % - xl : x-coordinate of bottom-left vertex of the domain 11 | % - xr : x-coordinate of top-right vertex of the domain 12 | % - yl : y-coordinate of bottom-left vertex of the domain 13 | % - yr : y-coordinate of top-right vertex of the domain 14 | % - Mx : the number of elements along x-direction 15 | % - My : the number of elements along y-direction 16 | % - k : polynomial order for the approximate solution 17 | % 18 | % Returns: 19 | % - c4n : coordinates for nodes. 20 | % - n4e : nodes for elements. 21 | % - n4db : nodes for Dirichlet boundary. 22 | % - ind4e : indices for elements 23 | 24 | % index 25 | ind4e = zeros(Mx*My, (k+1)^2); 26 | tmp = repmat((1:k:k*Mx)', 1, My) ... 27 | + repmat((0:k*(k*Mx+1):((k*Mx+1)*((My-1)*k+1)-1)), Mx, 1); 28 | tmp = tmp(:); 29 | for j=1:k+1 30 | ind4e(:,(j-1)*(k+1)+(1:(k+1))) = repmat(tmp+(j-1)*(k*Mx+1), 1, k+1) ... 31 | + repmat((0:k), Mx*My, 1); 32 | end 33 | 34 | % n4e 35 | n4e = ind4e(:,[1 k+1 (k+1)^2 (k*(k+1)+1)]); 36 | 37 | % indDb 38 | inddb = [1:(k*Mx+1), 2*(k*Mx+1):(k*Mx+1):(k*Mx+1)*(k*My+1), ... 39 | ((k*Mx+1)*(k*My+1)-1):-1:(k*My*(k*Mx+1)+1), ... 40 | ((k*My-1)*(k*Mx+1)+1):-(k*Mx+1):(k*Mx+2)]'; 41 | 42 | % c4n 43 | x = linspace(xl, xr, k*Mx+1); 44 | y = linspace(yl, yr, k*My+1); 45 | y = repmat(y, k*Mx+1, 1); 46 | x = repmat(x, k*My+1, 1)'; 47 | c4n = [x(:), y(:)]; 48 | end -------------------------------------------------------------------------------- /fem_2d_triangle/compute_error_fem_2d_triangle.m: -------------------------------------------------------------------------------- 1 | function error = compute_error_fem_2d_triangle(c4n,n4e,ind4e,M_R,Dr_R,Ds_R,u,ux,uy) 2 | %compute_error_fem_2d_triangle Semi H1 error (2D triangular element) 3 | % compute_error_fem_2d_triangle(c4n,n4e,ind4e,M_R,Dr_R,Ds_R,u,ux,uy) 4 | % computes the semi H1 error between the exact solution and the FE solution. 5 | % 6 | % Parameters: 7 | % - c4n : coordinates for nodes. 8 | % - n4e : nodes for elements. 9 | % - ind4e : indices for elements 10 | % - M_R : Mass matrix on the reference triangle 11 | % - Dr_R : Differentiation matrix with respect to r on the reference 12 | % triangle 13 | % - Ds_R : Differentiation matrix with respect to s on the reference 14 | % triangle 15 | % - u : numerical solution 16 | % - ux : Derivative of the exact solution with respect to x for the 17 | % model problem 18 | % - uy : Derivative of the exact solution with respect to y for the 19 | % model problem 20 | % 21 | % Returns: 22 | % - error Semi H1 error between the exact solution and the FE solution. 23 | 24 | error = 0; 25 | for j=1:size(n4e,1) 26 | xr = (c4n(n4e(j,1),1)-c4n(n4e(j,3),1))/2; 27 | yr = (c4n(n4e(j,1),2)-c4n(n4e(j,3),2))/2; 28 | xs = (c4n(n4e(j,2),1)-c4n(n4e(j,3),1))/2; 29 | ys = (c4n(n4e(j,2),2)-c4n(n4e(j,3),2))/2; 30 | J = xr*ys-xs*yr; 31 | rx=ys/J; ry=-xs/J; sx=-yr/J; sy=xr/J; 32 | 33 | Dx_u = (rx*Dr_R+sx*Ds_R)*u(ind4e(j,:)); 34 | Dy_u = (ry*Dr_R+sy*Ds_R)*u(ind4e(j,:)); 35 | Dex=ux(c4n(ind4e(j,:),:)) - Dx_u; 36 | Dey=uy(c4n(ind4e(j,:),:)) - Dy_u; 37 | error=error+J*(Dex'*M_R*Dex+Dey'*M_R*Dey); 38 | end 39 | error=sqrt(error); 40 | end -------------------------------------------------------------------------------- /fem_2d_triangle/fem_2d_triangle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_triangle/fem_2d_triangle.pdf -------------------------------------------------------------------------------- /fem_2d_triangle/fem_2d_triangle_exercise1.m: -------------------------------------------------------------------------------- 1 | % Exercise 1. Add the matrices for the cubic approximations (k=3) in 2 | % get_matrices_2d_triangle.m and check the convergence rate. 3 | % 4 | % After you modify get_matrices_2d_triangle.m, run this code in command window. 5 | % >> fem_2d_triangle_exercise1() -------------------------------------------------------------------------------- /fem_2d_triangle/fem_2d_triangle_exercise1.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_triangle/fem_2d_triangle_exercise1.p -------------------------------------------------------------------------------- /fem_2d_triangle/fem_2d_triangle_exercise2.m: -------------------------------------------------------------------------------- 1 | % Exercise 2. Modify fem_for_poisson_2d_triangle_ex2.m to solve the Poisson 2 | % problem with non-homogeneous Dirichlet boundary condition, 3 | % 4 | % - div(grad u) = f(x) in \Omega \\ 5 | % u(x) = u_D(x) on \partial\Omega. \\ 6 | % 7 | % After you modify fem_for_poisson_2d_triangle_ex2.m, run this code in command window. 8 | % >> fem_2d_triangle_exercise2() 9 | % 10 | % 11 | % 12 | % 13 | % The following is the main code. If your code is right, the convergence 14 | % rate is k. 15 | % You can also compare the solution obtained from fem_for_poisson_2d_triangle_ex2.m 16 | % with that from fem_for_poisson_2d_triangle_ex2_sol.m 17 | % 18 | % iter = 5; 19 | % k = 3; 20 | % xl = 0; xr = 1; yl = 0; yr = 1; M = 2.^(1:iter); 21 | % f=@(x) 2*pi^2*sin(pi*x(:,1)).*sin(pi*x(:,2)) - 2; 22 | % u_D=@(x) x(:,1)*0 + x(:,1).^2; 23 | % ux=@(x) pi*cos(pi*x(:,1)).*sin(pi*x(:,2)) + 2*x(:,1); 24 | % uy=@(x) pi*sin(pi*x(:,1)).*cos(pi*x(:,2)); 25 | % 26 | % error=zeros(1,iter); 27 | % time=zeros(1,iter); 28 | % h=1./M; 29 | % for j=1:iter 30 | % [c4n,n4e,ind4e,n4db] = mesh_fem_2d_triangle(xl,xr,yl,yr,M(j),M(j),k); 31 | % [M_R, Srr_R, Srs_R, Ssr_R, Sss_R, Dr_R, Ds_R] = get_matrices_2d_triangle_sol(k); 32 | % u = fem_for_poisson_2d_triangle_ex2(c4n,n4e,n4db,ind4e,M_R,Srr_R,Srs_R, ... 33 | % Ssr_R,Sss_R,f,u_D); 34 | % error(j) = compute_error_fem_2d_triangle(c4n,n4e,ind4e,M_R,Dr_R, ... 35 | % Ds_R,u,ux,uy); 36 | % disp(j) 37 | % end 38 | % convergence_rate = (log(error(2:end)) - log(error(1:end-1))) ./ (log(h(2:end)) - log(h(1:end-1))); 39 | % str1 = sprintf('Convergence rate for k = %d \n', k); 40 | % disp(str1) 41 | % disp(num2str(convergence_rate)) -------------------------------------------------------------------------------- /fem_2d_triangle/fem_2d_triangle_exercise2.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_triangle/fem_2d_triangle_exercise2.p -------------------------------------------------------------------------------- /fem_2d_triangle/fem_2d_triangle_exercise3.m: -------------------------------------------------------------------------------- 1 | % Exercise 3. Modify fem_for_poisson_2d_triangle_ex3.m to solve the Poisson 2 | % problem with mixed boundary condition, 3 | % 4 | % - div(grad u) = f(x) in \Omega \\ 5 | % u(x) = u_D(x) on \Gamma_D \\ 6 | % grad u(x).n = u_N(x) on \Gamma_N. 7 | % 8 | % After you modify fem_for_poisson_2d_triangle_ex3.m, run this code in 9 | % command window. 10 | % >> fem_2d_triangle_exercise3() 11 | % 12 | % 13 | % 14 | % 15 | % The following is the main code. If your code is right, the convergence 16 | % rate is k. 17 | % You can also compare the solution obtained from fem_for_poisson_2d_triangle_ex3.m 18 | % with that from fem_for_poisson_2d_triangle_ex3_sol.m 19 | % 20 | % iter = 5; 21 | % k = 3; 22 | % xl = 0; xr = 1; yl = 0; yr = 1; M = 2.^(1:iter); 23 | % f=@(x) 2*pi^2*sin(pi*x(:,1)).*sin(pi*x(:,2)) - 2; 24 | % u_D=@(x) x(:,1)*0 + x(:,1).^2; 25 | % u_N=@(x) -pi*sin(pi*x(:,1)).*cos(pi*x(:,2)); 26 | % ux=@(x) pi*cos(pi*x(:,1)).*sin(pi*x(:,2)) + 2*x(:,1); 27 | % uy=@(x) pi*sin(pi*x(:,1)).*cos(pi*x(:,2)); 28 | % 29 | % error=zeros(1,iter); 30 | % time=zeros(1,iter); 31 | % h=1./M; 32 | % for j=1:iter 33 | % [c4n,n4e,ind4e,n4db] = mesh_fem_2d_triangle(xl,xr,yl,yr,M(j),M(j),k); 34 | % n4nb = repmat(1:(k+1),M(j),1) + repmat((0:k:(k*M(j)-1))',1,k+1); 35 | % n4db = n4db([1,(k*M(j)+1):end]); 36 | % [M_R, Srr_R, Srs_R, Ssr_R, Sss_R, Dr_R, Ds_R] = get_matrices_2d_triangle_sol(k); 37 | % M_R1D = get_matrices_1d(k); 38 | % u = fem_for_poisson_2d_triangle_ex3(c4n,n4e,n4db, ... 39 | % n4nb,ind4e,M_R,Srr_R,Srs_R,Ssr_R,Sss_R,M_R1D,f,u_D,u_N); 40 | % error(j) = compute_error_fem_2d_triangle(c4n,n4e,ind4e,M_R,Dr_R, ... 41 | % Ds_R,u,ux,uy); 42 | % disp(j) 43 | % end 44 | % convergence_rate = (log(error(2:end)) - log(error(1:end-1))) ./ (log(h(2:end)) - log(h(1:end-1))); 45 | % str1 = sprintf('Convergence rate for k = %d \n', k); 46 | % disp(str1) 47 | % disp(num2str(convergence_rate)) -------------------------------------------------------------------------------- /fem_2d_triangle/fem_2d_triangle_exercise3.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_triangle/fem_2d_triangle_exercise3.p -------------------------------------------------------------------------------- /fem_2d_triangle/fem_for_poisson_2d_triangle.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, fns] = fem_for_poisson_2d_triangle(c4n,n4e,n4db, ... 2 | ind4e,M_R,Srr_R,Srs_R,Ssr_R,Sss_R,f,u_D) 3 | %fem_for_poisson_2d_triangle FEM solver for Poisson problem in 2D with 4 | % triangular elements 5 | % fem_for_poisson_2d_triangle(c4n,n4e,n4db,ind4e,M_R,Srr_R,Srs_R,Ssr_R, 6 | % Sss_R,f,u_D) solves the Poisson problem. In order to use this code, 7 | % mesh information (c4n,n4e,n4db,ind4e), matrices (M_R,Srr_R,Srs_R,Ssr_R, 8 | % Sss_R), the source f, and the boundary condition u_D. Then the results 9 | % of this code are the numerical solution u, the global stiffness matrix 10 | % A, the global load vector b and the freenodes. 11 | % 12 | % Parameters: 13 | % - c4n : coordinates for nodes. 14 | % - n4e : nodes for elements. 15 | % - n4db : nodes for Dirichlet boundary. 16 | % - ind4e : indices for elements 17 | % - M_R : Mass matrix on the reference triangle 18 | % - Srr_R : Stiffness matrix on the reference triangle 19 | % - Srs_R : Stiffness matrix on the reference triangle 20 | % - Ssr_R : Stiffness matrix on the reference triangle 21 | % - Sss_R : Stiffness matrix on the reference triangle 22 | % - f : RHS in the Poisson problem 23 | % - u_D : Dirichlet boundary condition for the solution u 24 | % 25 | % Returns: 26 | % - u : numerical solution 27 | % - A : Global stiffness matrix 28 | % - b : Global right-hand side 29 | % - fns : free nodes 30 | 31 | number_of_nodes = size(c4n,1); 32 | A = sparse(number_of_nodes,number_of_nodes); 33 | b = zeros(number_of_nodes,1); 34 | u = b; 35 | for j=1:size(n4e,1) 36 | xr = (c4n(n4e(j,1),1)-c4n(n4e(j,3),1))/2; 37 | yr = (c4n(n4e(j,1),2)-c4n(n4e(j,3),2))/2; 38 | xs = (c4n(n4e(j,2),1)-c4n(n4e(j,3),1))/2; 39 | ys = (c4n(n4e(j,2),2)-c4n(n4e(j,3),2))/2; 40 | J = xr*ys-xs*yr; 41 | rx=ys/J; ry=-xs/J; sx=-yr/J; sy=xr/J; 42 | 43 | A(ind4e(j,:),ind4e(j,:)) = A(ind4e(j,:),ind4e(j,:)) ... 44 | + J*((rx^2+ry^2)*Srr_R + (rx*sx+ry*sy)*(Srs_R+Ssr_R) + (sx^2+sy^2)*Sss_R); 45 | b(ind4e(j,:)) = b(ind4e(j,:)) + J*M_R*f(c4n(ind4e(j,:),:)); 46 | end 47 | fns = setdiff(1:number_of_nodes, n4db); 48 | u(n4db) = u_D(c4n(n4db,:)); 49 | u(fns) = A(fns,fns)\b(fns); 50 | end -------------------------------------------------------------------------------- /fem_2d_triangle/fem_for_poisson_2d_triangle_ex2.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, fns] = fem_for_poisson_2d_triangle_ex2(c4n,n4e,n4db, ... 2 | ind4e,M_R,Srr_R,Srs_R,Ssr_R,Sss_R,f,u_D) 3 | %fem_for_poisson_2d_triangle_ex2 FEM solver for Poisson problem in 2D with 4 | % triangular elements 5 | % fem_for_poisson_2d_triangle_ex2(c4n,n4e,n4db,ind4e,M_R,Srr_R,Srs_R,Ssr_R, 6 | % Sss_R,f,u_D) solves the Poisson problem. In order to use this code, 7 | % mesh information (c4n,n4e,n4db,ind4e), matrices (M_R,Srr_R,Srs_R,Ssr_R, 8 | % Sss_R), the source f, and the boundary condition u_D. Then the results 9 | % of this code are the numerical solution u, the global stiffness matrix 10 | % A, the global load vector b and the freenodes. 11 | % 12 | % Parameters: 13 | % - c4n : coordinates for nodes. 14 | % - n4e : nodes for elements. 15 | % - n4db : nodes for Dirichlet boundary. 16 | % - ind4e : indices for elements 17 | % - M_R : Mass matrix on the reference triangle 18 | % - Srr_R : Stiffness matrix on the reference triangle 19 | % - Srs_R : Stiffness matrix on the reference triangle 20 | % - Ssr_R : Stiffness matrix on the reference triangle 21 | % - Sss_R : Stiffness matrix on the reference triangle 22 | % - f : RHS in the Poisson problem 23 | % - u_D : Dirichlet boundary condition for the solution u 24 | % 25 | % Returns: 26 | % - u : numerical solution 27 | % - A : Global stiffness matrix 28 | % - b : Global right-hand side 29 | % - fns : free nodes 30 | 31 | number_of_nodes = size(c4n,1); 32 | A = sparse(number_of_nodes,number_of_nodes); 33 | b = zeros(number_of_nodes,1); 34 | u = b; 35 | for j=1:size(n4e,1) 36 | xr = (c4n(n4e(j,1),1)-c4n(n4e(j,3),1))/2; 37 | yr = (c4n(n4e(j,1),2)-c4n(n4e(j,3),2))/2; 38 | xs = (c4n(n4e(j,2),1)-c4n(n4e(j,3),1))/2; 39 | ys = (c4n(n4e(j,2),2)-c4n(n4e(j,3),2))/2; 40 | J = xr*ys-xs*yr; 41 | rx=ys/J; ry=-xs/J; sx=-yr/J; sy=xr/J; 42 | 43 | A(ind4e(j,:),ind4e(j,:)) = A(ind4e(j,:),ind4e(j,:)) ... 44 | + J*((rx^2+ry^2)*Srr_R + (rx*sx+ry*sy)*(Srs_R+Ssr_R) + (sx^2+sy^2)*Sss_R); 45 | b(ind4e(j,:)) = b(ind4e(j,:)) + J*M_R*f(c4n(ind4e(j,:),:)); 46 | end 47 | fns = setdiff(1:number_of_nodes, n4db); 48 | u(n4db) = u_D(c4n(n4db,:)); 49 | 50 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 51 | % TODO: Add a few lines to treat non-homogeneous Dirichlet boundary 52 | % condition. 53 | 54 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 55 | 56 | u(fns) = A(fns,fns)\b(fns); 57 | end -------------------------------------------------------------------------------- /fem_2d_triangle/fem_for_poisson_2d_triangle_ex2_sol.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, fns] = fem_for_poisson_2d_triangle_ex2_sol(c4n,n4e,n4db, ... 2 | ind4e,M_R,Srr_R,Srs_R,Ssr_R,Sss_R,f,u_D) 3 | %fem_for_poisson_2d_triangle_ex2_sol FEM solver for Poisson problem in 2D with 4 | % triangular elements 5 | % fem_for_poisson_2d_triangle_ex2_sol(c4n,n4e,n4db,ind4e,M_R,Srr_R,Srs_R,Ssr_R, 6 | % Sss_R,f,u_D) solves the Poisson problem. In order to use this code, 7 | % mesh information (c4n,n4e,n4db,ind4e), matrices (M_R,Srr_R,Srs_R,Ssr_R, 8 | % Sss_R), the source f, and the boundary condition u_D. Then the results 9 | % of this code are the numerical solution u, the global stiffness matrix 10 | % A, the global load vector b and the freenodes. 11 | % 12 | % Parameters: 13 | % - c4n : coordinates for nodes. 14 | % - n4e : nodes for elements. 15 | % - n4db : nodes for Dirichlet boundary. 16 | % - ind4e : indices for elements 17 | % - M_R : Mass matrix on the reference triangle 18 | % - Srr_R : Stiffness matrix on the reference triangle 19 | % - Srs_R : Stiffness matrix on the reference triangle 20 | % - Ssr_R : Stiffness matrix on the reference triangle 21 | % - Sss_R : Stiffness matrix on the reference triangle 22 | % - f : RHS in the Poisson problem 23 | % - u_D : Dirichlet boundary condition for the solution u 24 | % 25 | % Returns: 26 | % - u : numerical solution 27 | % - A : Global stiffness matrix 28 | % - b : Global right-hand side 29 | % - fns : free nodes 30 | end -------------------------------------------------------------------------------- /fem_2d_triangle/fem_for_poisson_2d_triangle_ex2_sol.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_triangle/fem_for_poisson_2d_triangle_ex2_sol.p -------------------------------------------------------------------------------- /fem_2d_triangle/fem_for_poisson_2d_triangle_ex3.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, fns] = fem_for_poisson_2d_triangle_ex3(c4n,n4e,n4db, ... 2 | n4nb,ind4e,M_R,Srr_R,Srs_R,Ssr_R,Sss_R,M_R1D,f,u_D,u_N) 3 | %fem_for_poisson_2d_triangle_ex3 FEM solver for Poisson problem in 2D with 4 | % triangular elements 5 | % fem_for_poisson_2d_triangle_ex3(c4n,n4e,n4db,n4nb,ind4e,M_R,Srr_R,Srs_R, 6 | % Ssr_R,Sss_R,M_R1D,f,u_D,u_N) solves the Poisson problem. In order to use 7 | % this code, mesh information (c4n,n4e,n4db,ind4e), matrices (M_R,Srr_R, 8 | % Srs_R,Ssr_R,Sss_R), the source f, and the boundary condition u_D. Then 9 | % the results of this code are the numerical solution u, the global 10 | % stiffness matrix A, the global load vector b and the freenodes. 11 | % 12 | % Parameters: 13 | % - c4n : coordinates for nodes. 14 | % - n4e : nodes for elements. 15 | % - n4db : nodes for Dirichlet boundary. 16 | % - n4nb : nodes for Neumann boundary. 17 | % - ind4e : indices for elements 18 | % - M_R : Mass matrix on the reference triangle 19 | % - Srr_R : Stiffness matrix on the reference triangle 20 | % - Srs_R : Stiffness matrix on the reference triangle 21 | % - Ssr_R : Stiffness matrix on the reference triangle 22 | % - Sss_R : Stiffness matrix on the reference triangle 23 | % - M_R1D : Mass matrix on the reference interval in 1D 24 | % - f : RHS in the Poisson problem 25 | % - u_D : Dirichlet boundary condition for the solution u 26 | % - u_N : Neumann boundary condition for the solution u 27 | % 28 | % Returns: 29 | % - u : numerical solution 30 | % - A : Global stiffness matrix 31 | % - b : Global right-hand side 32 | % - fns : free nodes 33 | 34 | number_of_nodes = size(c4n,1); 35 | A = sparse(number_of_nodes,number_of_nodes); 36 | b = zeros(number_of_nodes,1); 37 | u = b; 38 | for j=1:size(n4e,1) 39 | xr = (c4n(n4e(j,1),1)-c4n(n4e(j,3),1))/2; 40 | yr = (c4n(n4e(j,1),2)-c4n(n4e(j,3),2))/2; 41 | xs = (c4n(n4e(j,2),1)-c4n(n4e(j,3),1))/2; 42 | ys = (c4n(n4e(j,2),2)-c4n(n4e(j,3),2))/2; 43 | J = xr*ys-xs*yr; 44 | rx=ys/J; ry=-xs/J; sx=-yr/J; sy=xr/J; 45 | 46 | A(ind4e(j,:),ind4e(j,:)) = A(ind4e(j,:),ind4e(j,:)) ... 47 | + J*((rx^2+ry^2)*Srr_R + (rx*sx+ry*sy)*(Srs_R+Ssr_R) + (sx^2+sy^2)*Sss_R); 48 | b(ind4e(j,:)) = b(ind4e(j,:)) + J*M_R*f(c4n(ind4e(j,:),:)); 49 | end 50 | 51 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 52 | % TODO: Add a few lines to treat Neumann boundary condition. 53 | % Hint: You can use Jacobian and Mass matrix in 1D. 54 | 55 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 56 | 57 | fns = setdiff(1:number_of_nodes, n4db); 58 | u(n4db) = u_D(c4n(n4db,:)); 59 | 60 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 61 | % TODO: Add a few lines to treat non-homogeneous Dirichlet boundary 62 | % condition. 63 | 64 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 65 | 66 | u(fns) = A(fns,fns)\b(fns); 67 | end -------------------------------------------------------------------------------- /fem_2d_triangle/fem_for_poisson_2d_triangle_ex3_sol.m: -------------------------------------------------------------------------------- 1 | function [u, A, b, fns] = fem_for_poisson_2d_triangle_ex3_sol(c4n,n4e,n4db, ... 2 | n4nb,ind4e,M_R,Srr_R,Srs_R,Ssr_R,Sss_R,M_R1D,f,u_D,u_N) 3 | %fem_for_poisson_2d_triangle_ex3_sol FEM solver for Poisson problem in 2D 4 | % with triangular elements 5 | % fem_for_poisson_2d_triangle_ex3_sol(c4n,n4e,n4db,n4nb,ind4e,M_R,Srr_R,Srs_R, 6 | % Ssr_R,Sss_R,M_R1D,f,u_D,u_N) solves the Poisson problem. In order to use 7 | % this code, mesh information (c4n,n4e,n4db,ind4e), matrices (M_R,Srr_R, 8 | % Srs_R,Ssr_R,Sss_R), the source f, and the boundary condition u_D. Then 9 | % the results of this code are the numerical solution u, the global 10 | % stiffness matrix A, the global load vector b and the freenodes. 11 | % 12 | % Parameters: 13 | % - c4n : coordinates for nodes. 14 | % - n4e : nodes for elements. 15 | % - n4db : nodes for Dirichlet boundary. 16 | % - n4nb : nodes for Neumann boundary. 17 | % - ind4e : indices for elements 18 | % - M_R : Mass matrix on the reference triangle 19 | % - Srr_R : Stiffness matrix on the reference triangle 20 | % - Srs_R : Stiffness matrix on the reference triangle 21 | % - Ssr_R : Stiffness matrix on the reference triangle 22 | % - Sss_R : Stiffness matrix on the reference triangle 23 | % - M_R1D : Mass matrix on the reference interval in 1D 24 | % - f : RHS in the Poisson problem 25 | % - u_D : Dirichlet boundary condition for the solution u 26 | % - u_N : Neumann boundary condition for the solution u 27 | % 28 | % Returns: 29 | % - u : numerical solution 30 | % - A : Global stiffness matrix 31 | % - b : Global right-hand side 32 | % - fns : free nodes 33 | end -------------------------------------------------------------------------------- /fem_2d_triangle/fem_for_poisson_2d_triangle_ex3_sol.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_triangle/fem_for_poisson_2d_triangle_ex3_sol.p -------------------------------------------------------------------------------- /fem_2d_triangle/get_matrices_2d_triangle.m: -------------------------------------------------------------------------------- 1 | function [M_R, Srr_R, Srs_R, Ssr_R, Sss_R, Dr_R, Ds_R] = get_matrices_2d_triangle(k) 2 | %get_matrices_2d_triangle Matrices for Poisson using FEM in 2D 3 | % get_matrices_2d_triangle(k) generates the mass matrix M_R, the 4 | % stiffness matrices Srr_R, Srs_R, Ssr_R and Sss_R, and the 5 | % differentiation matrices Dr_R and Ds_R for continuous k-th order 6 | % polynomial approximations on the reference interval. 7 | % 8 | % Parameters: 9 | % - k : polynomial order for the approximate solution 10 | % 11 | % Returns: 12 | % - M_R : Mass matrix on the reference interval 13 | % - Srr_R : Stiffness matrix on the reference interval 14 | % - Srs_R : Stiffness matrix on the reference interval 15 | % - Ssr_R : Stiffness matrix on the reference interval 16 | % - Sss_R : Stiffness matrix on the reference interval 17 | % - Dr_R : Differentiation matrix with respect to r on the reference 18 | % triangle 19 | % - Ds_R : Differentiation matrix with respect to s on the reference 20 | % triangle 21 | 22 | if k==1 23 | M_R = [2 1 1; 1 2 1; 1 1 2]/6; 24 | Srr_R = [1 -1 0; -1 1 0; 0 0 0]/2; 25 | Srs_R = [1 0 -1; -1 0 1; 0 0 0]/2; 26 | Ssr_R = [1 -1 0; 0 0 0; -1 1 0]/2; 27 | Sss_R = [1 0 -1; 0 0 0; -1 0 1]/2; 28 | Dr_R = [-1 1 0; -1 1 0; -1 1 0]/2; 29 | Ds_R = [-1 0 1; -1 0 1; -1 0 1]/2; 30 | elseif k==2 31 | M_R = [6 0 -1 0 -4 -1; 0 32 0 16 16 -4; -1 0 6 -4 0 -1; 32 | 0 16 -4 32 16 0; -4 16 0 16 32 0; -1 -4 -1 0 0 6]/90; 33 | Srr_R = [3 -4 1 0 0 0; -4 8 -4 0 0 0; 1 -4 3 0 0 0; 34 | 0 0 0 8 -8 0; 0 0 0 -8 8 0; 0 0 0 0 0 0]/6; 35 | Srs_R = [3 0 0 -4 0 1; -4 4 0 4 -4 0; 1 -4 0 0 4 -1; 36 | 0 4 0 4 -4 -4; 0 -4 0 -4 4 4; 0 0 0 0 0 0]/6; 37 | Ssr_R = [3 -4 1 0 0 0; 0 4 -4 4 -4 0; 0 0 0 0 0 0; 38 | -4 4 0 4 -4 0; 0 -4 4 -4 4 0; 1 0 -1 -4 4 0]/6; 39 | Sss_R = [3 0 0 -4 0 1; 0 8 0 0 -8 0; 0 0 0 0 0 0; 40 | -4 0 0 8 0 -4; 0 -8 0 0 8 0; 1 0 0 -4 0 3]/6; 41 | Dr_R = [-3 4 -1 0 0 0; -1 0 1 0 0 0; 1 -4 3 0 0 0; 42 | -1 2 -1 -2 2 0; 1 -2 1 -2 2 0; 1 0 -1 -4 4 0]/2; 43 | Ds_R = [-3 0 0 4 0 -1; -1 -2 0 2 2 -1; 1 -4 0 0 4 -1; 44 | -1 0 0 0 0 1; 1 -2 0 -2 2 1; 1 0 0 -4 0 3]/2; 45 | else 46 | M_R = 0; Srr_R = 0; Srs_R = 0; Ssr_R = 0; Sss_R = 0; Dr_R = 0; Ds_R = 0; 47 | end 48 | end -------------------------------------------------------------------------------- /fem_2d_triangle/get_matrices_2d_triangle_sol.m: -------------------------------------------------------------------------------- 1 | function [M_R, Srr_R, Srs_R, Ssr_R, Sss_R, Dr_R, Ds_R] = get_matrices_2d_triangle_sol(k) 2 | %get_matrices_2d_triangle Matrices for Poisson using FEM in 2D 3 | % get_matrices_2d_triangle(k) generates the mass matrix M_R, the 4 | % stiffness matrices Srr_R, Srs_R, Ssr_R and Sss_R, and the 5 | % differentiation matrices Dr_R and Ds_R for continuous k-th order 6 | % polynomial approximations on the reference interval. 7 | % 8 | % Parameters: 9 | % - k : polynomial order for the approximate solution 10 | % 11 | % Returns: 12 | % - M_R : Mass matrix on the reference interval 13 | % - Srr_R : Stiffness matrix on the reference interval 14 | % - Srs_R : Stiffness matrix on the reference interval 15 | % - Ssr_R : Stiffness matrix on the reference interval 16 | % - Sss_R : Stiffness matrix on the reference interval 17 | % - Dr_R : Differentiation matrix with respect to r on the reference 18 | % triangle 19 | % - Ds_R : Differentiation matrix with respect to s on the reference 20 | % triangle 21 | end -------------------------------------------------------------------------------- /fem_2d_triangle/get_matrices_2d_triangle_sol.p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/fem_2d_triangle/get_matrices_2d_triangle_sol.p -------------------------------------------------------------------------------- /fem_2d_triangle/main_fem_for_poisson_2d_triangle.m: -------------------------------------------------------------------------------- 1 | clear 2 | tic 3 | iter = 6; 4 | k = 1; 5 | xl = 0; xr = 1; yl = 0; yr = 1; M = 2.^(1:iter); 6 | f=@(x) 2*pi^2*sin(pi*x(:,1)).*sin(pi*x(:,2)); 7 | u_D=@(x) x(:,1)*0; 8 | ux=@(x) pi*cos(pi*x(:,1)).*sin(pi*x(:,2)); 9 | uy=@(x) pi*sin(pi*x(:,1)).*cos(pi*x(:,2)); 10 | 11 | error=zeros(1,iter); 12 | time=zeros(1,iter); 13 | h=1./M; 14 | for j=1:iter 15 | [c4n,n4e,ind4e,n4db] = mesh_fem_2d_triangle(xl,xr,yl,yr,M(j),M(j),k); 16 | [M_R, Srr_R, Srs_R, Ssr_R, Sss_R, Dr_R, Ds_R] = get_matrices_2d_triangle(k); 17 | u = fem_for_poisson_2d_triangle(c4n,n4e,n4db,ind4e,M_R,Srr_R,Srs_R, ... 18 | Ssr_R,Sss_R,f,u_D); 19 | error(j) = compute_error_fem_2d_triangle(c4n,n4e,ind4e,M_R,Dr_R, ... 20 | Ds_R,u,ux,uy); 21 | disp(j) 22 | end 23 | rateE=(log(error(2:end))-log(error(1:end-1)))./(log(h(2:end))-log(h(1:end-1))); 24 | disp(rateE) 25 | toc -------------------------------------------------------------------------------- /fem_2d_triangle/mesh_fem_2d_triangle.m: -------------------------------------------------------------------------------- 1 | function [c4n, n4e, ind4e, inddb] = mesh_fem_2d_triangle(xl, xr, yl, yr, Mx, My, k) 2 | %mesh_fem_2d_triangle Mesh geometry on 2D rectangular domain 3 | % mesh_fem_2d_triangle(xl, xr, yl, yr, Mx, My, k) generates an uniform 4 | % triangular mesh on the domain [xl,xr]x[yl,yr] in 2D with Mx elements 5 | % along x-direction and My elements along y-direction. Also this code 6 | % returns an index matrix for continuous k-th order polynomial 7 | % approximations. 8 | % 9 | % 10 | % Parameters: 11 | % - xl : x-coordinate of bottom-left vertex of the domain 12 | % - xr : x-coordinate of top-right vertex of the domain 13 | % - yl : y-coordinate of bottom-left vertex of the domain 14 | % - yr : y-coordinate of top-right vertex of the domain 15 | % - Mx : the number of elements along x-direction 16 | % - My : the number of elements along y-direction 17 | % - k : polynomial order for the approximate solution 18 | % 19 | % Returns: 20 | % - c4n coordinates for nodes. 21 | % - n4e nodes for elements. 22 | % - ind4e indices for elements 23 | % - n4db nodes for Dirichlet boundary. 24 | 25 | % index 26 | ind4e = zeros(2*Mx*My,(k+1)*(k+2)/2); 27 | tmp = repmat((1:k:k*Mx)',1,My) ... 28 | + repmat((0:k*(k*Mx+1):((k*Mx+1)*((My-1)*k+1)-1)),Mx,1); 29 | tmp2 = repmat(((k+1):k:(k*Mx+1))',1,My) ... 30 | + repmat((k*(k*Mx+1):k*(k*Mx+1):((k*Mx+1)*(k*My))),Mx,1); 31 | tmp = tmp(:); tmp2=tmp2(:); 32 | for j=1:k+1 33 | ind4e(1:2:2*Mx*My,(1+(j-1)*(k+2-j/2))+(0:(k+1-j))) = ... 34 | repmat(tmp,1,k+2-j)+repmat(((j-1)*(Mx*k+1)+(0:(k+1-j))),Mx*My,1); 35 | ind4e(2:2:2*Mx*My,(1+(j-1)*(k+2-j/2))+(0:(k+1-j))) = ... 36 | repmat(tmp2,1,k+2-j)+repmat((-(j-1)*(Mx*k+1)-(0:(k+1-j))),Mx*My,1); 37 | end 38 | 39 | % n4e 40 | n4e = ind4e(:,[k+1 (k+1)*(k+2)/2 1]); 41 | 42 | % indDb 43 | inddb = [1:(k*Mx+1), 2*(k*Mx+1):(k*Mx+1):(k*Mx+1)*(k*My+1), ... 44 | ((k*Mx+1)*(k*My+1)-1):-1:(k*My*(k*Mx+1)+1), ... 45 | ((k*My-1)*(k*Mx+1)+1):-(k*Mx+1):(k*Mx+2)]; 46 | 47 | % c4n 48 | x=linspace(xl,xr,k*Mx+1); 49 | y=linspace(yl,yr,k*My+1); 50 | y=repmat(y,k*Mx+1,1); 51 | x=repmat(x,k*My+1,1)'; 52 | c4n = [x(:), y(:)]; 53 | end -------------------------------------------------------------------------------- /test.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dw-shin/basic_fem_tutorial/e05d36fbe8db3d9fd4eb30333f577eeb68620ad1/test.PNG --------------------------------------------------------------------------------