├── BESO3D ├── test.m ├── README.md └── SBESO3D.m ├── UCOpt2D ├── test.m ├── README.md ├── elementMatVec.m ├── Q4elementStiffnessMatrix.m ├── homogenize.m └── UCOpt.m ├── Level set 88 ├── test.m ├── README.md └── levelset88.m ├── BESO88 ├── tests.m ├── README.md └── SBESO88.m ├── Level set 3D ├── tests.m ├── README.md ├── D3_LB.m └── levelset3D.m ├── UCOpt3D ├── test.m ├── README.md ├── hexahedron.m ├── homo3DY.m ├── UCOpt3D.m └── Top3dSTL_v3.m ├── SIMP_3D MMA ├── test.m ├── README.md └── top3dmma.m ├── 2D Homogenization Young ├── test.m ├── README.md ├── elementMatVec.m └── homogenizeY.m ├── SIMP_88 MMA ├── tests.m ├── README.md └── top88MMA.m ├── 3D Homogenization Young ├── test.m ├── README.md ├── topology │ ├── x.txt │ ├── grid.txt │ ├── Star.txt │ ├── tesseract.txt │ ├── octet.txt │ ├── face_center.txt │ ├── x_cross_grid.txt │ ├── grid_octet.txt │ └── vintiles.txt ├── transform.m ├── hexahedronY.m ├── visual.m ├── GenerateVoxel.m └── homo3DY.m ├── README.md ├── CITATION.cff ├── LICENSE └── .gitignore /BESO3D/test.m: -------------------------------------------------------------------------------- 1 | clear; 2 | close all; 3 | clc; 4 | SBESO3D(30,30,4,0.3,3,1.5,0.02); -------------------------------------------------------------------------------- /UCOpt2D/test.m: -------------------------------------------------------------------------------- 1 | clc; clear; close all; 2 | 3 | UCOpt(10,10,100,30,20,20,0.3,3,1.5,1); -------------------------------------------------------------------------------- /Level set 88/test.m: -------------------------------------------------------------------------------- 1 | clear; 2 | close all; 3 | clc; 4 | tic 5 | levelset88(40,20,0.3,3,2,2) 6 | toc -------------------------------------------------------------------------------- /BESO88/tests.m: -------------------------------------------------------------------------------- 1 | clear; 2 | close all; 3 | clc; 4 | tic 5 | SBESO88(10,5,120,40,0.5,3.0,2,0.02) 6 | toc -------------------------------------------------------------------------------- /Level set 3D/tests.m: -------------------------------------------------------------------------------- 1 | clear; 2 | close all; 3 | clc; 4 | tic 5 | levelset3D(30,20,5,0.3,3,5,2) 6 | toc -------------------------------------------------------------------------------- /UCOpt3D/test.m: -------------------------------------------------------------------------------- 1 | clc; clear; close all; 2 | 3 | UCOpt3D(10,10,10,120,20,20,20,20,20,0.4,3,1.5,1); 4 | -------------------------------------------------------------------------------- /SIMP_3D MMA/test.m: -------------------------------------------------------------------------------- 1 | clear; 2 | close all; 3 | clc; 4 | type = ["Fixed" "Svanberg" "Liu&Tovar" "Christensen&Klarbring"]; 5 | top3dmma(60,20,4,0.3,3,1.5,type(1)); -------------------------------------------------------------------------------- /2D Homogenization Young/test.m: -------------------------------------------------------------------------------- 1 | %% Test for homogenization 2 | clc; clear; 3 | x = randi([1 2],10); 4 | E = 1 * (x==1) + 0.0001 * (x==2); 5 | homogenizeY(1,1,E,0.2,90); -------------------------------------------------------------------------------- /SIMP_88 MMA/tests.m: -------------------------------------------------------------------------------- 1 | clear; 2 | close all; 3 | clc; 4 | type = ["Fixed" "Svanberg" "Liu&Tovar" "Christensen&Klarbring"]; 5 | tic 6 | top88MMA(120,40,0.4,3.0,2,2,type(1)) 7 | toc -------------------------------------------------------------------------------- /UCOpt2D/README.md: -------------------------------------------------------------------------------- 1 | # UCOpt2D 2 | 3 | Code implementation for the optimal design of materials is 2D based on [1]. 4 | 5 | 6 | [1] G. Kazakis, N.D. Lagaros. A Simple Matlab Code for Material Design Optimization Using Reduced Order Models, _materials_, 2022. 7 | -------------------------------------------------------------------------------- /UCOpt3D/README.md: -------------------------------------------------------------------------------- 1 | # UCOpt3D 2 | 3 | Code implementation for the optimal design of materials is 3D based on [1]. 4 | 5 | 6 | [1] G. Kazakis, N.D. Lagaros. Topology optimization based material design for 3D domains using MATLAB, _Applied Sciences_, 2022. 7 | -------------------------------------------------------------------------------- /3D Homogenization Young/test.m: -------------------------------------------------------------------------------- 1 | clc; clear; close all; 2 | 3 | lx = 1; ly = lx; lz = lx; 4 | E = 1; 5 | nu = 0.2; 6 | 7 | [voxel,Density] = GenerateVoxel(40,'topology/x.txt',0.1); 8 | 9 | E = E*(voxel==1); 10 | CH = homo3DY(lx,ly,lz,E,nu,10e-3); 11 | visual(CH); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TopOpt 2 | Simple easy-to-use Topology Optimization based scripts for a variety of applications 3 | 4 | ### Contents: 5 | - SIMP 88 MMA 6 | - SIMP 3D MMA 7 | - BESO 88 8 | - BESO 3D 9 | - LEVEL SET 88 10 | - LEVEL SET 3D 11 | - HOMOGENIZATION 2D YOUNG 12 | - HOMOGENIZATION 3D YOUNG 13 | - UCOpt2D 14 | - UCOpt3D 15 | -------------------------------------------------------------------------------- /2D Homogenization Young/README.md: -------------------------------------------------------------------------------- 1 | # homogenizeY 2 | 3 | Implementation of the homogenize Matlab code [1] with small changes to compute the homogenized elasticity matrix from the young modulus and Poisson's ratio. 4 | 5 | 6 | [1] E. Andreassen, C.S. Andreasen. How to determine composite material properties using numerical homogenization, _structural multidisciplinary optimization_, 2014. 7 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | title: Topology Optimization scripts 3 | message: >- 4 | If you use this repository, please cite it using the 5 | metadata from this file. 6 | type: software 7 | authors: 8 | - given-names: George 9 | email: kzkgeorge@gmail.com 10 | family-names: Kazakis 11 | affiliation: NTUA 12 | url: https://github.com/GeorgeKazakis/TopOpt 13 | -------------------------------------------------------------------------------- /3D Homogenization Young/README.md: -------------------------------------------------------------------------------- 1 | # homo3DY 2 | 3 | Implementation of the homogenize Matlab code [2] with small changes to compute the homogenized elasticity tensor from the young modulus and Poisson's ratio. 4 | 5 | [1] G. Dong, Y. Tang, Y.F. Zhao, A 149 Line Homogenization Code for Three-Dimensional Celluler Materials Written in Matlab, _Journal of Engineering Materials and Technology_, 2018. 6 | -------------------------------------------------------------------------------- /Level set 3D/README.md: -------------------------------------------------------------------------------- 1 | # levelset3D 2 | 3 | Implementation of the Top3D Matlab code [1] with small changes to run the level set approach based on the top_levelset Matlab code [2]. 4 | 5 | [1] K. Liu, A. Tovar. An efficient 3D topology optimization code written in Matlab, _structural multidisciplinary optimization_, 2014. 6 | 7 | [2] V. Challis. A discrete level-set topology optimization code written in Matlab, _structural multidisciplinary optimization_, 2010. 8 | -------------------------------------------------------------------------------- /BESO3D/README.md: -------------------------------------------------------------------------------- 1 | # SBESO3D 2 | 3 | Implementation of the Top3D Matlab code [1] with small changes to run the BESO approach based on the SBESO Matlab code [2]. SBESO3D function is a modified top3D function with all the needed SBESO changes to run the BESO topology optimization approach. 4 | 5 | [1] K. Liu, A. Tovar. An efficient 3D topology optimization code written in Matlab, _structural multidisciplinary optimization_, 2014. 6 | 7 | [2] X. Huang, Y. Xie. A further review of ESO type methods for topology optimization, _structural multidisciplinary optimization_, 2010. 8 | -------------------------------------------------------------------------------- /BESO88/README.md: -------------------------------------------------------------------------------- 1 | # SBESO88 2 | 3 | Implementation of the Top88 Matlab code [1] with small changes to run the BESO approach based on the SBESO Matlab code [2]. SBESO88 function is a modified top88 function with all the needed SBESO changes to run the BESO topology optimization approach. 4 | 5 | [1] E. Andreassen, A. clausen, M. Schevenels, B.S. Lazarov, O. Sigmund. Efficient topology optimization in MATLAB using 88 lines of code, _structural multidisciplinary optimization_, 2011. 6 | 7 | [2] X. Huang, Y. Xie. A further review of ESO type methods for topology optimization, _structural multidisciplinary optimization_, 2010. 8 | -------------------------------------------------------------------------------- /Level set 88/README.md: -------------------------------------------------------------------------------- 1 | # levelset88 2 | 3 | Implementation of the Top88 Matlab code [1] with small changes to run the level set approach based on the top_levelset Matlab code [2]. levelset88 function is a modified top88 function with all the needed top_levelset changes to run the level set topology optimization approach. 4 | 5 | [1] E. Andreassen, A. clausen, M. Schevenels, B.S. Lazarov, O. Sigmund. Efficient topology optimization in MATLAB using 88 lines of code, _structural multidisciplinary optimization_, 2011. 6 | 7 | [2] V. Challis. A discrete level-set topology optimization code written in Matlab, _structural multidisciplinary optimization_, 2010. 8 | -------------------------------------------------------------------------------- /UCOpt2D/elementMatVec.m: -------------------------------------------------------------------------------- 1 | function [ke, fe] = elementMatVec(a, b, phi, nu) 2 | %elementMatVec COMPUTE ELEMENT STIFFNESS MATRIX AND FORCE VECTOR (NUMERICALLY) 3 | % Compute element stiffness matrix numerically and break it into to parts 4 | % concerning the young modulus and poisson ratio 5 | % input 6 | % a: x size of element / 2 (dx/2) 7 | % b: y size of element / 2 (dy/2) 8 | % phi: elements angle (usually 90) 9 | % output 10 | % ke: ke connected with young modulus 11 | % fe: fe connected with young modulus 12 | A = [1 nu 0; nu 1 0; 0 0 (1-nu)/2]; 13 | C = 1/(1-nu^2)*A; 14 | [ke,fe] = Q4elementStiffnessMatrix(a, b, phi, C); 15 | end -------------------------------------------------------------------------------- /3D Homogenization Young/topology/x.txt: -------------------------------------------------------------------------------- 1 | //Grid ID x y z 2 | GRID 1 0 0 0 3 | GRID 2 0.5 0.5 0.5 4 | GRID 3 1 1 1 5 | GRID 4 1 0 0 6 | GRID 5 0 1 1 7 | GRID 6 0 1 0 8 | GRID 7 1 0 1 9 | GRID 8 1 1 0 10 | GRID 9 0 0 1 11 | //Strut ID Start End 12 | STRUT 1 1 2 13 | STRUT 2 2 3 14 | STRUT 3 4 2 15 | STRUT 4 2 5 16 | STRUT 5 6 2 17 | STRUT 6 2 7 18 | STRUT 7 8 2 19 | STRUT 8 2 9 20 | -------------------------------------------------------------------------------- /3D Homogenization Young/topology/grid.txt: -------------------------------------------------------------------------------- 1 | //Grid ID x y z 2 | GRID 1 0 0 0 3 | GRID 2 1 0 0 4 | GRID 3 0 1 0 5 | GRID 4 0 0 1 6 | GRID 5 1 0 1 7 | GRID 6 0 1 1 8 | GRID 7 1 1 0 9 | GRID 8 1 1 1 10 | //Strut ID Start End 11 | STRUT 1 1 2 12 | STRUT 2 1 3 13 | STRUT 3 1 4 14 | STRUT 4 4 5 15 | STRUT 5 4 6 16 | STRUT 6 3 7 17 | STRUT 7 3 6 18 | STRUT 8 6 8 19 | STRUT 9 2 7 20 | STRUT 10 2 5 21 | STRUT 11 5 8 22 | STRUT 12 7 8 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 George Kazakis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /3D Homogenization Young/topology/Star.txt: -------------------------------------------------------------------------------- 1 | //Grid ID x y z 2 | GRID 1 0 0 0 3 | GRID 2 1 0 0 4 | GRID 3 0 1 0 5 | GRID 4 0 0 1 6 | GRID 5 0.5 0.5 0.5 7 | GRID 6 1 1 1 8 | GRID 7 0 1 1 9 | GRID 8 1 0 1 10 | GRID 9 1 1 0 11 | //Strut ID Start End 12 | STRUT 1 1 2 13 | STRUT 2 1 3 14 | STRUT 3 1 4 15 | STRUT 4 1 5 16 | STRUT 5 5 6 17 | STRUT 6 2 5 18 | STRUT 7 5 7 19 | STRUT 8 3 5 20 | STRUT 9 5 8 21 | STRUT 10 9 5 22 | STRUT 11 5 4 23 | STRUT 12 4 8 24 | STRUT 13 4 7 25 | STRUT 14 3 9 26 | STRUT 15 3 7 27 | STRUT 16 7 6 28 | STRUT 17 2 9 29 | STRUT 18 2 8 30 | STRUT 19 8 6 31 | STRUT 20 9 6 32 | -------------------------------------------------------------------------------- /SIMP_3D MMA/README.md: -------------------------------------------------------------------------------- 1 | # Top88 MMA 2 | 3 | Implementation of the Top3D Matlab code [1] with small changes to run a simplified version of the MMA method [2] for minimum compliance topology optimization. 4 | 5 | ### Simplified MMA 6 | 7 | Due to the derivative of the compliance always being negative (dc/dx < 0) the p term of the MMA function f(x) is always zero. Thus the MMA function f(x) can be simplified into the following expression: 8 | 9 | f(x) = r + Σ(q/(x-L) 10 | 11 | Using the simplified form of the MMA function the Lagrangian function is described using the following expression: 12 | 13 | L(x,λ) = f(x) + λ (Σx - volfrac) 14 | 15 | To compute the new set of material densities x the derivative of the Lagrangian function with respect to x must be set equal to zero following the expression: 16 | 17 | dL/dx = q/(x-L)^2 + λdv = 0 => x = sqrt(q/λdv) + L 18 | 19 | Thus the final expression for computing the new set of material densities x is following the expression: 20 | 21 | xnew = sqrt(q/λdv) + L 22 | 23 | Where L is one of the two moving asymptotes updated using the expressions defined in [2] and term q is taken from the MMA function definition: 24 | 25 | q = -(x-L)^2 dC/dx 26 | 27 | [1] K. Liu, A. Tovar. An efficient 3D topology optimization code written in Matlab, _structural multidisciplinary optimization_, 2014. 28 | 29 | [2] Kr. Svanberg. The method of moving asymptotes - a new method for structural optimization, _International Journal for numerical methods in Engineering_, 1987. 30 | -------------------------------------------------------------------------------- /SIMP_88 MMA/README.md: -------------------------------------------------------------------------------- 1 | # Top88 MMA 2 | 3 | Implementation of the Top88 Matlab code [1] with small changes to run a simplified version of the MMA method [2] for minimum compliance topology optimization. 4 | 5 | ### Simplified MMA 6 | 7 | Due to the derivative of the compliance always being negative (dc/dx < 0) the p term of the MMA function f(x) is always zero. Thus the MMA function f(x) can be simplified into the following expression: 8 | 9 | f(x) = r + Σ(q/(x-L) 10 | 11 | Using the simplified form of the MMA function the Lagrangian function is described using the following expression: 12 | 13 | L(x,λ) = f(x) + λ (Σx - volfrac) 14 | 15 | To compute the new set of material densities x the derivative of the Lagrangian function with respect to x must be set equal to zero following the expression: 16 | 17 | dL/dx = q/(x-L)^2 + λdv = 0 => x = sqrt(q/λdv) + L 18 | 19 | Thus the final expression for computing the new set of material densities x is following the expression: 20 | 21 | xnew = sqrt(q/λdv) + L 22 | 23 | Where L is one of the two moving asymptotes updated using the expressions defined in [2] and term q is taken from the MMA function definition: 24 | 25 | q = -(x-L)^2 dC/dx 26 | 27 | [1] E. Andreassen, A. clausen, M. Schevenels, B.S. Lazarov, O. Sigmund. Efficient topology optimization in MATLAB using 88 lines of code, _structural multidisciplinary optimization_, 2011. 28 | 29 | [2] Kr. Svanberg. The method of moving asymptotes - a new method for structural optimization, _International Journal for numerical methods in Engineering_, 1987. 30 | -------------------------------------------------------------------------------- /UCOpt2D/Q4elementStiffnessMatrix.m: -------------------------------------------------------------------------------- 1 | function [KE,FE] = Q4elementStiffnessMatrix(a, b, phi, C) 2 | %elementMatVec COMPUTE ELEMENT STIFFNESS MATRIX AND FORCE VECTOR (NUMERICALLY) 3 | % Compute element stiffness matrix numerically and break it into to parts 4 | % concerning the young modulus and poisson ratio 5 | % input 6 | % phi: elements angle (usually 90) 7 | % C: elasticity tensor 8 | % output 9 | % KE: element stiffness matrix 10 | 11 | % Two Gauss points in both directions 12 | xx = [-1/sqrt(3), 1/sqrt(3)]; yy = xx; 13 | ww = [1,1]; 14 | % Initialize 15 | KE = zeros(8,8); 16 | FE = zeros(8,3); 17 | L = zeros(3,4); L(1,1) = 1; L(2,4) = 1; L(3,2:3) = 1; 18 | for ii=1:length(xx) 19 | for jj=1:length(yy) 20 | % Integration point 21 | x = xx(ii); y = yy(jj); 22 | % Differentiated shape functions 23 | dNx = 1/4*[-(1-y) (1-y) (1+y) -(1+y)]; 24 | dNy = 1/4*[-(1-x) -(1+x) (1+x) (1-x)]; 25 | % Jacobian 26 | J = [dNx; dNy]*[-a a a+2*b/tan(phi*pi/180) 2*b/tan(phi*pi/180)-a;... 27 | -b -b b b]'; 28 | detJ = J(1,1)*J(2,2) - J(1,2)*J(2,1); 29 | ER = [J(2,2) -J(1,2); -J(2,1) J(1,1)]; 30 | invJ = 1/detJ*ER; 31 | % Weight factor at this point 32 | weight = ww(ii)*ww(jj)*detJ; 33 | % Strain-displacement matrix 34 | G = [invJ zeros(2); zeros(2) invJ]; 35 | dN = zeros(4,8); 36 | dN(1,1:2:8) = dNx; 37 | dN(2,1:2:8) = dNy; 38 | dN(3,2:2:8) = dNx; 39 | dN(4,2:2:8) = dNy; 40 | B = L*G*dN; 41 | % Element matrices 42 | KE = KE + weight*(B' * C * B); 43 | % Element Loads 44 | FE = FE + weight*(B' * C * diag([1 1 1])); 45 | end 46 | end 47 | end -------------------------------------------------------------------------------- /2D Homogenization Young/elementMatVec.m: -------------------------------------------------------------------------------- 1 | function [ke, fe] = elementMatVec(a, b, phi, nu) 2 | %elementMatVec COMPUTE ELEMENT STIFFNESS MATRIX AND FORCE VECTOR (NUMERICALLY) 3 | % Compute element stiffness matrix numerically and break it into to parts 4 | % concerning the young modulus and poisson ratio 5 | % input 6 | % a: x size of element / 2 (dx/2) 7 | % b: y size of element / 2 (dy/2) 8 | % phi: elements angle (usually 90) 9 | % output 10 | % ke: ke connected with young modulus 11 | % fe: fe connected with young modulus 12 | A = [1 nu 0; nu 1 0; 0 0 (1-nu)/2]; 13 | C = 1/(1-nu^2)*A; 14 | % Two Gauss points in both directions 15 | xx = [-1/sqrt(3), 1/sqrt(3)]; yy = xx; 16 | ww = [1,1]; 17 | % Initialize 18 | ke = zeros(8,8); 19 | fe = zeros(8,3); 20 | L = zeros(3,4); L(1,1) = 1; L(2,4) = 1; L(3,2:3) = 1; 21 | for ii=1:length(xx) 22 | for jj=1:length(yy) 23 | % Integration point 24 | x = xx(ii); y = yy(jj); 25 | % Differentiated shape functions 26 | dNx = 1/4*[-(1-y) (1-y) (1+y) -(1+y)]; 27 | dNy = 1/4*[-(1-x) -(1+x) (1+x) (1-x)]; 28 | % Jacobian 29 | J = [dNx; dNy]*[-a a a+2*b/tan(phi*pi/180) 2*b/tan(phi*pi/180)-a;... 30 | -b -b b b]'; 31 | detJ = J(1,1)*J(2,2) - J(1,2)*J(2,1); 32 | ER = [J(2,2) -J(1,2); -J(2,1) J(1,1)]; 33 | invJ = 1/detJ*ER; 34 | % Weight factor at this point 35 | weight = ww(ii)*ww(jj)*detJ; 36 | % Strain-displacement matrix 37 | G = [invJ zeros(2); zeros(2) invJ]; 38 | dN = zeros(4,8); 39 | dN(1,1:2:8) = dNx; 40 | dN(2,1:2:8) = dNy; 41 | dN(3,2:2:8) = dNx; 42 | dN(4,2:2:8) = dNy; 43 | B = L*G*dN; 44 | % Element matrices 45 | ke = ke + weight*(B' * C * B); 46 | % Element Loads 47 | fe = fe + weight*(B' * C * diag([1 1 1])); 48 | end 49 | end 50 | end -------------------------------------------------------------------------------- /3D Homogenization Young/topology/tesseract.txt: -------------------------------------------------------------------------------- 1 | //Grid ID x y z 2 | GRID 1 0 0 0 3 | GRID 2 1 0 0 4 | GRID 3 0.25 0.25 0.25 5 | GRID 4 0.75 0.25 0.25 6 | GRID 5 0 1 0 7 | GRID 6 0.25 0.75 0.25 8 | GRID 7 0 0 1 9 | GRID 8 0.25 0.25 0.75 10 | GRID 9 0.75 0.75 0.25 11 | GRID 10 0.75 0.75 0.75 12 | GRID 11 0.75 0.25 0.75 13 | GRID 12 0.25 0.75 0.75 14 | GRID 13 1 1 0 15 | GRID 14 1 0 1 16 | GRID 15 1 1 1 17 | GRID 16 0 1 1 18 | //Strut ID Start End 19 | STRUT 1 1 2 20 | STRUT 2 3 4 21 | STRUT 3 1 5 22 | STRUT 4 3 6 23 | STRUT 5 1 7 24 | STRUT 6 3 8 25 | STRUT 7 9 4 26 | STRUT 8 9 6 27 | STRUT 9 9 10 28 | STRUT 10 11 4 29 | STRUT 11 11 8 30 | STRUT 12 11 10 31 | STRUT 13 12 6 32 | STRUT 14 12 8 33 | STRUT 15 12 10 34 | STRUT 16 1 3 35 | STRUT 17 2 4 36 | STRUT 18 13 9 37 | STRUT 19 5 6 38 | STRUT 20 7 8 39 | STRUT 21 14 11 40 | STRUT 22 15 10 41 | STRUT 23 16 12 42 | STRUT 24 7 14 43 | STRUT 25 7 16 44 | STRUT 26 5 13 45 | STRUT 27 5 16 46 | STRUT 28 16 15 47 | STRUT 29 2 13 48 | STRUT 30 2 14 49 | STRUT 31 14 15 50 | STRUT 32 13 15 51 | -------------------------------------------------------------------------------- /3D Homogenization Young/topology/octet.txt: -------------------------------------------------------------------------------- 1 | //Grid ID x y z 2 | GRID 1 0.5 0.5 0 3 | GRID 2 0 0 0 4 | GRID 3 1 0 0 5 | GRID 4 1 1 0 6 | GRID 5 0 1 0 7 | GRID 6 1 0.5 0.5 8 | GRID 7 0.5 1 0.5 9 | GRID 8 0 0.5 0.5 10 | GRID 9 0.5 0 0.5 11 | GRID 10 0.5 0.5 1 12 | GRID 11 0 0 1 13 | GRID 12 0 1 1 14 | GRID 13 1 0 1 15 | GRID 14 1 1 1 16 | //Strut ID Start End 17 | STRUT 1 1 2 18 | STRUT 2 1 3 19 | STRUT 3 1 4 20 | STRUT 4 1 5 21 | STRUT 5 1 6 22 | STRUT 6 1 7 23 | STRUT 7 1 8 24 | STRUT 8 1 9 25 | STRUT 9 10 6 26 | STRUT 10 10 7 27 | STRUT 11 10 8 28 | STRUT 12 10 9 29 | STRUT 13 8 2 30 | STRUT 14 8 5 31 | STRUT 15 8 11 32 | STRUT 16 8 12 33 | STRUT 17 7 6 34 | STRUT 18 7 8 35 | STRUT 19 9 2 36 | STRUT 20 9 3 37 | STRUT 21 9 11 38 | STRUT 22 9 13 39 | STRUT 23 9 6 40 | STRUT 24 9 8 41 | STRUT 25 10 11 42 | STRUT 26 10 13 43 | STRUT 27 10 14 44 | STRUT 28 10 12 45 | STRUT 29 7 5 46 | STRUT 30 7 4 47 | STRUT 31 7 12 48 | STRUT 32 7 14 49 | STRUT 33 6 3 50 | STRUT 34 6 4 51 | STRUT 35 6 13 52 | STRUT 36 6 14 53 | -------------------------------------------------------------------------------- /3D Homogenization Young/topology/face_center.txt: -------------------------------------------------------------------------------- 1 | //Grid ID x y z 2 | GRID 1 0 0 0 3 | GRID 2 0.5 0 0.5 4 | GRID 3 1 0 1 5 | GRID 4 1 0 0 6 | GRID 5 0 0 1 7 | GRID 6 0 0.5 0.5 8 | GRID 7 0 1 1 9 | GRID 8 0 1 0 10 | GRID 9 0.5 0.5 0 11 | GRID 10 1 1 0 12 | GRID 11 0.5 0.5 1 13 | GRID 12 1 1 1 14 | GRID 13 0.5 1 0.5 15 | GRID 14 1 0.5 0.5 16 | //Strut ID Start End 17 | STRUT 1 1 2 18 | STRUT 2 2 3 19 | STRUT 3 4 2 20 | STRUT 4 2 5 21 | STRUT 5 1 6 22 | STRUT 6 6 7 23 | STRUT 7 8 6 24 | STRUT 8 6 5 25 | STRUT 9 1 9 26 | STRUT 10 9 10 27 | STRUT 11 4 9 28 | STRUT 12 9 8 29 | STRUT 13 5 11 30 | STRUT 14 11 12 31 | STRUT 15 3 11 32 | STRUT 16 11 7 33 | STRUT 17 8 13 34 | STRUT 18 13 12 35 | STRUT 19 10 13 36 | STRUT 20 13 7 37 | STRUT 21 4 14 38 | STRUT 22 14 12 39 | STRUT 23 10 14 40 | STRUT 24 14 3 41 | STRUT 25 1 4 42 | STRUT 26 1 8 43 | STRUT 27 1 5 44 | STRUT 28 5 3 45 | STRUT 29 5 7 46 | STRUT 30 8 10 47 | STRUT 31 8 7 48 | STRUT 32 7 12 49 | STRUT 33 4 10 50 | STRUT 34 4 3 51 | STRUT 35 3 12 52 | STRUT 36 10 12 53 | -------------------------------------------------------------------------------- /3D Homogenization Young/topology/x_cross_grid.txt: -------------------------------------------------------------------------------- 1 | //Grid ID x y z 2 | GRID 1 0 0 0 3 | GRID 2 0.5 0 0.5 4 | GRID 3 1 0 1 5 | GRID 4 1 0 0 6 | GRID 5 0 0 1 7 | GRID 6 0 0.5 0.5 8 | GRID 7 0 1 1 9 | GRID 8 0 1 0 10 | GRID 9 0.5 0.5 0 11 | GRID 10 1 1 0 12 | GRID 11 0.5 0.5 1 13 | GRID 12 1 1 1 14 | GRID 13 0.5 1 0.5 15 | GRID 14 1 0.5 0.5 16 | GRID 15 0.5 0.5 0.5 17 | //Strut ID Start End 18 | STRUT 1 1 2 19 | STRUT 2 2 3 20 | STRUT 3 4 2 21 | STRUT 4 2 5 22 | STRUT 5 1 6 23 | STRUT 6 6 7 24 | STRUT 7 8 6 25 | STRUT 8 6 5 26 | STRUT 9 1 9 27 | STRUT 10 9 10 28 | STRUT 11 4 9 29 | STRUT 12 9 8 30 | STRUT 13 5 11 31 | STRUT 14 11 12 32 | STRUT 15 3 11 33 | STRUT 16 11 7 34 | STRUT 17 8 13 35 | STRUT 18 13 12 36 | STRUT 19 10 13 37 | STRUT 20 13 7 38 | STRUT 21 4 14 39 | STRUT 22 14 12 40 | STRUT 23 10 14 41 | STRUT 24 14 3 42 | STRUT 25 1 4 43 | STRUT 26 1 8 44 | STRUT 27 1 5 45 | STRUT 28 5 3 46 | STRUT 29 5 7 47 | STRUT 30 8 10 48 | STRUT 31 8 7 49 | STRUT 32 7 12 50 | STRUT 33 4 10 51 | STRUT 34 4 3 52 | STRUT 35 3 12 53 | STRUT 36 10 12 54 | STRUT 37 1 15 55 | STRUT 38 15 12 56 | STRUT 39 4 15 57 | STRUT 40 15 7 58 | STRUT 41 8 15 59 | STRUT 42 15 3 60 | STRUT 43 10 15 61 | STRUT 44 15 5 62 | -------------------------------------------------------------------------------- /3D Homogenization Young/transform.m: -------------------------------------------------------------------------------- 1 | function otr = transform(itr,tmx) 2 | 3 | % 4 | % FUNCTION 5 | % otr = transform(itr,tmx) 6 | % 7 | % DESCRIPTION 8 | % transform 3D-tensor (Euclidean or Cartesion tensor) of any order (>0) to another coordinate system 9 | % 10 | % PARAMETERS 11 | % otr = output tensor, after transformation; has the same dimensions as the input tensor 12 | % itr = input tensor, before transformation; should be a 3-element vector, a 3x3 matrix, or a 3x3x3x... multidimensional array, each dimension containing 3 elements 13 | % tmx = transformation matrix, 3x3 matrix that contains the direction cosines between the old and the new coordinate system 14 | % 15 | 16 | ne = numel(itr); % number of tensor elements 17 | nd = ndims(itr); % number of tensor dimensions, i.e. order of tensor 18 | if (ne==3), nd = 1; end % order of tensor is 1 in case of a 3x1 or 1x3 vector 19 | 20 | otr = itr; % create output tensor 21 | otr(:) = 0; % fill output tensor with zeros; this way a symbolic tensor remains symbolic 22 | 23 | iie = zeros(nd,1); % initialise vector with indices of input tensor element 24 | ioe = zeros(nd,1); % initialise vector with indices of output tensor element 25 | cne = cumprod(3*ones(nd,1))/3; % vector with cumulative number of elements for each dimension (divided by three) 26 | 27 | for oe = 1:ne, % loop over all output elements 28 | ioe = mod(floor((oe-1)./cne),3)+1; % calculate indices of current output tensor element 29 | for ie = 1:ne, % loop over all input elements 30 | pmx = 1; % initialise product of transformation matrices 31 | iie = mod(floor((ie-1)./cne),3)+1; % calculate indices of current input tensor element 32 | for id = 1:nd, % loop over all dimensions 33 | pmx = pmx * tmx( ioe(id), iie(id) ); % create product of transformation matrices 34 | end 35 | otr(oe) = otr(oe) + pmx * itr(ie); % add product of transformation matrices and input tensor element to output tensor element 36 | end 37 | end 38 | 39 | % Transform matrix about Z axis 40 | % for x = 0:pi/20:pi/2 41 | % trans = [cos(x) cos(x-pi/2) 0; 42 | % cos(x+pi/2) cos(x) 0; 43 | % 0 0 1]; 44 | % N_CH = transform(C,trans); 45 | % end -------------------------------------------------------------------------------- /3D Homogenization Young/topology/grid_octet.txt: -------------------------------------------------------------------------------- 1 | //Grid ID x y z 2 | GRID 1 0.5 0.5 0 3 | GRID 2 0 0 0 4 | GRID 3 1 0 0 5 | GRID 4 1 1 0 6 | GRID 5 0 1 0 7 | GRID 6 1 0.5 0.5 8 | GRID 7 0.5 1 0.5 9 | GRID 8 0 0.5 0.5 10 | GRID 9 0.5 0 0.5 11 | GRID 10 0.5 0.5 1 12 | GRID 11 0 0 1 13 | GRID 12 0 1 1 14 | GRID 13 1 0 1 15 | GRID 14 1 1 1 16 | //Strut ID Start End 17 | STRUT 1 1 2 18 | STRUT 2 1 3 19 | STRUT 3 1 4 20 | STRUT 4 1 5 21 | STRUT 5 1 6 22 | STRUT 6 1 7 23 | STRUT 7 1 8 24 | STRUT 8 1 9 25 | STRUT 9 10 6 26 | STRUT 10 10 7 27 | STRUT 11 10 8 28 | STRUT 12 10 9 29 | STRUT 13 8 2 30 | STRUT 14 8 5 31 | STRUT 15 8 11 32 | STRUT 16 8 12 33 | STRUT 17 7 6 34 | STRUT 18 7 8 35 | STRUT 19 9 2 36 | STRUT 20 9 3 37 | STRUT 21 9 11 38 | STRUT 22 9 13 39 | STRUT 23 9 6 40 | STRUT 24 9 8 41 | STRUT 25 10 11 42 | STRUT 26 10 13 43 | STRUT 27 10 14 44 | STRUT 28 10 12 45 | STRUT 29 7 5 46 | STRUT 30 7 4 47 | STRUT 31 7 12 48 | STRUT 32 7 14 49 | STRUT 33 6 3 50 | STRUT 34 6 4 51 | STRUT 35 6 13 52 | STRUT 36 6 14 53 | STRUT 37 2 3 54 | STRUT 38 2 5 55 | STRUT 39 2 11 56 | STRUT 40 11 13 57 | STRUT 41 11 12 58 | STRUT 42 5 4 59 | STRUT 43 5 12 60 | STRUT 44 12 14 61 | STRUT 45 3 4 62 | STRUT 46 3 13 63 | STRUT 47 13 14 64 | STRUT 48 4 14 65 | -------------------------------------------------------------------------------- /3D Homogenization Young/hexahedronY.m: -------------------------------------------------------------------------------- 1 | %% COMPUTE ELEMENT STIFFNESS MATRIX AND LOAD VECTOR 2 | function [ke, fe] = hexahedronY(a, b, c, nu) 3 | % Constitutive matrix contributions 4 | E = 1; 5 | C = E/((1+nu)*(1-2*nu))*[1-nu nu nu 0 0 0; nu 1-nu nu 0 0 0;... 6 | nu nu 1-nu 0 0 0; 0 0 0 (1-2*nu)/2 0 0; 0 0 0 0 (1-2*nu)/2 0;... 7 | 0 0 0 0 0 (1-2*nu)/2]; 8 | % Three Gauss points in both directions 9 | % xx = [-1/sqrt(3), 1/sqrt(3)]; 10 | xx = [-sqrt(3/5), 0, sqrt(3/5)]; 11 | yy = xx; zz = xx; 12 | ww = [5/9, 8/9, 5/9]; 13 | % Initialize 14 | ke = zeros(24,24); 15 | fe = zeros(24,6); 16 | for ii = 1:length(xx) 17 | for jj = 1:length(yy) 18 | for kk = 1:length(zz) 19 | %integration point 20 | x = xx(ii); y = yy(jj); z = zz(kk); 21 | %stress strain displacement matrix 22 | qx = [ -((y-1)*(z-1))/8, ((y-1)*(z-1))/8, -((y+1)*(z-1))/8,... 23 | ((y+1)*(z-1))/8, ((y-1)*(z+1))/8, -((y-1)*(z+1))/8,... 24 | ((y+1)*(z+1))/8, -((y+1)*(z+1))/8]; 25 | qy = [ -((x-1)*(z-1))/8, ((x+1)*(z-1))/8, -((x+1)*(z-1))/8,... 26 | ((x-1)*(z-1))/8, ((x-1)*(z+1))/8, -((x+1)*(z+1))/8,... 27 | ((x+1)*(z+1))/8, -((x-1)*(z+1))/8]; 28 | qz = [ -((x-1)*(y-1))/8, ((x+1)*(y-1))/8, -((x+1)*(y+1))/8,... 29 | ((x-1)*(y+1))/8, ((x-1)*(y-1))/8, -((x+1)*(y-1))/8,... 30 | ((x+1)*(y+1))/8, -((x-1)*(y+1))/8]; 31 | % Jacobian 32 | J = [qx; qy; qz]*[-a a a -a -a a a -a; -b -b b b -b -b b b;... 33 | -c -c -c -c c c c c]'; 34 | qxyz = J\[qx;qy;qz]; 35 | B_e = zeros(6,3,8); 36 | for i_B = 1:8 37 | B_e(:,:,i_B) = [qxyz(1,i_B) 0 0; 38 | 0 qxyz(2,i_B) 0; 39 | 0 0 qxyz(3,i_B); 40 | qxyz(2,i_B) qxyz(1,i_B) 0; 41 | 0 qxyz(3,i_B) qxyz(2,i_B); 42 | qxyz(3,i_B) 0 qxyz(1,i_B)]; 43 | end 44 | B = [B_e(:,:,1) B_e(:,:,2) B_e(:,:,3) B_e(:,:,4) B_e(:,:,5)... 45 | B_e(:,:,6) B_e(:,:,7) B_e(:,:,8)]; 46 | % Weight factor at this point 47 | weight = det(J)*ww(ii) * ww(jj) * ww(kk); 48 | % Element matrices 49 | ke = ke + weight * B' * C * B; 50 | % Element loads 51 | fe = fe + weight * B' * C; 52 | end 53 | end 54 | end 55 | end -------------------------------------------------------------------------------- /3D Homogenization Young/topology/vintiles.txt: -------------------------------------------------------------------------------- 1 | //Grid ID x y z 2 | GRID 1 0 0.5 0.25 3 | GRID 2 0 0.25 0 4 | GRID 3 0 0.75 0 5 | GRID 4 0.25 0.5 0.5 6 | GRID 5 0.5 1 0.25 7 | GRID 6 0.5 0.75 0.5 8 | GRID 7 1 0.5 0.25 9 | GRID 8 0.75 0.5 0.5 10 | GRID 9 0.5 0 0.25 11 | GRID 10 0.75 0 0 12 | GRID 11 0.25 0 0 13 | GRID 12 0.5 0.25 0.5 14 | GRID 13 0 0.5 0.75 15 | GRID 14 0 0.25 1 16 | GRID 15 0 0.75 1 17 | GRID 16 0.5 1 0.75 18 | GRID 17 1 0.5 0.75 19 | GRID 18 0.5 0 0.75 20 | GRID 19 0.75 0 1 21 | GRID 20 0.25 0 1 22 | GRID 21 0.25 1 0 23 | GRID 22 0.75 1 0 24 | GRID 23 1 0.75 0 25 | GRID 24 1 0.25 0 26 | GRID 25 0.25 1 1 27 | GRID 26 0.75 1 1 28 | GRID 27 1 0.75 1 29 | GRID 28 1 0.25 1 30 | //Strut ID Start End 31 | STRUT 1 1 2 32 | STRUT 2 1 3 33 | STRUT 3 1 4 34 | STRUT 4 5 6 35 | STRUT 5 7 8 36 | STRUT 6 9 10 37 | STRUT 7 9 11 38 | STRUT 8 9 12 39 | STRUT 9 13 14 40 | STRUT 10 13 15 41 | STRUT 11 13 4 42 | STRUT 12 16 6 43 | STRUT 13 17 8 44 | STRUT 14 18 19 45 | STRUT 15 18 20 46 | STRUT 16 18 12 47 | STRUT 17 3 21 48 | STRUT 18 22 23 49 | STRUT 19 24 10 50 | STRUT 20 4 12 51 | STRUT 21 8 12 52 | STRUT 22 4 6 53 | STRUT 23 8 6 54 | STRUT 24 2 11 55 | STRUT 25 15 25 56 | STRUT 26 26 27 57 | STRUT 27 28 19 58 | STRUT 28 14 20 59 | STRUT 29 5 22 60 | STRUT 30 5 21 61 | STRUT 31 16 26 62 | STRUT 32 16 25 63 | STRUT 33 7 24 64 | STRUT 34 7 23 65 | STRUT 35 17 28 66 | STRUT 36 17 27 67 | -------------------------------------------------------------------------------- /3D Homogenization Young/visual.m: -------------------------------------------------------------------------------- 1 | % input the homogenized elasticity tensor 2 | function [s] = visual(CH) 3 | % transform it to 3*3*3*3 tensor 4 | tensor = generate(CH); 5 | % find the E1 in 360 degree 6 | % x = 0:pi/180:2*pi; 7 | [a,e] = meshgrid(0:0.02*pi:2*pi, -pi/2:0.01*pi:pi/2); 8 | E1 = zeros(size(a)); 9 | for i = 1:size(a,1) 10 | for j = 1:size(a,2) 11 | % build the transformation matrix 12 | trans_z = [cos(a(i,j)) -sin(a(i,j)) 0; 13 | sin(a(i,j)) cos(a(i,j)) 0; 14 | 0 0 1]; 15 | trans_y = [cos(e(i,j)) 0 sin(e(i,j)); 16 | 0 1 0; 17 | -sin(e(i,j)) 0 cos(e(i,j))]; 18 | % calculate the new tensor 19 | N_tensor = transform(tensor,trans_y*trans_z); 20 | % transform the tensor to 6*6 21 | N_CH = ToMatrix(N_tensor); 22 | % calculate the E1 23 | E = modulus(N_CH); 24 | E1(i,j) = E(1); 25 | end 26 | end 27 | [x,y,z] = sph2cart(a,e,E1); 28 | c = sqrt(x.^2+y.^2+z.^2); 29 | s = surf(x,y,z,c); 30 | s.EdgeColor = 'none'; 31 | s.FaceColor = 'interp'; 32 | display(s) 33 | end 34 | 35 | function [E] = modulus(CH) 36 | S = inv(CH); 37 | E = zeros(6,1); 38 | E(1) = 1/S(1,1); 39 | E(2) = 1/S(2,2); 40 | E(3) = 1/S(3,3); 41 | E(4) = 1/S(4,4); 42 | E(5) = 1/S(5,5); 43 | E(6) = 1/S(6,6); 44 | end 45 | 46 | function C = generate(CH) 47 | C = zeros(3,3,3,3); 48 | for i = 1:6 49 | for j = 1:6 50 | [a,b] = change(i); 51 | [c,d] = change(j); 52 | C(a,b,c,d) = CH(i,j); 53 | end 54 | end 55 | for i = 1:3 56 | if (i == 3) 57 | j = 1; 58 | else 59 | j = i+1; 60 | end 61 | for m = 1:3 62 | if (m == 3) 63 | n = 1; 64 | else 65 | n = m+1; 66 | end 67 | C(j,i,n,m) = C(i,j,m,n); 68 | C(j,i,m,n) = C(i,j,m,n); 69 | C(i,j,n,m) = C(i,j,m,n); 70 | C(j,i,m,m) = C(i,j,m,m); 71 | C(m,m,j,i) = C(m,m,i,j); 72 | end 73 | end 74 | end 75 | 76 | % change the index 4 5 6 to 23 31 12 77 | function [a,b] = change(w) 78 | 79 | if (w < 4) 80 | a = w; 81 | b = w; 82 | else 83 | if (w == 4) 84 | a = 2; 85 | b = 3; 86 | else 87 | if (w == 5) 88 | a = 3; 89 | b = 1; 90 | else 91 | if (w==6) 92 | a = 1; 93 | b = 2; 94 | end 95 | end 96 | end 97 | end 98 | 99 | end 100 | 101 | function CH = ToMatrix(C) 102 | CH = zeros(6,6); 103 | for i = 1:6 104 | for j = 1:6 105 | [a,b] = change(i); 106 | [c,d] = change(j); 107 | CH(i,j) = C(a,b,c,d); 108 | end 109 | end 110 | end -------------------------------------------------------------------------------- /2D Homogenization Young/homogenizeY.m: -------------------------------------------------------------------------------- 1 | function CH = homogenizeY(lx, ly, E, nu, phi) 2 | %% INITIALIZE 3 | % Deduce discretization 4 | [nely, nelx] = size(E); 5 | dx = lx/nelx; dy = ly/nely; 6 | nel = nely*nelx; 7 | [ke, fe] = elementMatVec(dx/2, dy/2, phi, nu); 8 | % Node number and element degrees of freedom for full(not periodic) mesh 9 | nodenrs = reshape(1:(nelx+1)*(nely+1),1+nely,1+nelx); 10 | edofVec = reshape(2*nodenrs(1:end-1,1:end-1)+1,nel,1); 11 | edofMat = repmat(edofVec,1,8)+repmat([0 1 2*nely+[2 3 0 1] -2 -1],nel,1); 12 | %% IMPOSE PERIODIC BOUNDARY CONDITIONS 13 | % Use original edofMat to index into list with the periodic dofs 14 | nn = (nelx+1)*(nely+1); % Total number of nodes 15 | nnP = (nelx)*(nely); % total number of unique nodes 16 | nnPArray = reshape(1:nnP,nely ,nelx); 17 | % Extend with a mirror of the top border 18 | nnPArray(end+1,:) = nnPArray(1,:); 19 | % Extend with a mirror of the left border 20 | nnPArray(:,end+1) = nnPArray(:,1); 21 | % Make a vector into which we can index using edofMat: 22 | dofVector = zeros(2*nn,1); 23 | dofVector(1:2:end) = 2*nnPArray(:)-1; 24 | dofVector(2:2:end) = 2*nnPArray(:); 25 | edofMat = dofVector(edofMat); 26 | ndof = 2*nnP; % Number of dofs 27 | %% ASSEMBLE STIFFNESS MATRIX 28 | % Indexing vectors 29 | iK = kron(edofMat,ones(8,1))'; 30 | jK = kron(edofMat,ones(1,8))'; 31 | % The corresponding stiffness matrix entries 32 | sK = ke(:)*E(:).'; 33 | K = sparse(iK(:), jK(:), sK(:), ndof, ndof); 34 | %% LOAD VECTORS AND SOLUTION 35 | % Assembly three load cases corresponding to the three strain cases 36 | sF = fe(:)*E(:).'; 37 | iF = repmat(edofMat',3,1); 38 | jF = [ones(8,nel); 2*ones(8,nel); 3*ones(8,nel)]; 39 | F = sparse(iF(:), jF(:), sF(:), ndof, 3); 40 | % Solve (remember to constrain one node) 41 | % K = 0.5*(K+K.'); 42 | chi(3:ndof,:) = K(3:ndof,3:ndof)\F(3:ndof,:); % 1,2 dofs constrained 43 | %% HOMOGENIZATION 44 | % The displacement vector corresponding to the unit strain cases 45 | chi0 = zeros(nel, 8, 3); 46 | % The element displacements for the three unit strains 47 | chi0_e = zeros(8, 3); 48 | chi0_e([3 5:end],:) = ke([3 5:end],[3 5:end])\fe([3 5:end],:); 49 | % epsilon0_11 = (1, 0, 0) 50 | chi0(:,:,1) = kron(chi0_e(:,1)', ones(nel,1)); 51 | % epsilon0_22 = (0, 1, 0) 52 | chi0(:,:,2) = kron(chi0_e(:,2)', ones(nel,1)); 53 | % epsilon0_12 = (0, 0, 1) 54 | chi0(:,:,3) = kron(chi0_e(:,3)', ones(nel,1)); 55 | CH = zeros(3); 56 | DCH = cell(nely,nelx); 57 | DCH(:,:) = {zeros(3)}; 58 | cellVolume = lx*ly; 59 | for i =1:3 60 | for j = 1:3 61 | sumYoung = ((chi0(:,:,i) - chi(edofMat+(i-1)*ndof))*ke).*... 62 | (chi0(:,:,j) - chi(edofMat+(j-1)*ndof)); 63 | sumYoung = reshape(sum(sumYoung,2), nely, nelx); 64 | % Homogenized elasticity tensor 65 | CH(i,j) = 1/cellVolume*sum(sum(E.*sumYoung)); 66 | end 67 | end 68 | disp('--- Homogenized elasticity tensor ---'); disp(CH) 69 | end -------------------------------------------------------------------------------- /3D Homogenization Young/GenerateVoxel.m: -------------------------------------------------------------------------------- 1 | function [voxel,Density] = GenerateVoxel(n,address,radius) 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % n is the number of voxel along each axis 4 | % address is the file location of wireframe 5 | % density is the relative density 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | size = 1/n; % initial size of voxels 8 | voxel = zeros(n,n,n); % initial grid with zeros 9 | %% generate a list of centers of voxel 10 | voxel_c = zeros(n^3,6); 11 | p = 0; % p count the number of all voxels 12 | for i = 1:n % i for z axis 13 | for j = 1:n % j for y axis 14 | for k = 1:n % k for x axis 15 | p = p + 1; 16 | voxel_c(p,1:3) = [k,j,i]; % save index along x,y,z axis 17 | % save coordinate along x,y,z axis 18 | voxel_c(p,4:6) = [(k-0.5)*size,(j-0.5)*size,(i-0.5)*size]; 19 | end 20 | end 21 | end 22 | %% Get the voxel close the the strut witnin a certain distance 23 | [node,strut] = ReadStrut(address); % get the information of strut 24 | for i = 1:length(voxel_c) % for each voxel, deside if it is active 25 | % for each strut, get the distance to the voxel 26 | for j = 1:length(strut) 27 | start_n = node(strut(j,1),:); % start node coordinate 28 | end_n = node(strut(j,2),:); % end node coordinate 29 | center = voxel_c(i,4:6); % voxel center position 30 | % determine alpha and beta are acute angle 31 | alpha = acosd(((center - start_n)*(end_n - start_n)')... 32 | /(norm(center - start_n)*norm(end_n - start_n))); 33 | beta = acosd(((center - end_n)*(start_n - end_n)')... 34 | /(norm(center - end_n)*norm(start_n - end_n))); 35 | if(alpha<90 && beta<90)% if not acute angle, distance to line 36 | distance = norm(cross(end_n - start_n,center - start_n))... 37 | /norm(end_n - start_n); 38 | else % if it is acute angle, distance to node 39 | distance = min(norm(center - start_n),norm(center - end_n)); 40 | end 41 | if (distance<=radius) % if distance less than radius, active it 42 | voxel(voxel_c(i,1),voxel_c(i,2),voxel_c(i,3)) = 1; 43 | continue; % run for the next voxel 44 | end 45 | end 46 | end 47 | Density = sum(sum(sum(voxel)))/n^3;% calculate the relative density 48 | end 49 | %%Import information of strut 50 | function [nodelist,strutlist] = ReadStrut(address) 51 | fid = fopen(address,'r'); 52 | k = 1; 53 | j = 1; 54 | tline = fgetl(fid); 55 | while ischar(tline) 56 | if (tline(1) == 'G') 57 | x = str2double(tline(17:24)); 58 | y = str2double(tline(25:32)); 59 | z = str2double(tline(33:40)); 60 | nodelist(k,1:3) = [x,y,z]; 61 | k = k + 1; 62 | end 63 | if (tline(1) == 'S') 64 | Snode = str2double(tline(17:24)); 65 | Enode = str2double(tline(25:32)); 66 | strutlist(j,1:2) = [Snode,Enode]; 67 | j = j + 1; 68 | end 69 | tline = fgetl(fid); 70 | end 71 | fclose(fid); 72 | end 73 | 74 | -------------------------------------------------------------------------------- /UCOpt2D/homogenize.m: -------------------------------------------------------------------------------- 1 | function [CH,DCH] = homogenize(lx, ly, E, nu, dE, phi) 2 | %% INITIALIZE 3 | % Deduce discretization 4 | [nely, nelx] = size(E); 5 | dx = lx/nelx; dy = ly/nely; 6 | nel = nely*nelx; 7 | [ke, fe] = elementMatVec(dx/2, dy/2, phi, nu); 8 | % Node number and element degrees of freedom for full(not periodic) mesh 9 | nodenrs = reshape(1:(nelx+1)*(nely+1),1+nely,1+nelx); 10 | edofVec = reshape(2*nodenrs(1:end-1,1:end-1)+1,nel,1); 11 | edofMat = repmat(edofVec,1,8)+repmat([0 1 2*nely+[2 3 0 1] -2 -1],nel,1); 12 | %% IMPOSE PERIODIC BOUNDARY CONDITIONS 13 | % Use original edofMat to index into list with the periodic dofs 14 | nn = (nelx+1)*(nely+1); % Total number of nodes 15 | nnP = (nelx)*(nely); % total number of unique nodes 16 | nnPArray = reshape(1:nnP,nely ,nelx); 17 | % Extend with a mirror of the top border 18 | nnPArray(end+1,:) = nnPArray(1,:); 19 | % Extend with a mirror of the left border 20 | nnPArray(:,end+1) = nnPArray(:,1); 21 | % Make a vector into which we can index using edofMat: 22 | dofVector = zeros(2*nn,1); 23 | dofVector(1:2:end) = 2*nnPArray(:)-1; 24 | dofVector(2:2:end) = 2*nnPArray(:); 25 | edofMat = dofVector(edofMat); 26 | ndof = 2*nnP; % Number of dofs 27 | %% ASSEMBLE STIFFNESS MATRIX 28 | % Indexing vectors 29 | iK = kron(edofMat,ones(8,1))'; 30 | jK = kron(edofMat,ones(1,8))'; 31 | % The corresponding stiffness matrix entries 32 | sK = ke(:)*E(:).'; 33 | K = sparse(iK(:), jK(:), sK(:), ndof, ndof); 34 | %% LOAD VECTORS AND SOLUTION 35 | % Assembly three load cases corresponding to the three strain cases 36 | sF = fe(:)*E(:).'; 37 | iF = repmat(edofMat',3,1); 38 | jF = [ones(8,nel); 2*ones(8,nel); 3*ones(8,nel)]; 39 | F = sparse(iF(:), jF(:), sF(:), ndof, 3); 40 | % Solve (remember to constrain one node) 41 | % K = 0.5*(K+K.'); 42 | chi(3:ndof,:) = K(3:ndof,3:ndof)\F(3:ndof,:); % 1,2 dofs constrained 43 | %% HOMOGENIZATION 44 | % The displacement vector corresponding to the unit strain cases 45 | chi0 = zeros(nel, 8, 3); 46 | % The element displacements for the three unit strains 47 | chi0_e = zeros(8, 3); 48 | chi0_e([3 5:end],:) = ke([3 5:end],[3 5:end])\fe([3 5:end],:); 49 | % epsilon0_11 = (1, 0, 0) 50 | chi0(:,:,1) = kron(chi0_e(:,1)', ones(nel,1)); 51 | % epsilon0_22 = (0, 1, 0) 52 | chi0(:,:,2) = kron(chi0_e(:,2)', ones(nel,1)); 53 | % epsilon0_12 = (0, 0, 1) 54 | chi0(:,:,3) = kron(chi0_e(:,3)', ones(nel,1)); 55 | CH = zeros(3); 56 | DCH = cell(nely,nelx); 57 | DCH(:,:) = {zeros(3)}; 58 | cellVolume = lx*ly; 59 | for i =1:3 60 | for j = 1:3 61 | sumYoung = ((chi0(:,:,i) - chi(edofMat+(i-1)*ndof))*ke).*... 62 | (chi0(:,:,j) - chi(edofMat+(j-1)*ndof)); 63 | sumYoung = reshape(sum(sumYoung,2), nely, nelx); 64 | % Homogenized elasticity tensor 65 | CH(i,j) = 1/cellVolume*sum(sum(E.*sumYoung)); 66 | finalSum = dE.*sumYoung; 67 | for k=1:nely 68 | for l=1:nelx 69 | DCH{k,l}(i,j) = 1/cellVolume*finalSum(k,l); 70 | end 71 | end 72 | end 73 | end 74 | % disp('--- Homogenized elasticity tensor ---'); disp(CH) 75 | end -------------------------------------------------------------------------------- /BESO88/SBESO88.m: -------------------------------------------------------------------------------- 1 | %%%% AN 88 LINE TOPOLOGY OPTIMIZATION CODE Nov, 2010 %%%% 2 | function SBESO88(lx,ly,nelx,nely,volfrac,penal,rmin,er) 3 | %% MATERIAL PROPERTIES 4 | E0 = 1; 5 | Emin = 1e-9; 6 | nu = 0.3; 7 | dx = lx/nelx; 8 | dy = ly/nely; 9 | r = dx/dy; 10 | t = r^(-1); 11 | %% PREPARE FINITE ELEMENT ANALYSIS 12 | % A11 = [12 3 -6 -3; 3 12 3 0; -6 3 12 -3; -3 0 -3 12]; 13 | % A12 = [-6 -3 0 3; -3 -6 -3 -6; 0 -3 -6 3; 3 -6 3 -6]; 14 | % B11 = [-4 3 -2 9; 3 -4 -9 4; -2 -9 -4 -3; 9 4 -3 -4]; 15 | % B12 = [ 2 -3 4 -9; -3 2 9 -2; 4 9 2 3; -9 -2 3 2]; 16 | A11 = [8*t+4*r 3 -8*t+2*r -3; 3 8*r+4*t 3 4*r-4*t; -8*t+2*r 3 8*t+4*r -3; -3 4*r-4*t -3 8*r+4*t]; 17 | A12 = [-4*t-2*r -3 4*t-4*r 3; -3 -4*r-2*t -3 -8*r+2*t; 4*t-4*r -3 -4*t-2*r 3; 3 -8*r+2*t 3 -4*r-2*t]; 18 | B11 = [-4*r 3 -2*r 9; 3 -4*t -9 4*t; -2*r -9 -4*r -3; 9 4*t -3 -4*t]; 19 | B12 = [ 2*r -3 4*r -9; -3 2*t 9 -2*t; 4*r 9 2*r 3; -9 -2*t 3 2*t]; 20 | KE = 1/(1-nu^2)/24*([A11 A12;A12' A11]+nu*[B11 B12;B12' B11]); 21 | nodenrs = reshape(1:(1+nelx)*(1+nely),1+nely,1+nelx); 22 | edofVec = reshape(2*nodenrs(1:end-1,1:end-1)+1,nelx*nely,1); 23 | edofMat = repmat(edofVec,1,8)+repmat([0 1 2*nely+[2 3 0 1] -2 -1],nelx*nely,1); 24 | iK = reshape(kron(edofMat,ones(8,1))',64*nelx*nely,1); 25 | jK = reshape(kron(edofMat,ones(1,8))',64*nelx*nely,1); 26 | % DEFINE LOADS AND SUPPORTS (HALF MBB-BEAM) 27 | F = sparse(2*(nelx+1)*(nely+1),1,-1,2*(nely+1)*(nelx+1),1); 28 | U = zeros(2*(nely+1)*(nelx+1),1); 29 | fixeddofs = (1:1:2*(nely+1)); 30 | alldofs = (1:2*(nely+1)*(nelx+1)); 31 | freedofs = setdiff(alldofs,fixeddofs); 32 | %% PREPARE FILTER 33 | iH = ones(nelx*nely*(2*(ceil(rmin)-1)+1)^2,1); 34 | jH = ones(size(iH)); 35 | sH = zeros(size(iH)); 36 | k = 0; 37 | for i1 = 1:nelx 38 | for j1 = 1:nely 39 | e1 = (i1-1)*nely+j1; 40 | for i2 = max(i1-(ceil(rmin)-1),1):min(i1+(ceil(rmin)-1),nelx) 41 | for j2 = max(j1-(ceil(rmin)-1),1):min(j1+(ceil(rmin)-1),nely) 42 | e2 = (i2-1)*nely+j2; 43 | k = k+1; 44 | iH(k) = e1; 45 | jH(k) = e2; 46 | sH(k) = max(0,rmin-sqrt((i1-i2)^2+(j1-j2)^2)); 47 | end 48 | end 49 | end 50 | end 51 | H = sparse(iH,jH,sH); 52 | Hs = sum(H,2); 53 | %% INITIALIZE ITERATION 54 | x = ones(nely,nelx); 55 | vol = 1; 56 | % xPhys = x; 57 | loop = 0; 58 | change = 1; 59 | %% START ITERATION 60 | while change > 0.001 61 | loop = loop + 1; 62 | vol = max(vol*(1-er),volfrac); 63 | if loop > 1; olddc = dc; end 64 | %% FE-ANALYSIS 65 | sK = reshape(KE(:)*(Emin+x(:)'.^penal*(E0-Emin)),64*nelx*nely,1); 66 | K = sparse(iK,jK,sK); K = (K+K')/2; 67 | U(freedofs) = K(freedofs,freedofs)\F(freedofs); 68 | %% OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS 69 | ce = reshape(0.5*(sum((U(edofMat)*KE).*U(edofMat),2)),nely,nelx); 70 | c(loop) = sum(sum((Emin+x.^penal*(E0-Emin)).*ce)); 71 | dc = penal*(E0-Emin)*x.^(penal-1).*ce; 72 | %% FILTERING/MODIFICATION OF SENSITIVITIES 73 | dc(:) = H*(dc(:))./Hs; 74 | if loop > 1; dc = (dc+olddc)/2.; end 75 | %% OPTIMALITY CRITERIA UPDATE OF DESIGN VARIABLES AND PHYSICAL DENSITIES 76 | l1 = min(min(dc)); l2 = max(max(dc)); 77 | while (l2-l1)/(l1+l2) > 1e-3 78 | lmid = 0.5*(l2+l1); 79 | x = max(0.001,sign(dc-lmid)); 80 | % xnew = max(0,max(x-move,min(1,min(x+move,x.*sqrt(-dc./dv/lmid))))); 81 | if sum(x(:)) > vol*nelx*nely, l1 = lmid; else l2 = lmid; end 82 | end 83 | if loop > 10 84 | change = abs(sum(c(loop-9:loop-5))-sum(c(loop-4:loop)))/sum(c(loop-4:loop)); 85 | end 86 | %% PRINT RESULTS 87 | fprintf(' It.:%5i Obj.:%11.4f Vol.:%7.3f ch.:%7.3f\n',loop,c(loop),mean(x(:)),change); 88 | %% PLOT DENSITIES 89 | colormap(gray); imagesc(1-x); caxis([0 1]); axis equal; axis off; drawnow; 90 | end 91 | % 92 | -------------------------------------------------------------------------------- /UCOpt2D/UCOpt.m: -------------------------------------------------------------------------------- 1 | function c = UCOpt(lx,ly,nelx,nely,nlx,nly,volfrac,penal,rmin,ft) 2 | %% MATERIAL PROPERTIES 3 | E0 = 1; 4 | Emin = 1e-9; 5 | nu = 0.3; 6 | %% PREPARE FINITE ELEMENT ANALYSIS 7 | nodenrs = reshape(1:(1+nelx)*(1+nely),1+nely,1+nelx); 8 | edofVec = reshape(2*nodenrs(1:end-1,1:end-1)+1,nelx*nely,1); 9 | edofMat = repmat(edofVec,1,8)+repmat([0 1 2*nely+[2 3 0 1] -2 -1],nelx*nely,1); 10 | iK = reshape(kron(edofMat,ones(8,1))',64*nelx*nely,1); 11 | jK = reshape(kron(edofMat,ones(1,8))',64*nelx*nely,1); 12 | % DEFINE LOADS AND SUPPORTS (HALF MBB-BEAM) 13 | F = sparse(2*(nelx+1)*(nely+1),1,-1,2*(nely+1)*(nelx+1),1); 14 | fixeddofs = 1:2*(nely+1); 15 | % F = sparse(2,1,-1,2*(nely+1)*(nelx+1),1); 16 | % fixeddofs = union(1:2:2*(nely+1),2*(nelx+1)*(nely+1)); 17 | U = zeros(2*(nely+1)*(nelx+1),1); 18 | alldofs = 1:2*(nely+1)*(nelx+1); 19 | freedofs = setdiff(alldofs,fixeddofs); 20 | %% PREPARE FILTER 21 | iH = ones(nlx*nly*(2*(ceil(rmin)-1)+1)^2,1); 22 | jH = ones(size(iH)); 23 | sH = zeros(size(iH)); 24 | k = 0; 25 | for i1 = 1:nlx 26 | for j1 = 1:nly 27 | e1 = (i1-1)*nly+j1; 28 | for i2 = max(i1-(ceil(rmin)-1),1):min(i1+(ceil(rmin)-1),nlx) 29 | for j2 = max(j1-(ceil(rmin)-1),1):min(j1+(ceil(rmin)-1),nly) 30 | e2 = (i2-1)*nly+j2; 31 | k = k+1; 32 | iH(k) = e1; 33 | jH(k) = e2; 34 | sH(k) = max(0,rmin-sqrt((i1-i2)^2+(j1-j2)^2)); 35 | end 36 | end 37 | end 38 | end 39 | H = sparse(iH,jH,sH); 40 | Hs = sum(H,2); 41 | %% INITIALIZE ITERATION 42 | x = ones(nly,nlx); 43 | for i = 1:nlx 44 | for j = 1:nly 45 | if sqrt((i-nlx/2-0.5)^2+(j-nly/2-0.5)^2) < min(nlx,nly)/3 46 | x(j,i) = 0; 47 | end 48 | end 49 | end 50 | xPhys = x; 51 | loop = 0; 52 | change = 1; 53 | %% START ITERATION 54 | while change > 0.01 55 | loop = loop + 1; 56 | %% INTERPOLATION 57 | [E, dE] = interpolate(x,E0,Emin,penal); 58 | %% HOMOGENIZATION 59 | [CH,DCH] = homogenize(0.000001*lx,0.000001*ly,E,nu,dE,90); 60 | %% FE-ANALYSIS 61 | KE = Q4elementStiffnessMatrix(lx/nelx,ly/nely,90,CH); 62 | sK = reshape(KE(:)*ones(1,nely*nelx),64*nelx*nely,1); 63 | K = sparse(iK,jK,sK); K = (K+K')/2; 64 | U(freedofs) = K(freedofs,freedofs)\F(freedofs); 65 | %% OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS 66 | f = @(DCh) Q4elementStiffnessMatrix(lx/nelx,ly/nely,90,DCh); 67 | dKe = cellfun(f,DCH,'UniformOutput',false); 68 | f= @(dKE) reshape(sum((U(edofMat)*dKE).*U(edofMat),2),nely,nelx); 69 | ce = cellfun(f,dKe,'UniformOutput',false); 70 | c = sum(sum(cell2mat(cellfun(@sum, ce, 'UniformOutput',false)))); 71 | dc = - cell2mat(cellfun(@sum,cellfun(@sum,cellfun(@sum, ce, 'UniformOutput',false),'UniformOutput',false),'UniformOutput',false)); 72 | dv = ones(nly,nlx); 73 | %% FILTERING/MODIFICATION OF SENSITIVITIES 74 | if ft == 1 75 | dc(:) = H*(x(:).*dc(:))./Hs./max(1e-3,x(:)); 76 | elseif ft == 2 77 | dc(:) = H*(dc(:)./Hs); 78 | dv(:) = H*(dv(:)./Hs); 79 | end 80 | %% OPTIMALITY CRITERIA UPDATE OF DESIGN VARIABLES AND PHYSICAL DENSITIES 81 | l1 = 0; l2 = 1e9; move = 0.2; 82 | while (l2-l1)/(l1+l2) > 1e-3 83 | lmid = 0.5*(l2+l1); 84 | xnew = max(0,max(x-move,min(1,min(x+move,x.*sqrt(-dc./dv/lmid))))); 85 | if ft == 1 86 | xPhys = xnew; 87 | elseif ft == 2 88 | xPhys(:) = (H*xnew(:))./Hs; 89 | end 90 | if sum(xPhys(:)) > volfrac*nlx*nly, l1 = lmid; else l2 = lmid; end 91 | end 92 | change = max(abs(xnew(:)-x(:))); 93 | x = xnew; 94 | %% PRINT RESULTS 95 | fprintf(' It.:%5i Obj.:%11.4f Vol.:%7.3f ch.:%7.3f\n',loop,c, ... 96 | mean(xPhys(:)),change); 97 | %% PLOT DENSITIES 98 | colormap(gray); imagesc(1-xPhys); caxis([0 1]); axis equal; axis off; drawnow; 99 | end 100 | end 101 | 102 | function [E,dE] = interpolate(x, E0, Emin, penal) 103 | E = Emin + x.^penal * (E0-Emin); 104 | dE = penal * x.^(penal-1) * (E0-Emin); 105 | end 106 | -------------------------------------------------------------------------------- /3D Homogenization Young/homo3DY.m: -------------------------------------------------------------------------------- 1 | function CH = homo3DY(lx,ly,lz,E,nu,Emin) 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % lx = Unit cell length in x-direction. 4 | % ly = Unit cell length in y-direction. 5 | % lz = Unit cell length in z-direction. 6 | % lambda = Lame's first parameter for solid materials. 7 | % mu = Lame's second parameter for solid materials. 8 | % voxel = Material indicator matrix. Used to determine nelx/nely/nelz 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% INITIALIZE 11 | [nelx, nely, nelz] = size(E); %size of voxel model along x,y and z axis 12 | % Stiffness matrix 13 | dx = lx/nelx; dy = ly/nely; dz = lz/nelz; 14 | nel = nelx*nely*nelz; 15 | [ke, fe] = hexahedronY(dx/2,dy/2,dz/2,nu); 16 | % Node numbers and element degrees of freedom for full (not periodic) mesh 17 | nodenrs = reshape(1:(1+nelx)*(1+nely)*(1+nelz),1+nelx,1+nely,1+nelz); 18 | edofVec = reshape(3*nodenrs(1:end-1,1:end-1,1:end-1)+1,nel,1); 19 | addx = [0 1 2 3*nelx+[3 4 5 0 1 2] -3 -2 -1]; 20 | addxy = 3*(nely+1)*(nelx+1)+addx; 21 | edof = repmat(edofVec,1,24) + repmat([addx addxy],nel,1); 22 | %% IMPOOSE PERIODIC BOUNDARY CONDITIONS 23 | % Use original edofMat to index into list with the periodic dofs 24 | nn = (nelx+1)*(nely+1)*(nelz+1); % Total number of nodes 25 | nnP = (nelx)*(nely)*(nelz); % Total number of unique nodes 26 | nnPArray = reshape(1:nnP, nelx, nely, nelz); 27 | % Extend with a mirror of the back border 28 | nnPArray(end+1,:,:) = nnPArray(1,:,:); 29 | % Extend with a mirror of the left border 30 | nnPArray(:, end+1, :) = nnPArray(:,1,:); 31 | % Extend with a mirror of the top border 32 | nnPArray(:, :, end+1) = nnPArray(:,:,1); 33 | % Make a vector into which we can index using edofMat: 34 | dofVector = zeros(3*nn, 1); 35 | dofVector(1:3:end) = 3*nnPArray(:)-2; 36 | dofVector(2:3:end) = 3*nnPArray(:)-1; 37 | dofVector(3:3:end) = 3*nnPArray(:); 38 | edof = dofVector(edof); 39 | ndof = 3*nnP; 40 | %% ASSEMBLE GLOBAL STIFFNESS MATRIX AND LOAD VECTORS 41 | % Indexing vectors 42 | iK = kron(edof,ones(24,1))'; 43 | jK = kron(edof,ones(1,24))'; 44 | % Material properties assigned to voxels with materials 45 | % E = E*(voxel==1); 46 | % The corresponding stiffness matrix entries 47 | sK = ke(:)*E(:).'; 48 | K = sparse(iK(:), jK(:), sK(:), ndof, ndof); 49 | K = 1/2*(K+K'); 50 | % Assembly three load cases corresponding to the three strain cases 51 | iF = repmat(edof',6,1); 52 | jF = [ones(24,nel); 2*ones(24,nel); 3*ones(24,nel);... 53 | 4*ones(24,nel); 5*ones(24,nel); 6*ones(24,nel);]; 54 | sF = fe(:)*E(:).'; 55 | F = sparse(iF(:), jF(:), sF(:), ndof, 6); 56 | %% SOLUTION 57 | % solve by PCG method, remember to constrain one node 58 | activedofs = edof(E>Emin,:); activedofs = sort(unique(activedofs(:))); 59 | X = zeros(ndof,6); 60 | L = ichol(K(activedofs(4:end),activedofs(4:end))); 61 | for i = 1:6 62 | X(activedofs(4:end),i) = pcg(K(activedofs(4:end),... 63 | activedofs(4:end)),F(activedofs(4:end),i),1e-10,300,L,L'); 64 | end 65 | % X(activedofs(4:end),:) = K(activedofs(4:end),activedofs(4:end))... 66 | % \F(activedofs(4:end),:); % Solving by direct method 67 | %% HOMOGENIZATION 68 | % The displacement vectors corresponding to the unit strain cases 69 | X0 = zeros(nel, 24, 6); 70 | % The element displacements for the six unit strains 71 | X0_e = zeros(24, 6); 72 | %fix degrees of nodes [1 2 3 5 6 12]; 73 | % ke = keMu + keLambda; % Here the exact ratio does not matter, because 74 | % fe = feMu + feLambda; % it is reflected in the load vector 75 | X0_e([4 7:11 13:24],:) = ke([4 7:11 13:24],[4 7:11 13:24])... 76 | \fe([4 7:11 13:24],:); 77 | X0(:,:,1) = kron(X0_e(:,1)', ones(nel,1)); % epsilon0_11 = (1,0,0,0,0,0) 78 | X0(:,:,2) = kron(X0_e(:,2)', ones(nel,1)); % epsilon0_22 = (0,1,0,0,0,0) 79 | X0(:,:,3) = kron(X0_e(:,3)', ones(nel,1)); % epsilon0_33 = (0,0,1,0,0,0) 80 | X0(:,:,4) = kron(X0_e(:,4)', ones(nel,1)); % epsilon0_12 = (0,0,0,1,0,0) 81 | X0(:,:,5) = kron(X0_e(:,5)', ones(nel,1)); % epsilon0_23 = (0,0,0,0,1,0) 82 | X0(:,:,6) = kron(X0_e(:,6)', ones(nel,1)); % epsilon0_13 = (0,0,0,0,0,1) 83 | CH = zeros(6); 84 | DCH = cell(nely,nelx,nelz); 85 | DCH(:,:,:) = {zeros(6)}; 86 | volume = lx*ly*lz; 87 | for i = 1:6 88 | for j = 1:6 89 | sum_Y = ((X0(:,:,i) - X(edof+(i-1)*ndof))*ke).*... 90 | (X0(:,:,j) - X(edof+(j-1)*ndof)); 91 | sum_Y = reshape(sum(sum_Y,2), nelx, nely, nelz); 92 | % Homogenized elasticity tensor 93 | CH(i,j) = 1/volume*sum(sum(sum(E.*sum_Y))); 94 | end 95 | end 96 | end -------------------------------------------------------------------------------- /Level set 88/levelset88.m: -------------------------------------------------------------------------------- 1 | function levelset88(nelx,nely,volfrac,stepLength,numReinit,topWeight) 2 | %% MATERIAL PROPERTIES 3 | E0 = 1; 4 | nu = 0.3; 5 | Emin = 0.0001; 6 | lambda = E0*nu/((1+nu)*(1-nu)); 7 | mu = E0/(2*(1+nu)); 8 | %% PREPARE FINITE ELEMENT ANALYSIS 9 | % KE 10 | A11 = [12 3 -6 -3; 3 12 3 0; -6 3 12 -3; -3 0 -3 12]; 11 | A12 = [-6 -3 0 3; -3 -6 -3 -6; 0 -3 -6 3; 3 -6 3 -6]; 12 | B11 = [-4 3 -2 9; 3 -4 -9 4; -2 -9 -4 -3; 9 4 -3 -4]; 13 | B12 = [ 2 -3 4 -9; -3 2 9 -2; 4 9 2 3; -9 -2 3 2]; 14 | KE = 1/(1-nu^2)/24*([A11 A12;A12' A11]+nu*[B11 B12;B12' B11]); 15 | % KTr 16 | A11 = [4 3 -4 3; 3 4 -3 2; -4 -3 4 -3; 3 2 -3 4]; 17 | A12 = [-2 -3 2 -3; -3 -2 3 -4; 2 3 -2 3; -3 -4 3 -2]; 18 | KTr = 1/(1-nu)/12*([A11 A12;A12' A11]); 19 | nodenrs = reshape(1:(1+nelx)*(1+nely),1+nely,1+nelx); 20 | edofVec = reshape(2*nodenrs(1:end-1,1:end-1)+1,nelx*nely,1); 21 | edofMat = repmat(edofVec,1,8)+repmat([0 1 2*nely+[2 3 0 1] -2 -1],nelx*nely,1); 22 | iK = reshape(kron(edofMat,ones(8,1))',64*nelx*nely,1); 23 | jK = reshape(kron(edofMat,ones(1,8))',64*nelx*nely,1); 24 | % DEFINE LOADS AND SUPPORTS (Bridge) 25 | F = sparse(2*(round(nelx/2)+1)*(nely+1),1,1,2*(nely+1)*(nelx+1),1); 26 | U = zeros(2*(nely+1)*(nelx+1),1); 27 | fixeddofs = [2*(nely+1)-1:2*(nely+1),2*(nelx+1)*(nely+1)-1:2*(nelx+1)*(nely+1)]; 28 | alldofs = 1:2*(nely+1)*(nelx+1); 29 | freedofs = setdiff(alldofs,fixeddofs); 30 | %% INITIALIZE ITERATION 31 | x = ones(nely,nelx); 32 | [lsf] = reinit(x); % Initialize levelset function 33 | loop = 0; 34 | %% START ITERATION 35 | while loop < 200 36 | loop = loop + 1; 37 | %% FE-ANALYSIS 38 | sK = reshape(KE(:)*(Emin+x(:)'*(E0-Emin)),64*nelx*nely,1); 39 | K = sparse(iK,jK,sK); K = (K+K')/2; 40 | U(freedofs) = K(freedofs,freedofs)\F(freedofs); 41 | %% 42 | % Current Volume 43 | volCurr = sum(x(:))/(nelx*nely); 44 | % Set augmented Lagrangian parameters 45 | if loop == 1 46 | la = -0.01; La = 1000; alpha = 0.9; 47 | else 48 | la = la - 1/La * (volCurr - volfrac); La= alpha * La; 49 | end 50 | %% OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS 51 | ce = reshape(sum((U(edofMat)*KE).*U(edofMat),2),nely,nelx); 52 | ge = reshape(sum((U(edofMat)*KTr).*U(edofMat),2),nely,nelx); 53 | c(loop) = sum(sum((Emin+x*(E0-Emin)).*ce)); 54 | dc = -((E0-Emin)*x+Emin).*ce - la + 1/La*(volCurr-volfrac); 55 | dg = x.*(pi/2*(lambda+2*mu)/mu/(lambda+mu)*(4*mu*ce+(lambda-mu)*ge))... 56 | + pi*(la - 1/La*(volCurr-volfrac)); 57 | % Design update 58 | [x,lsf] = updateStep(lsf,dc,dg,stepLength,topWeight); 59 | % Reinitialize level-set function 60 | if ~mod(loop,numReinit) 61 | [lsf] = reinit(x); 62 | end 63 | %% PRINT RESULTS 64 | fprintf(' It.:%5i Obj.:%11.4f Vol.:%7.3f\n',loop,c(loop), ... 65 | mean(x(:))); 66 | %% PLOT DENSITIES 67 | colormap(gray); imagesc(1-x); caxis([0 1]); axis equal; axis off; drawnow; 68 | end 69 | end 70 | % 71 | %%---- REINITIALIZATION OF LEVEL-SETFUNCTION ---- 72 | function [lsf] = reinit(struc) 73 | strucFull = zeros(size(struc)+2); 74 | strucFull(2:end-1,2:end-1) = struc; 75 | % Use "bwdist" (Image Processing Toolbox) 76 | lsf = (~strucFull).*(bwdist(strucFull)-0.5) - strucFull.*(bwdist(strucFull-1)-0.5); 77 | end 78 | % 79 | %%----- DESIGN UPDATE ---- 80 | function [struc,lsf] = updateStep(lsf,shapeSens,topSens,stepLength,topWeight) 81 | % Smooth the sensitivities 82 | [shapeSens] = conv2(padarray(shapeSens,[1,1],'replicate'),1/6*[0 1 0; 1 2 1;0 1 0],'valid'); 83 | [topSens] = conv2(padarray(topSens,[1,1],'replicate'),1/6*[0 1 0; 1 2 1; 0 1 0],'valid'); 84 | % Load bearing pixels must remain solid -Bridge: 85 | % edw nomizw einai karfota gia to paradeigma pou exei. 86 | shapeSens(end,[1,round(end/2):round(end/2+1),end]) = 0; 87 | topSens(end,[1,round(end/2):round(end/2+1),end]) = 0; 88 | % Design update via evolution 89 | [struc,lsf] = evolve(-shapeSens,topSens.*(lsf(2:end-1,2:end-1)<0),lsf,stepLength,topWeight); 90 | end 91 | % 92 | %%---- EVOLUTION OF LEVEL-SET FUNCTION---- 93 | function [struc,lsf] = evolve(v,g,lsf,stepLength,w) 94 | % Extend sensitivites using a zero border 95 | vFull = zeros(size(v)+2); vFull(2:end-1,2:end-1) = v; 96 | gFull = zeros(size(g)+2); gFull(2:end-1,2:end-1) = g; 97 | % Choose time step for evolution based onCFL value 98 | dt = 0.1/max(abs(v(:))); 99 | % Evolve for total time stepLength * CFLvalue: 100 | for i = 1:(10*stepLength) 101 | % Calculate derivatives on the grid 102 | dpx = circshift(lsf,[0,-1])-lsf; 103 | dmx = lsf - circshift(lsf,[0,1]); 104 | dpy = circshift(lsf,[-1,0]) - lsf; 105 | dmy = lsf - circshift(lsf,[1,0]); 106 | % Update level set function using anupwind scheme 107 | lsf = lsf - dt * min(vFull,0).* ... 108 | sqrt( min(dmx,0).^2+max(dpx,0).^2+min(dmy,0).^2+max(dpy,0).^2 ) ... 109 | - dt * max(vFull,0) .*... 110 | sqrt( max(dmx,0).^2+min(dpx,0).^2+max(dmy,0).^2+min(dpy,0).^2 )... 111 | - w*dt*gFull; 112 | end 113 | % New structure obtained from lsf 114 | strucFull = (lsf<0); struc = strucFull(2:end-1,2:end-1); 115 | end 116 | % -------------------------------------------------------------------------------- /UCOpt3D/hexahedron.m: -------------------------------------------------------------------------------- 1 | classdef hexahedron 2 | %hexahedron hexahedron element stiffness matrix 3 | 4 | properties 5 | weights; 6 | Bv; 7 | end 8 | 9 | methods 10 | function obj = hexahedron(a,b,c) 11 | %hexahedron Construct an instance of this class 12 | % compute weights and B for later use 13 | [weights,B] = obj.initialize(a,b,c); 14 | obj.weights = weights; 15 | obj.Bv = B; 16 | end 17 | 18 | function [ke,fe] = elemStiffness(obj,C) 19 | ke = zeros(24,24); 20 | fe = zeros(24,6); 21 | for i = 1:size(obj.weights,1) 22 | ke = ke + obj.weights(i) * obj.Bv{i}' * C * obj.Bv{i}; 23 | fe = fe + obj.weights(i) * obj.Bv{i}' * C; 24 | end 25 | end 26 | 27 | function [ke,fe] = elemStiffnessC(obj,E,nu) 28 | C = obj.elasticityTensor(E,nu); 29 | [ke,fe] = elemStiffness(obj,C); 30 | end 31 | end 32 | methods(Static) 33 | function [weights,Bv] = initialize(a,b,c) 34 | % Three Gauss points in both directions 35 | xx = [-sqrt(3/5), 0, sqrt(3/5)]; 36 | yy = xx; zz = xx; 37 | ww = [5/9, 8/9, 5/9]; 38 | % Initialize 39 | weights = zeros(length(xx) * length(yy) * length(zz),1); 40 | Bv = cell(length(xx) * length(yy) * length(zz),1); 41 | count = 0; 42 | for ii = 1:length(xx) 43 | for jj = 1:length(yy) 44 | for kk = 1:length(zz) 45 | count = count + 1; 46 | %integration point 47 | x = xx(ii); y = yy(jj); z = zz(kk); 48 | %stress strain displacement matrix 49 | qx = [ -((y-1)*(z-1))/8, ((y-1)*(z-1))/8, -((y+1)*(z-1))/8,... 50 | ((y+1)*(z-1))/8, ((y-1)*(z+1))/8, -((y-1)*(z+1))/8,... 51 | ((y+1)*(z+1))/8, -((y+1)*(z+1))/8]; 52 | qy = [ -((x-1)*(z-1))/8, ((x+1)*(z-1))/8, -((x+1)*(z-1))/8,... 53 | ((x-1)*(z-1))/8, ((x-1)*(z+1))/8, -((x+1)*(z+1))/8,... 54 | ((x+1)*(z+1))/8, -((x-1)*(z+1))/8]; 55 | qz = [ -((x-1)*(y-1))/8, ((x+1)*(y-1))/8, -((x+1)*(y+1))/8,... 56 | ((x-1)*(y+1))/8, ((x-1)*(y-1))/8, -((x+1)*(y-1))/8,... 57 | ((x+1)*(y+1))/8, -((x-1)*(y+1))/8]; 58 | % Jacobian 59 | J = [qx; qy; qz]*[-a a a -a -a a a -a; -b -b b b -b -b b b;... 60 | -c -c -c -c c c c c]'; 61 | qxyz = J\[qx;qy;qz]; 62 | B_e = zeros(6,3,8); 63 | for i_B = 1:8 64 | B_e(:,:,i_B) = [qxyz(1,i_B) 0 0; 65 | 0 qxyz(2,i_B) 0; 66 | 0 0 qxyz(3,i_B); 67 | qxyz(2,i_B) qxyz(1,i_B) 0; 68 | 0 qxyz(3,i_B) qxyz(2,i_B); 69 | qxyz(3,i_B) 0 qxyz(1,i_B)]; 70 | end 71 | B = [B_e(:,:,1) B_e(:,:,2) B_e(:,:,3) B_e(:,:,4) B_e(:,:,5)... 72 | B_e(:,:,6) B_e(:,:,7) B_e(:,:,8)]; 73 | % Weight factor at this point 74 | weight = det(J)*ww(ii) * ww(jj) * ww(kk); 75 | % Save 76 | weights(count) = weight; 77 | Bv{count} = B; 78 | end 79 | end 80 | end 81 | end 82 | 83 | function [C] = elasticityTensor(E,nu) 84 | C = E/((1+nu)*(1-2*nu))*[1-nu nu nu 0 0 0; nu 1-nu nu 0 0 0;... 85 | nu nu 1-nu 0 0 0; 0 0 0 (1-2*nu)/2 0 0; 0 0 0 0 (1-2*nu)/2 0;... 86 | 0 0 0 0 0 (1-2*nu)/2]; 87 | end 88 | end 89 | end 90 | % 91 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 92 | % This Matlab code was modified by G. Kazakis and N.D. Lagaros and was 93 | % based on the homo3D.m code written by G. Dong, Y. Tang, Y.F. Zhao, 94 | % in the paper "A 149 Line Homogenization Code for Three-Dimensional 95 | % Cellular Materials Written in matlab", G. Dong, Y. Tang, Y.F. Zhao, 96 | % Journal of Engineering Materials and Technology, 2018 97 | % 98 | % The code is intended for educational purposes, extensions can be found in 99 | % the paper "Topology optimization based material design for 3D domains 100 | % using MATLAB" 101 | % 102 | % Disclaimer: 103 | % The authors reserves all rights for the program. 104 | % The code may be distributed and used for educational purposes. 105 | % The authors do not guarantee that the code is free from errors, and 106 | % they shall not be liable in any event caused by the use of the program. 107 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /SIMP_88 MMA/top88MMA.m: -------------------------------------------------------------------------------- 1 | function top88MMA(nelx,nely,volfrac,penal,rmin,ft,type) 2 | %% MATERIAL PROPERTIES 3 | E0 = 1; 4 | Emin = 1e-9; 5 | nu = 0.3; 6 | %% PREPARE FINITE ELEMENT ANALYSIS 7 | A11 = [12 3 -6 -3; 3 12 3 0; -6 3 12 -3; -3 0 -3 12]; 8 | A12 = [-6 -3 0 3; -3 -6 -3 -6; 0 -3 -6 3; 3 -6 3 -6]; 9 | B11 = [-4 3 -2 9; 3 -4 -9 4; -2 -9 -4 -3; 9 4 -3 -4]; 10 | B12 = [ 2 -3 4 -9; -3 2 9 -2; 4 9 2 3; -9 -2 3 2]; 11 | KE = 1/(1-nu^2)/24*([A11 A12;A12' A11]+nu*[B11 B12;B12' B11]); 12 | nodenrs = reshape(1:(1+nelx)*(1+nely),1+nely,1+nelx); 13 | edofVec = reshape(2*nodenrs(1:end-1,1:end-1)+1,nelx*nely,1); 14 | edofMat = repmat(edofVec,1,8)+repmat([0 1 2*nely+[2 3 0 1] -2 -1],nelx*nely,1); 15 | iK = reshape(kron(edofMat,ones(8,1))',64*nelx*nely,1); 16 | jK = reshape(kron(edofMat,ones(1,8))',64*nelx*nely,1); 17 | % DEFINE LOADS AND SUPPORTS (HALF MBB-BEAM) 18 | F = sparse(2,1,-1,2*(nely+1)*(nelx+1),1); 19 | U = zeros(2*(nely+1)*(nelx+1),1); 20 | fixeddofs = union(1:2:2*(nely+1),2*(nelx+1)*(nely+1)); 21 | alldofs = 1:2*(nely+1)*(nelx+1); 22 | freedofs = setdiff(alldofs,fixeddofs); 23 | %% PREPARE FILTER 24 | iH = ones(nelx*nely*(2*(ceil(rmin)-1)+1)^2,1); 25 | jH = ones(size(iH)); 26 | sH = zeros(size(iH)); 27 | k = 0; 28 | for i1 = 1:nelx 29 | for j1 = 1:nely 30 | e1 = (i1-1)*nely+j1; 31 | for i2 = max(i1-(ceil(rmin)-1),1):min(i1+(ceil(rmin)-1),nelx) 32 | for j2 = max(j1-(ceil(rmin)-1),1):min(j1+(ceil(rmin)-1),nely) 33 | e2 = (i2-1)*nely+j2; 34 | k = k+1; 35 | iH(k) = e1; 36 | jH(k) = e2; 37 | sH(k) = max(0,rmin-sqrt((i1-i2)^2+(j1-j2)^2)); 38 | end 39 | end 40 | end 41 | end 42 | H = sparse(iH,jH,sH); 43 | Hs = sum(H,2); 44 | %% INITIALIZE ITERATION 45 | x = repmat(volfrac,nely,nelx); 46 | xold1 = repmat(volfrac,nely,nelx); 47 | xold2 = repmat(volfrac,nely,nelx); 48 | xPhys = x; 49 | loop = 0; 50 | change = 1; 51 | Lm = zeros(nely,nelx); 52 | Um = zeros(nely,nelx); 53 | %% START ITERATION 54 | while change > 0.01 55 | loop = loop + 1; 56 | %% FE-ANALYSIS 57 | sK = reshape(KE(:)*(Emin+xPhys(:)'.^penal*(E0-Emin)),64*nelx*nely,1); 58 | K = sparse(iK,jK,sK); K = (K+K')/2; 59 | U(freedofs) = K(freedofs,freedofs)\F(freedofs); 60 | %% OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS 61 | ce = reshape(sum((U(edofMat)*KE).*U(edofMat),2),nely,nelx); 62 | c = sum(sum((Emin+xPhys.^penal*(E0-Emin)).*ce)); 63 | dc = -penal*(E0-Emin)*xPhys.^(penal-1).*ce; 64 | dv = ones(nely,nelx); 65 | %% FILTERING/MODIFICATION OF SENSITIVITIES 66 | if ft == 1 67 | dc(:) = H*(x(:).*dc(:))./Hs./max(1e-3,x(:)); 68 | elseif ft == 2 69 | dc(:) = H*(dc(:)./Hs); 70 | dv(:) = H*(dv(:)./Hs); 71 | end 72 | %% Moving Asymptotes 73 | [Lm,Um,a,b] = updateMovingAsymptotes(loop,x,xold1,xold2,Lm,Um,type); 74 | %% MMA UPDATE OF DESIGN VARIABLES AND PHYSICAL DENSITIES 75 | l1 = 0; l2 = 1e9; move = 0.2; 76 | while (l2-l1)/(l1+l2) > 1e-3 77 | lmid = 0.5*(l2+l1); 78 | q = -(x - Lm).^2.*dc; 79 | xnew = max(0,max(x-move,max(a,min(1,min(x+move,min(b,real(sqrt(q./dv/lmid)+Lm))))))); 80 | if ft == 1 81 | xPhys = xnew; 82 | elseif ft == 2 83 | xPhys(:) = (H*xnew(:))./Hs; 84 | end 85 | if sum(xPhys(:)) > volfrac*nelx*nely, l1 = lmid; else l2 = lmid; end 86 | end 87 | change = max(abs(xnew(:)-x(:))); 88 | % save xold1 and xold2 89 | xold2 = xold1; 90 | xold1 = x; 91 | x = xnew; 92 | %% PRINT RESULTS 93 | fprintf(' It.:%5i Obj.:%11.4f Vol.:%7.3f ch.:%7.3f\n',loop,c, ... 94 | mean(xPhys(:)),change); 95 | %% PLOT DENSITIES 96 | colormap(gray); imagesc(1-xPhys); caxis([0 1]); axis equal; axis off; drawnow; 97 | end 98 | end 99 | 100 | function [Lm,Um,a,b] = updateMovingAsymptotes(loop,x,xold1,xold2,Lm,Um,w) 101 | switch (w) 102 | case 'Fixed' 103 | s0 = 0.1; 104 | Lm = x - s0; 105 | Um = x + s0; 106 | a = 0.9*Lm + 0.1*x; 107 | b = 0.9*Um + 0.1*x; 108 | case 'Svanberg' 109 | if loop < 3 110 | Lm = x - 1; 111 | Um = x + 1; 112 | else 113 | s = 0.7; 114 | xg1 = sign(x - xold1); 115 | xg2 = sign(xold1 - xold2); 116 | Lm = x - s * (x - Lm) .* (xg1 ~= xg2) - (x - Lm)./s .* (xg1 == xg2); 117 | Um = x + s * (Um - x) .* (xg1 ~= xg2) + (Um - x)./s .* (xg1 == xg2); 118 | end 119 | a = 0.9*Lm + 0.1*x; 120 | b = 0.9*Um + 0.1*x; 121 | case 'Liu&Tovar' 122 | if loop < 3 123 | Lm = (2*x - 1)./2; 124 | Um = Lm + 1; 125 | else 126 | xg = (x - xold1).*(xold1 - xold2); 127 | g = 0.7 * (xg < 0) + 1.2 * (xg > 0) + 1 * (xg == 0); 128 | Lm = (2*x - g)./2; 129 | Um = Lm + g; 130 | end 131 | a = 0.9*Lm + 0.1*x; 132 | b = 0.9*Um + 0.1*x; 133 | case 'Christensen&Klarbring' 134 | if loop < 3 135 | sinit = 0.5; 136 | Lm = x - sinit; 137 | Um = x + sinit; 138 | else 139 | slow = 0.5; 140 | sfast = 1.5; 141 | xg1 = sign(x - xold1); 142 | xg2 = sign(xold1 - xold2); 143 | Lm = x - slow * (x - Lm) .* (xg1 ~= xg2) - sfast * (x - Lm) .* (xg1 == xg2); 144 | Um = x + slow * (Um - x) .* (xg1 ~= xg2) + sfast * (Um - x) .* (xg1 == xg2); 145 | end 146 | mu = 0.5; 147 | a = max(0, Lm + mu*(x - Lm)); 148 | b = min(1, Um - mu*(Um - x)); 149 | end 150 | end 151 | 152 | 153 | -------------------------------------------------------------------------------- /UCOpt3D/homo3DY.m: -------------------------------------------------------------------------------- 1 | function [CH,DCH] = homo3DY(lx,ly,lz,E,dE,nu,Emin,hk) 2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 | % lx = Unit cell length in x-direction. 4 | % ly = Unit cell length in y-direction. 5 | % lz = Unit cell length in z-direction. 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | %% INITIALIZE 8 | [nelx, nely, nelz] = size(E); %size of voxel model along x,y and z axis 9 | % Stiffness matrix 10 | % dx = lx/nelx; dy = ly/nely; dz = lz/nelz; 11 | nel = nelx*nely*nelz; 12 | % [ke1, fe1] = hexahedronY(dx/2,dy/2,dz/2,nu); 13 | [ke,fe] = hk.elemStiffnessC(1,nu); 14 | % Node numbers and element degrees of freedom for full (not periodic) mesh 15 | nodenrs = reshape(1:(1+nelx)*(1+nely)*(1+nelz),1+nelx,1+nely,1+nelz); 16 | edofVec = reshape(3*nodenrs(1:end-1,1:end-1,1:end-1)+1,nel,1); 17 | addx = [0 1 2 3*nelx+[3 4 5 0 1 2] -3 -2 -1]; 18 | addxy = 3*(nely+1)*(nelx+1)+addx; 19 | edof = repmat(edofVec,1,24) + repmat([addx addxy],nel,1); 20 | %% IMPOOSE PERIODIC BOUNDARY CONDITIONS 21 | % Use original edofMat to index into list with the periodic dofs 22 | nn = (nelx+1)*(nely+1)*(nelz+1); % Total number of nodes 23 | nnP = (nelx)*(nely)*(nelz); % Total number of unique nodes 24 | nnPArray = reshape(1:nnP, nelx, nely, nelz); 25 | % Extend with a mirror of the back border 26 | nnPArray(end+1,:,:) = nnPArray(1,:,:); 27 | % Extend with a mirror of the left border 28 | nnPArray(:, end+1, :) = nnPArray(:,1,:); 29 | % Extend with a mirror of the top border 30 | nnPArray(:, :, end+1) = nnPArray(:,:,1); 31 | % Make a vector into which we can index using edofMat: 32 | dofVector = zeros(3*nn, 1); 33 | dofVector(1:3:end) = 3*nnPArray(:)-2; 34 | dofVector(2:3:end) = 3*nnPArray(:)-1; 35 | dofVector(3:3:end) = 3*nnPArray(:); 36 | edof = dofVector(edof); 37 | ndof = 3*nnP; 38 | %% ASSEMBLE GLOBAL STIFFNESS MATRIX AND LOAD VECTORS 39 | % Indexing vectors 40 | iK = kron(edof,ones(24,1))'; 41 | jK = kron(edof,ones(1,24))'; 42 | % Material properties assigned to voxels with materials 43 | % E = E*(voxel==1); 44 | % The corresponding stiffness matrix entries 45 | sK = ke(:)*E(:).'; 46 | K = sparse(iK(:), jK(:), sK(:), ndof, ndof); 47 | K = 1/2*(K+K'); 48 | % Assembly three load cases corresponding to the three strain cases 49 | iF = repmat(edof',6,1); 50 | jF = [ones(24,nel); 2*ones(24,nel); 3*ones(24,nel);... 51 | 4*ones(24,nel); 5*ones(24,nel); 6*ones(24,nel);]; 52 | sF = fe(:)*E(:).'; 53 | F = sparse(iF(:), jF(:), sF(:), ndof, 6); 54 | %% SOLUTION 55 | % solve by PCG method, remember to constrain one node 56 | activedofs = edof(E>Emin,:); activedofs = sort(unique(activedofs(:))); 57 | X = zeros(ndof,6); 58 | % L = ichol(K(activedofs(4:end),activedofs(4:end))); 59 | % for i = 1:6 60 | % X(activedofs(4:end),i) = pcg(K(activedofs(4:end),... 61 | % activedofs(4:end)),F(activedofs(4:end),i),1e-10,300,L,L'); 62 | % end 63 | X(activedofs(4:end),:) = K(activedofs(4:end),activedofs(4:end))... 64 | \F(activedofs(4:end),:); % Solving by direct method 65 | %% HOMOGENIZATION 66 | % The displacement vectors corresponding to the unit strain cases 67 | X0 = zeros(nel, 24, 6); 68 | % The element displacements for the six unit strains 69 | X0_e = zeros(24, 6); 70 | %fix degrees of nodes [1 2 3 5 6 12]; 71 | % ke = keMu + keLambda; % Here the exact ratio does not matter, because 72 | % fe = feMu + feLambda; % it is reflected in the load vector 73 | X0_e([4 7:11 13:24],:) = ke([4 7:11 13:24],[4 7:11 13:24])... 74 | \fe([4 7:11 13:24],:); 75 | X0(:,:,1) = kron(X0_e(:,1)', ones(nel,1)); % epsilon0_11 = (1,0,0,0,0,0) 76 | X0(:,:,2) = kron(X0_e(:,2)', ones(nel,1)); % epsilon0_22 = (0,1,0,0,0,0) 77 | X0(:,:,3) = kron(X0_e(:,3)', ones(nel,1)); % epsilon0_33 = (0,0,1,0,0,0) 78 | X0(:,:,4) = kron(X0_e(:,4)', ones(nel,1)); % epsilon0_12 = (0,0,0,1,0,0) 79 | X0(:,:,5) = kron(X0_e(:,5)', ones(nel,1)); % epsilon0_23 = (0,0,0,0,1,0) 80 | X0(:,:,6) = kron(X0_e(:,6)', ones(nel,1)); % epsilon0_13 = (0,0,0,0,0,1) 81 | CH = zeros(6); 82 | DCH = cell(nely,nelx,nelz); 83 | DCH(:,:,:) = {zeros(6)}; 84 | volume = lx*ly*lz; 85 | for i = 1:6 86 | for j = 1:6 87 | sum_Y = ((X0(:,:,i) - X(edof+(i-1)*ndof))*ke).*... 88 | (X0(:,:,j) - X(edof+(j-1)*ndof)); 89 | sum_Y = reshape(sum(sum_Y,2), nely, nelx, nelz); 90 | % Homogenized elasticity tensor 91 | CH(i,j) = 1/volume*sum(sum(sum(E.*sum_Y))); 92 | fS = dE.*sum_Y; 93 | for k=1:nely 94 | for l=1:nelx 95 | for h=1:nelz 96 | DCH{k,l,h}(i,j) = 1/volume * fS(k,l,h); 97 | end 98 | end 99 | end 100 | end 101 | end 102 | end 103 | % 104 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 105 | % This Matlab code was modified by G. Kazakis and N.D. Lagaros and was 106 | % based on the homo3D.m code written by G. Dong, Y. Tang, Y.F. Zhao, 107 | % in the paper "A 149 Line Homogenization Code for Three-Dimensional 108 | % Cellular Materials Written in matlab", G. Dong, Y. Tang, Y.F. Zhao, 109 | % Journal of Engineering Materials and Technology, 2018 110 | % 111 | % The code is intended for educational purposes, extensions can be found in 112 | % the paper "Topology optimization based material design for 3D domains 113 | % using MATLAB" 114 | % 115 | % Disclaimer: 116 | % The authors reserves all rights for the program. 117 | % The code may be distributed and used for educational purposes. 118 | % The authors do not guarantee that the code is free from errors, and 119 | % they shall not be liable in any event caused by the use of the program. 120 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /Level set 3D/D3_LB.m: -------------------------------------------------------------------------------- 1 | function [K,B,E,V] = D3_LB (dx, dy, dz, miu) 2 | 3 | % x1 = -1; y1 = -1; z1 = -1; 4 | % x2 = 1; y2 = -1; z2 = -1; 5 | % x3 = 1; y3 = 1; z3 = -1; 6 | % x4 = -1; y4 = 1; z4 = -1; 7 | % x5 = -1; y5 = -1; z5 = 1; 8 | % x6 = 1; y6 = -1; z6 = 1; 9 | % x7 = 1; y7 = 1; z7 = 1; 10 | % x8 = -1; y8 = 1; z8 = 1; 11 | % Em = 1; miu = 0.3; 12 | x1 = -dx/2; y1 = -dy/2; z1 = -dz/2; 13 | x2 = dx/2; y2 = -dy/2; z2 = -dz/2; 14 | x3 = dx/2; y3 = dy/2; z3 = -dz/2; 15 | x4 = -dx/2; y4 = dy/2; z4 = -dz/2; 16 | x5 = -dx/2; y5 = -dy/2; z5 = dz/2; 17 | x6 = dx/2; y6 = -dy/2; z6 = dz/2; 18 | x7 = dx/2; y7 = dy/2; z7 = dz/2; 19 | x8 = -dx/2; y8 = dy/2; z8 = dz/2; 20 | Em = 1; 21 | 22 | % s=(1-miu); 23 | E = Em*(1-miu)/((1+miu)*(1-2*miu)).*... 24 | [ 1 1 1 0 0 0; 25 | 1 1 1 0 0 0; 26 | 1 1 1 0 0 0; 27 | 0 0 0 0 0 0; 28 | 0 0 0 0 0 0; 29 | 0 0 0 0 0 0]; 30 | 31 | K = zeros(24,24); K2 = zeros(24,24); K3 = zeros(24,24); 32 | B = zeros(6,24); 33 | V2 = 0; V3 = 0; V = 0; 34 | 35 | int_point = [ -sqrt(3/5) 0 sqrt(3/5) ]; 36 | 37 | 38 | for i=1:3 39 | if i==1, xi1=int_point(1); end 40 | if i==2, xi1=int_point(2); end 41 | if i==3, xi1=int_point(3); end 42 | for j=1:3 43 | if j==1, xi2=int_point(1); end 44 | if j==2, xi2=int_point(2); end 45 | if j==3, xi2=int_point(3); end 46 | for k=1:3 47 | if k==1, xi3=int_point(1); end 48 | if k==2, xi3=int_point(2); end 49 | if k==3, xi3=int_point(3); end 50 | R = 1/8.*[ (-1+xi3+xi2-xi2*xi3) (1-xi3-xi2+xi2*xi3) (1-xi3+xi2-xi2*xi3) ... 51 | (-1+xi3-xi2+xi2*xi3) (-1-xi3+xi2+xi2*xi3) (1+xi3-xi2-xi2*xi3) ... 52 | (1+xi3+xi2+xi2*xi3) (-1-xi3-xi2-xi2*xi3); 53 | (-1+xi3+xi1-xi1*xi3) (-1+xi3-xi1+xi1*xi3) (1-xi3+xi1-xi1*xi3) ... 54 | (1-xi3-xi1+xi1*xi3) (-1-xi3+xi1+xi1*xi3) (-1-xi3-xi1-xi1*xi3) ... 55 | (1+xi3+xi1+xi1*xi3) (1+xi3-xi1-xi1*xi3); 56 | (-1+xi2+xi1-xi1*xi2) (-1+xi2-xi1+xi1*xi2) (-1-xi2-xi1-xi1*xi2) ... 57 | (-1-xi2+xi1+xi1*xi2) (1-xi2-xi1+xi1*xi2) (1-xi2+xi1-xi1*xi2) ... 58 | (1+xi2+xi1+xi1*xi2) (1+xi2-xi1-xi1*xi2)]; 59 | 60 | J = R * [ x1 y1 z1; x2 y2 z2; x3 y3 z3; x4 y4 z4; x5 y5 z5; 61 | x6 y6 z6; x7 y7 z7; x8 y8 z8]; 62 | if inv(J) <=0, disp(' error: negative Jacobian in element'); end 63 | % dN = inv(J)*R; 64 | dN = J\R; 65 | 66 | B1 = [dN(1,1) 0 0 dN(1,2) 0 0 dN(1,3) 0 0 dN(1,4) 0 0 dN(1,5) 0 0 ... 67 | dN(1,6) 0 0 dN(1,7) 0 0 dN(1,8) 0 0; 68 | 0 dN(2,1) 0 0 dN(2,2) 0 0 dN(2,3) 0 0 dN(2,4) 0 0 dN(2,5) 0 0 ... 69 | dN(2,6) 0 0 dN(2,7) 0 0 dN(2,8) 0; 70 | 0 0 dN(3,1) 0 0 dN(3,2) 0 0 dN(3,3) 0 0 dN(3,4) 0 0 dN(3,5) 0 0 ... 71 | dN(3,6) 0 0 dN(3,7) 0 0 dN(3,8); 72 | dN(2,1) dN(1,1) 0 dN(2,2) dN(1,2) 0 dN(2,3) dN(1,3) ... 73 | 0 dN(2,4) dN(1,4) 0 dN(2,5) dN(1,5) 0 dN(2,6) dN(1,6) 0 ... 74 | dN(2,7) dN(1,7) 0 dN(2,8) dN(1,8) 0; 75 | 0 dN(3,1) dN(2,1) 0 dN(3,2) dN(2,2) 0 dN(3,3) dN(2,3) ... 76 | 0 dN(3,4) dN(2,4) 0 dN(3,5) dN(2,5) 0 dN(3,6) dN(2,6) 0 ... 77 | dN(3,7) dN(2,7) 0 dN(3,8) dN(2,8); 78 | dN(3,1) 0 dN(1,1) dN(3,2) 0 dN(1,2) dN(3,3) 0 dN(1,3) ... 79 | dN(3,4) 0 dN(1,4) dN(3,5) 0 dN(1,5) dN(3,6) 0 dN(1,6) ... 80 | dN(3,7) 0 dN(1,7) dN(3,8) 0 dN(1,8)]; 81 | 82 | Vo = det(J); 83 | K1 = B1'*E*B1.*Vo ; 84 | 85 | if k==1, V2 = V2 + 5/9.*Vo; end 86 | if k==2, V2 = V2 + 8/9.*Vo; end 87 | if k==3, V2 = V2 + 5/9.*Vo; end 88 | 89 | if (xi1==0 && xi2==0 && xi3==0), B(1:6,1:24,1) = B1; end 90 | 91 | if k==1, K2 = K2 + 5/9.*K1; end 92 | if k==2, K2 = K2 + 8/9.*K1; end 93 | if k==3, K2 = K2 + 5/9.*K1; end 94 | end 95 | 96 | if j==1, V3 = V3 + 5/9.*V2; end 97 | if j==2, V3 = V3 + 8/9.*V2; end 98 | if j==3, V3 = V3 + 5/9.*V2; end 99 | 100 | if j==1, K3 = K3 + 5/9.*K2; end 101 | if j==2, K3 = K3 + 8/9.*K2; end 102 | if j==3, K3 = K3 + 5/9.*K2; end 103 | K2 = K2.*0; V2 = 0; 104 | end 105 | 106 | if i==1, V = V + 5/9.*V3; end 107 | if i==2, V = V + 8/9.*V3; end 108 | if i==3, V = V + 5/9.*V3; end 109 | 110 | if i==1, K = K + 5/9.*K3; end 111 | if i==2, K = K + 8/9.*K3; end 112 | if i==3, K = K + 5/9.*K3; end 113 | K3 = K3.*0; V3 = 0; 114 | end 115 | 116 | nd_shape = [1 -1 -1 -1; 2 +1 -1 -1; 3 +1 +1 -1; 4 -1 +1 -1; 5 -1 -1 +1; 6 +1 -1 +1; 7 +1 +1 +1; 8 -1 +1 +1]; 117 | 118 | for i=1:8 119 | xi1 = nd_shape(i,2); 120 | xi2 = nd_shape(i,3); 121 | xi3 = nd_shape(i,4); 122 | 123 | R = 1/8.*[ (-1+xi3+xi2-xi2*xi3) (1-xi3-xi2+xi2*xi3) (1-xi3+xi2-xi2*xi3) ... 124 | (-1+xi3-xi2+xi2*xi3) (-1-xi3+xi2+xi2*xi3) (1+xi3-xi2-xi2*xi3) ... 125 | (1+xi3+xi2+xi2*xi3) (-1-xi3-xi2-xi2*xi3); 126 | (-1+xi3+xi1-xi1*xi3) (-1+xi3-xi1+xi1*xi3) (1-xi3+xi1-xi1*xi3) ... 127 | (1-xi3-xi1+xi1*xi3) (-1-xi3+xi1+xi1*xi3) (-1-xi3-xi1-xi1*xi3) ... 128 | (1+xi3+xi1+xi1*xi3) (1+xi3-xi1-xi1*xi3); 129 | (-1+xi2+xi1-xi1*xi2) (-1+xi2-xi1+xi1*xi2) (-1-xi2-xi1-xi1*xi2) ... 130 | (-1-xi2+xi1+xi1*xi2) (1-xi2-xi1+xi1*xi2) (1-xi2+xi1-xi1*xi2) ... 131 | (1+xi2+xi1+xi1*xi2) (1+xi2-xi1-xi1*xi2)]; 132 | 133 | J = R * [ x1 y1 z1; x2 y2 z2; x3 y3 z3; x4 y4 z4; x5 y5 z5; 134 | x6 y6 z6; x7 y7 z7; x8 y8 z8]; 135 | if inv(J) <=0, disp(' error: negative Jacobian in element'); end 136 | % dN = inv(J)*R; 137 | dN = J\R; 138 | 139 | Bi = [dN(1,1) 0 0 dN(1,2) 0 0 dN(1,3) 0 0 dN(1,4) 0 0 dN(1,5) 0 0 ... 140 | dN(1,6) 0 0 dN(1,7) 0 0 dN(1,8) 0 0; 141 | 0 dN(2,1) 0 0 dN(2,2) 0 0 dN(2,3) 0 0 dN(2,4) 0 0 dN(2,5) 0 0 ... 142 | dN(2,6) 0 0 dN(2,7) 0 0 dN(2,8) 0; 143 | 0 0 dN(3,1) 0 0 dN(3,2) 0 0 dN(3,3) 0 0 dN(3,4) 0 0 dN(3,5) 0 0 ... 144 | dN(3,6) 0 0 dN(3,7) 0 0 dN(3,8); 145 | dN(2,1) dN(1,1) 0 dN(2,2) dN(1,2) 0 dN(2,3) dN(1,3) ... 146 | 0 dN(2,4) dN(1,4) 0 dN(2,5) dN(1,5) 0 dN(2,6) dN(1,6) 0 ... 147 | dN(2,7) dN(1,7) 0 dN(2,8) dN(1,8) 0; 148 | 0 dN(3,1) dN(2,1) 0 dN(3,2) dN(2,2) 0 dN(3,3) dN(2,3) ... 149 | 0 dN(3,4) dN(2,4) 0 dN(3,5) dN(2,5) 0 dN(3,6) dN(2,6) 0 ... 150 | dN(3,7) dN(2,7) 0 dN(3,8) dN(2,8); 151 | dN(3,1) 0 dN(1,1) dN(3,2) 0 dN(1,2) dN(3,3) 0 dN(1,3) ... 152 | dN(3,4) 0 dN(1,4) dN(3,5) 0 dN(1,5) dN(3,6) 0 dN(1,6) ... 153 | dN(3,7) 0 dN(1,7) dN(3,8) 0 dN(1,8)]; 154 | 155 | B(1:6,1:24,i+1) = Bi; 156 | end 157 | 158 | -------------------------------------------------------------------------------- /UCOpt3D/UCOpt3D.m: -------------------------------------------------------------------------------- 1 | function UCOpt3D(lx,ly,lz,nelx,nely,nelz,nlx,nly,nlz,volfrac,penal,rmin,ft) 2 | % USER-DEFINED LOOP PARAMETERS 3 | maxloop = 200; % Maximum number of iterations 4 | tolx = 0.01; % Termination criterion 5 | displayflag = 1; % Display structure flag 6 | % USER-DEFINED MATERIAL PROPERTIES 7 | E0 = 1; % Young's modulus of solid material 8 | Emin = 1e-9; % Young's modulus of void-like material 9 | nu = 0.3; % Poisson's ratio 10 | % USER-DEFINED LOAD DOFs 11 | il = nelx; jl = 0; kl = 0:nelz; % Coordinates 12 | loadnid = kl*(nelx+1)*(nely+1)+il*(nely+1)+(nely+1-jl); % Node IDs 13 | loaddof = 3*loadnid(:) - 1; % DOFs 14 | % USER-DEFINED SUPPORT FIXED DOFs 15 | [jf,kf] = meshgrid(1:nely+1,1:nelz+1); % Coordinates 16 | fixednid = (kf-1)*(nely+1)*(nelx+1)+jf; % Node IDs 17 | fixeddof = [3*fixednid(:); 3*fixednid(:)-1; 3*fixednid(:)-2]; % DOFs 18 | % PREPARE FINITE ELEMENT ANALYSIS 19 | nele = nelx*nely*nelz; 20 | ndof = 3*(nelx+1)*(nely+1)*(nelz+1); 21 | F = sparse(loaddof,1,-1,ndof,1); 22 | U = zeros(ndof,1); 23 | freedofs = setdiff(1:ndof,fixeddof); 24 | % KE = lk_H8(nu); 25 | h1 = hexahedron(lx/nelx/2,ly/nely/2,lz/nelz/2); 26 | h2 = hexahedron(0.000001*lx/nlx/2,0.000001*ly/nly/2,0.000001*lz/nlz/2); 27 | nodegrd = reshape(1:(nely+1)*(nelx+1),nely+1,nelx+1); 28 | nodeids = reshape(nodegrd(1:end-1,1:end-1),nely*nelx,1); 29 | nodeidz = 0:(nely+1)*(nelx+1):(nelz-1)*(nely+1)*(nelx+1); 30 | nodeids = repmat(nodeids,size(nodeidz))+repmat(nodeidz,size(nodeids)); 31 | edofVec = 3*nodeids(:)+1; 32 | edofMat = repmat(edofVec,1,24)+ ... 33 | repmat([0 1 2 3*nely + [3 4 5 0 1 2] -3 -2 -1 ... 34 | 3*(nely+1)*(nelx+1)+[0 1 2 3*nely + [3 4 5 0 1 2] -3 -2 -1]],nele,1); 35 | iK = kron(edofMat,ones(24,1))'; 36 | jK = kron(edofMat,ones(1,24))'; 37 | % PREPARE FILTER 38 | iH = ones(nlx*nly*nlz*(2*(ceil(rmin)-1)+1)^2,1); 39 | jH = ones(size(iH)); 40 | sH = zeros(size(iH)); 41 | k = 0; 42 | for k1 = 1:nlz 43 | for i1 = 1:nlx 44 | for j1 = 1:nly 45 | e1 = (k1-1)*nlx*nly + (i1-1)*nly+j1; 46 | for k2 = max(k1-(ceil(rmin)-1),1):min(k1+(ceil(rmin)-1),nlz) 47 | for i2 = max(i1-(ceil(rmin)-1),1):min(i1+(ceil(rmin)-1),nlx) 48 | for j2 = max(j1-(ceil(rmin)-1),1):min(j1+(ceil(rmin)-1),nly) 49 | e2 = (k2-1)*nlx*nly + (i2-1)*nly+j2; 50 | k = k+1; 51 | iH(k) = e1; 52 | jH(k) = e2; 53 | sH(k) = max(0,rmin-sqrt((i1-i2)^2+(j1-j2)^2+(k1-k2)^2)); 54 | end 55 | end 56 | end 57 | end 58 | end 59 | end 60 | H = sparse(iH,jH,sH); 61 | Hs = sum(H,2); 62 | % INITIALIZE ITERATION 63 | x = repmat(ones,[nly,nlx,nlz]); 64 | for i=1:nly 65 | for j=1:nlx 66 | for k=1:nlz 67 | if sqrt((i-nlx/2-0.5)^2+(j-nly/2-0.5)^2+(k-nlz/2-0.5)^2) < min(min(nlx,nly),nlz)/3 68 | x(i,j,k) = 0; 69 | end 70 | end 71 | end 72 | end 73 | xPhys = x; 74 | loop = 0; 75 | change = 1; 76 | % START ITERATION 77 | while change > tolx && loop < maxloop 78 | loop = loop+1; 79 | % INTERPOLATION 80 | [E,dE] = interpolate(x,E0,Emin,penal); 81 | % Homogenization 82 | [CH,DCH] = homo3DY(0.000001*lx,0.000001*ly,0.000001*lz,E,dE,nu,Emin,h2); 83 | % FE-ANALYSIS 84 | KE = h1.elemStiffness(CH); 85 | sK = reshape(KE(:)*ones(1,nely*nelx*nelz),576*nelx*nely*nelz,1); 86 | K = sparse(iK(:),jK(:),sK(:)); K = (K+K')/2; 87 | U(freedofs,:) = K(freedofs,freedofs)\F(freedofs,:); 88 | % OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS 89 | dKe = cellfun(@h1.elemStiffness,DCH,'UniformOutput',false); 90 | f = @(dKE) (reshape(sum((U(edofMat)*dKE).*U(edofMat),2),[nely,nelx,nelz])); 91 | ce = cellfun(f, dKe, 'UniformOutput',false); 92 | c = sum(sum(sum(cell2mat(cellfun(@sum, ce, 'UniformOutput',false))))); 93 | dc = - cell2mat(cellfun(@sum,cellfun(@sum,cellfun(@sum, ce, 'UniformOutput',false),'UniformOutput',false),'UniformOutput',false)); 94 | dv = ones(nly,nlx,nlz); 95 | % FILTERING AND MODIFICATION OF SENSITIVITIES 96 | if ft == 1 97 | dc(:) = H*(x(:).*dc(:))./Hs./max(1e-3,x(:)); 98 | elseif ft == 2 99 | dc(:) = H*(dc(:)./Hs); 100 | dv(:) = H*(dv(:)./Hs); 101 | end 102 | % OPTIMALITY CRITERIA UPDATE 103 | l1 = 0; l2 = 1e9; move = 0.2; 104 | while (l2-l1)/(l1+l2) > 1e-3 105 | lmid = 0.5*(l2+l1); 106 | xnew = max(0,max(x-move,min(1,min(x+move,x.*sqrt(-dc./dv/lmid))))); 107 | if ft == 1 108 | xPhys = xnew; 109 | elseif ft == 2 110 | xPhys(:) = (H*xnew(:))./Hs; 111 | end 112 | if sum(xPhys(:)) > volfrac*nlx*nly*nlz, l1 = lmid; else l2 = lmid; end 113 | end 114 | change = max(abs(xnew(:)-x(:))); 115 | x = xnew; 116 | % PRINT RESULTS 117 | fprintf(' It.:%5i Obj.:%11.4f Vol.:%7.3f ch.:%7.3f\n',loop,c,mean(xPhys(:)),change); 118 | % PLOT DENSITIES 119 | if displayflag, clf; display_3D(xPhys); end 120 | end 121 | clf; display_3D(xPhys); 122 | end 123 | % ===================== AUXILIARY FUNCTIONS =============================== 124 | function [E,dE] = interpolate(x, E0, Emin, penal) 125 | E = Emin + x.^penal * (E0-Emin); 126 | dE = penal * x.^(penal-1) * (E0-Emin); 127 | end 128 | % DISPLAY 3D TOPOLOGY (ISO-VIEW) 129 | function display_3D(rho) 130 | [nely,nelx,nelz] = size(rho); 131 | hx = 1; hy = 1; hz = 1; % User-defined unit element size 132 | face = [1 2 3 4; 2 6 7 3; 4 3 7 8; 1 5 8 4; 1 2 6 5; 5 6 7 8]; 133 | set(gcf,'Name','ISO display','NumberTitle','off'); 134 | for k = 1:nelz 135 | z = (k-1)*hz; 136 | for i = 1:nelx 137 | x = (i-1)*hx; 138 | for j = 1:nely 139 | y = nely*hy - (j-1)*hy; 140 | if (rho(j,i,k) > 0.5) % User-defined display density threshold 141 | vert = [x y z; x y-hx z; x+hx y-hx z; x+hx y z; x y z+hx;x y-hx z+hx; x+hx y-hx z+hx;x+hx y z+hx]; 142 | vert(:,[2 3]) = vert(:,[3 2]); vert(:,2,:) = -vert(:,2,:); 143 | patch('Faces',face,'Vertices',vert,'FaceColor',[0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k))]); 144 | hold on; 145 | end 146 | end 147 | end 148 | end 149 | axis equal; axis tight; axis off; box on; view([30,30]); pause(1e-6); 150 | end 151 | % 152 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 153 | % This Matlab code was modified by G. Kazakis and N.D. Lagaros and was 154 | % based on the top3d.m code written by K. Liu and A. Tovar, 155 | % in the paper "An efficient 3D topology optimization code written in 156 | % Matlab", E. K. Liu and A. Tovar, Struct Multidisc Optim, 2014 157 | % 158 | % The code is intended for educational purposes, extensions can be found in 159 | % the paper "Topology optimization based material design for 3D domains 160 | % using MATLAB" 161 | % 162 | % Disclaimer: 163 | % The authors reserves all rights for the program. 164 | % The code may be distributed and used for educational purposes. 165 | % The authors do not guarantee that the code is free from errors, and 166 | % they shall not be liable in any event caused by the use of the program. 167 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /BESO3D/SBESO3D.m: -------------------------------------------------------------------------------- 1 | % A 169 LINE 3D TOPOLOGY OPITMIZATION CODE BY LIU AND TOVAR (JUL 2013) 2 | function SBESO3D(nelx,nely,nelz,volfrac,penal,rmin,er) 3 | % USER-DEFINED LOOP PARAMETERS 4 | maxloop = 200; % Maximum number of iterations 5 | tolx = 0.01; % Termination criterion 6 | displayflag = 1; % Display structure flag 7 | % USER-DEFINED MATERIAL PROPERTIES 8 | E0 = 1; % Young's modulus of solid material 9 | Emin = 1e-9; % Young's modulus of void-like material 10 | nu = 0.3; % Poisson's ratio 11 | % USER-DEFINED LOAD DOFs 12 | il = nelx; jl = 0; kl = 0:nelz; % Coordinates 13 | loadnid = kl*(nelx+1)*(nely+1)+il*(nely+1)+(nely+1-jl); % Node IDs 14 | loaddof = 3*loadnid(:) - 1; % DOFs 15 | % USER-DEFINED SUPPORT FIXED DOFs 16 | [jf,kf] = meshgrid(1:nely+1,1:nelz+1); % Coordinates 17 | fixednid = (kf-1)*(nely+1)*(nelx+1)+jf; % Node IDs 18 | fixeddof = [3*fixednid(:); 3*fixednid(:)-1; 3*fixednid(:)-2]; % DOFs 19 | % PREPARE FINITE ELEMENT ANALYSIS 20 | nele = nelx*nely*nelz; 21 | ndof = 3*(nelx+1)*(nely+1)*(nelz+1); 22 | F = sparse(loaddof,1,-1,ndof,1); 23 | U = zeros(ndof,1); 24 | freedofs = setdiff(1:ndof,fixeddof); 25 | KE = lk_H8(nu); 26 | nodegrd = reshape(1:(nely+1)*(nelx+1),nely+1,nelx+1); 27 | nodeids = reshape(nodegrd(1:end-1,1:end-1),nely*nelx,1); 28 | nodeidz = 0:(nely+1)*(nelx+1):(nelz-1)*(nely+1)*(nelx+1); 29 | nodeids = repmat(nodeids,size(nodeidz))+repmat(nodeidz,size(nodeids)); 30 | edofVec = 3*nodeids(:)+1; 31 | edofMat = repmat(edofVec,1,24)+ ... 32 | repmat([0 1 2 3*nely + [3 4 5 0 1 2] -3 -2 -1 ... 33 | 3*(nely+1)*(nelx+1)+[0 1 2 3*nely + [3 4 5 0 1 2] -3 -2 -1]],nele,1); 34 | iK = kron(edofMat,ones(24,1))'; 35 | jK = kron(edofMat,ones(1,24))'; 36 | % PREPARE FILTER 37 | iH = ones(nele*(2*(ceil(rmin)-1)+1)^2,1); 38 | jH = ones(size(iH)); 39 | sH = zeros(size(iH)); 40 | k = 0; 41 | for k1 = 1:nelz 42 | for i1 = 1:nelx 43 | for j1 = 1:nely 44 | e1 = (k1-1)*nelx*nely + (i1-1)*nely+j1; 45 | for k2 = max(k1-(ceil(rmin)-1),1):min(k1+(ceil(rmin)-1),nelz) 46 | for i2 = max(i1-(ceil(rmin)-1),1):min(i1+(ceil(rmin)-1),nelx) 47 | for j2 = max(j1-(ceil(rmin)-1),1):min(j1+(ceil(rmin)-1),nely) 48 | e2 = (k2-1)*nelx*nely + (i2-1)*nely+j2; 49 | k = k+1; 50 | iH(k) = e1; 51 | jH(k) = e2; 52 | sH(k) = max(0,rmin-sqrt((i1-i2)^2+(j1-j2)^2+(k1-k2)^2)); 53 | end 54 | end 55 | end 56 | end 57 | end 58 | end 59 | H = sparse(iH,jH,sH); 60 | Hs = sum(H,2); 61 | % INITIALIZE ITERATION 62 | x = ones(nely,nelx,nelz); 63 | vol = 1; 64 | loop = 0; 65 | change = 1; 66 | % START ITERATION 67 | while change > tolx && loop < maxloop 68 | loop = loop+1; 69 | vol = max(vol*(1-er),volfrac); 70 | if loop > 1; olddc = dc; end 71 | % FE-ANALYSIS 72 | sK = KE(:)*(Emin+x(:)'.^penal*(E0-Emin)); 73 | K = sparse(iK(:),jK(:),sK(:)); K = (K+K')/2; 74 | tolit=1e-8; 75 | maxit=8000; 76 | M=diag(diag(K(freedofs,freedofs))); 77 | U(freedofs,:) = pcg(K(freedofs,freedofs),F(freedofs,:),tolit,maxit,M); 78 | %U(freedofs,:) = K(freedofs,freedofs)\F(freedofs,:); 79 | % OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS 80 | ce = reshape(0.5*(sum((U(edofMat)*KE).*U(edofMat),2)),[nely,nelx,nelz]); 81 | c(loop) = sum(sum(sum((Emin+x.^penal*(E0-Emin)).*ce))); 82 | dc = penal*(E0-Emin)*x.^(penal-1).*ce; 83 | %% FILTERING/MODIFICATION OF SENSITIVITIES 84 | dc(:) = H*(dc(:))./Hs; 85 | if loop > 1; dc = (dc+olddc)/2.; end 86 | % BESO DESIGN UPDATE 87 | l1 = min(min(min(dc))); l2 = max(max(max(dc))); 88 | while (l2-l1)/(l1+l2) > 1e-3 89 | lmid = 0.5*(l2+l1); 90 | x = max(0.001,sign(dc-lmid)); 91 | if sum(x(:)) > vol*nele, l1 = lmid; else l2 = lmid; end 92 | end 93 | if loop > 10 94 | change = abs(sum(c(loop-9:loop-5))-sum(c(loop-4:loop)))/sum(c(loop-4:loop)); 95 | end 96 | % PRINT RESULTS 97 | fprintf(' It.:%5i Obj.:%11.4f Vol.:%7.3f ch.:%7.3f\n',loop,c(loop),mean(x(:)),change); 98 | % PLOT DENSITIES 99 | if displayflag, clf; display_3D(x); end 100 | end 101 | clf; display_3D(x); 102 | end 103 | % ===================== AUXILIARY FUNCTIONS =============================== 104 | % GENERATE ELEMENT STIFFNESS MATRIX 105 | function [KE] = lk_H8(nu) 106 | A = [32 6 -8 6 -6 4 3 -6 -10 3 -3 -3 -4 -8; 107 | -48 0 0 -24 24 0 0 0 12 -12 0 12 12 12]; 108 | k = 1/72*A'*[1; nu]; 109 | % GENERATE SIX SUB-MATRICES AND THEN GET KE MATRIX 110 | K1 = [k(1) k(2) k(2) k(3) k(5) k(5); 111 | k(2) k(1) k(2) k(4) k(6) k(7); 112 | k(2) k(2) k(1) k(4) k(7) k(6); 113 | k(3) k(4) k(4) k(1) k(8) k(8); 114 | k(5) k(6) k(7) k(8) k(1) k(2); 115 | k(5) k(7) k(6) k(8) k(2) k(1)]; 116 | K2 = [k(9) k(8) k(12) k(6) k(4) k(7); 117 | k(8) k(9) k(12) k(5) k(3) k(5); 118 | k(10) k(10) k(13) k(7) k(4) k(6); 119 | k(6) k(5) k(11) k(9) k(2) k(10); 120 | k(4) k(3) k(5) k(2) k(9) k(12) 121 | k(11) k(4) k(6) k(12) k(10) k(13)]; 122 | K3 = [k(6) k(7) k(4) k(9) k(12) k(8); 123 | k(7) k(6) k(4) k(10) k(13) k(10); 124 | k(5) k(5) k(3) k(8) k(12) k(9); 125 | k(9) k(10) k(2) k(6) k(11) k(5); 126 | k(12) k(13) k(10) k(11) k(6) k(4); 127 | k(2) k(12) k(9) k(4) k(5) k(3)]; 128 | K4 = [k(14) k(11) k(11) k(13) k(10) k(10); 129 | k(11) k(14) k(11) k(12) k(9) k(8); 130 | k(11) k(11) k(14) k(12) k(8) k(9); 131 | k(13) k(12) k(12) k(14) k(7) k(7); 132 | k(10) k(9) k(8) k(7) k(14) k(11); 133 | k(10) k(8) k(9) k(7) k(11) k(14)]; 134 | K5 = [k(1) k(2) k(8) k(3) k(5) k(4); 135 | k(2) k(1) k(8) k(4) k(6) k(11); 136 | k(8) k(8) k(1) k(5) k(11) k(6); 137 | k(3) k(4) k(5) k(1) k(8) k(2); 138 | k(5) k(6) k(11) k(8) k(1) k(8); 139 | k(4) k(11) k(6) k(2) k(8) k(1)]; 140 | K6 = [k(14) k(11) k(7) k(13) k(10) k(12); 141 | k(11) k(14) k(7) k(12) k(9) k(2); 142 | k(7) k(7) k(14) k(10) k(2) k(9); 143 | k(13) k(12) k(10) k(14) k(7) k(11); 144 | k(10) k(9) k(2) k(7) k(14) k(7); 145 | k(12) k(2) k(9) k(11) k(7) k(14)]; 146 | KE = 1/((nu+1)*(1-2*nu))*... 147 | [ K1 K2 K3 K4; 148 | K2' K5 K6 K3'; 149 | K3' K6 K5' K2'; 150 | K4 K3 K2 K1']; 151 | end 152 | % DISPLAY 3D TOPOLOGY (ISO-VIEW) 153 | function display_3D(rho) 154 | [nely,nelx,nelz] = size(rho); 155 | hx = 1; hy = 1; hz = 1; % User-defined unit element size 156 | face = [1 2 3 4; 2 6 7 3; 4 3 7 8; 1 5 8 4; 1 2 6 5; 5 6 7 8]; 157 | set(gcf,'Name','ISO display','NumberTitle','off'); 158 | for k = 1:nelz 159 | z = (k-1)*hz; 160 | for i = 1:nelx 161 | x = (i-1)*hx; 162 | for j = 1:nely 163 | y = nely*hy - (j-1)*hy; 164 | if (rho(j,i,k) > 0.5) % User-defined display density threshold 165 | vert = [x y z; x y-hx z; x+hx y-hx z; x+hx y z; x y z+hx;x y-hx z+hx; x+hx y-hx z+hx;x+hx y z+hx]; 166 | vert(:,[2 3]) = vert(:,[3 2]); vert(:,2,:) = -vert(:,2,:); 167 | patch('Faces',face,'Vertices',vert,'FaceColor',[0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k))]); 168 | hold on; 169 | end 170 | end 171 | end 172 | end 173 | axis equal; axis tight; axis off; box on; view([30,30]); pause(1e-6); 174 | end 175 | % ========================================================================= 176 | % === This code was written by K Liu and A Tovar, Dept. of Mechanical === 177 | % === Engineering, Indiana University-Purdue University Indianapolis, === 178 | % === Indiana, United States of America === 179 | % === ----------------------------------------------------------------- === 180 | % === Please send your suggestions and comments to: kailiu@iupui.edu === 181 | % === ----------------------------------------------------------------- === 182 | % === The code is intended for educational purposes, and the details === 183 | % === and extensions can be found in the paper: === 184 | % === '' '' === 185 | % === ----------------------------------------------------------------- === 186 | % === The code as well as an uncorrected version of the paper can be === 187 | % === downloaded from the website: http://top3dapp.com === 188 | % === ----------------------------------------------------------------- === 189 | % === Disclaimer: === 190 | % === The authors reserves all rights for the program. === 191 | % === The code may be distributed and used for educational purposes. === 192 | % === The authors do not guarantee that the code is free from errors, and = 193 | % === they shall not be liable in any event caused by the use of the code.= 194 | % ========================================================================= -------------------------------------------------------------------------------- /Level set 3D/levelset3D.m: -------------------------------------------------------------------------------- 1 | % A 169 LINE 3D TOPOLOGY OPITMIZATION CODE BY LIU AND TOVAR (JUL 2013) 2 | function levelset3D(nelx,nely,nelz,volfrac,stepLength,numReinit,topWeight) 3 | % USER-DEFINED LOOP PARAMETERS 4 | maxloop = 200; % Maximum number of iterations 5 | displayflag = 1; % Display structure flag 6 | % USER-DEFINED MATERIAL PROPERTIES 7 | E0 = 1; % Young's modulus of solid material 8 | Emin = 1e-9; % Young's modulus of void-like material 9 | nu = 0.3; % Poisson's ratio 10 | % USER-DEFINED LOAD DOFs 11 | il = nelx; jl = 0; kl = 0:nelz; % Coordinates 12 | loadnid = kl*(nelx+1)*(nely+1)+il*(nely+1)+(nely+1-jl); % Node IDs 13 | loaddof = 3*loadnid(:) - 1; % DOFs 14 | % USER-DEFINED SUPPORT FIXED DOFs 15 | [jf,kf] = meshgrid(1:nely+1,1:nelz+1); % Coordinates 16 | fixednid = (kf-1)*(nely+1)*(nelx+1)+jf; % Node IDs 17 | fixeddof = [3*fixednid(:); 3*fixednid(:)-1; 3*fixednid(:)-2]; % DOFs 18 | % PREPARE FINITE ELEMENT ANALYSIS 19 | nele = nelx*nely*nelz; 20 | ndof = 3*(nelx+1)*(nely+1)*(nelz+1); 21 | F = sparse(loaddof,1,-1,ndof,1); 22 | U = zeros(ndof,1); 23 | freedofs = setdiff(1:ndof,fixeddof); 24 | % KE 25 | KE = lk_H8(nu); 26 | % KTr 27 | dx = 1; dy = 1; dz = 1; 28 | [KTr] = D3_LB(dx, dy, dz, nu); 29 | % lambda & mu 30 | lambda = E0*nu/((1+nu)*(1-2*nu)); 31 | mu = E0/(2*(1+nu)); 32 | %%%%%%%%%%%%%%%%%%% 33 | nodegrd = reshape(1:(nely+1)*(nelx+1),nely+1,nelx+1); 34 | nodeids = reshape(nodegrd(1:end-1,1:end-1),nely*nelx,1); 35 | nodeidz = 0:(nely+1)*(nelx+1):(nelz-1)*(nely+1)*(nelx+1); 36 | nodeids = repmat(nodeids,size(nodeidz))+repmat(nodeidz,size(nodeids)); 37 | edofVec = 3*nodeids(:)+1; 38 | edofMat = repmat(edofVec,1,24)+ ... 39 | repmat([0 1 2 3*nely + [3 4 5 0 1 2] -3 -2 -1 ... 40 | 3*(nely+1)*(nelx+1)+[0 1 2 3*nely + [3 4 5 0 1 2] -3 -2 -1]],nele,1); 41 | iK = kron(edofMat,ones(24,1))'; 42 | jK = kron(edofMat,ones(1,24))'; 43 | % INITIALIZE ITERATION 44 | x = ones(nely,nelx,nelz); 45 | [lsf] = reinit(x); 46 | loop = 0; 47 | % START ITERATION 48 | while loop < maxloop 49 | loop = loop+1; 50 | % FE-ANALYSIS 51 | sK = KE(:)*(Emin+x(:)'*(E0-Emin)); 52 | K = sparse(iK(:),jK(:),sK(:)); K = (K+K')/2; 53 | tolit=1e-8; 54 | maxit=8000; 55 | M=diag(diag(K(freedofs,freedofs))); 56 | U(freedofs,:) = pcg(K(freedofs,freedofs),F(freedofs,:),tolit,maxit,M); 57 | %U(freedofs,:) = K(freedofs,freedofs)\F(freedofs,:); 58 | % Current Volume 59 | volCurr = sum(x(:))/(nelx*nely*nelz); 60 | % Set augmented Lagrangian parameters 61 | if loop == 1 62 | la = -0.01; La = 1000; alpha = 0.9; 63 | else 64 | la = la - 1/La * (volCurr - volfrac); La= alpha * La; 65 | end 66 | % OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS 67 | ce = reshape(sum((U(edofMat)*KE).*U(edofMat),2),[nely,nelx,nelz]); 68 | ge = reshape(sum((U(edofMat)*KTr).*U(edofMat),2),[nely,nelx,nelz]); 69 | c(loop) = sum(sum(sum((Emin+x*(E0-Emin)).*ce))); 70 | dc = -((E0-Emin)*x+Emin).*ce - la + 1/La*(volCurr-volfrac); 71 | dg = x.*(pi*(lambda+2*mu)/mu/(9*lambda+14*mu)*(20*mu*ce+(3*lambda-2*mu)*ge))... 72 | + pi*(la - 1/La*(volCurr-volfrac)); 73 | % Design update 74 | [x,lsf] = updateStep(lsf,dc,dg,stepLength,topWeight); 75 | % Reinitialize level-set function 76 | if ~mod(loop,numReinit) 77 | [lsf] = reinit(x); 78 | end 79 | % PRINT RESULTS 80 | fprintf(' It.:%5i Obj.:%11.4f Vol.:%7.3f\n',loop,c(loop),mean(x(:))); 81 | % PLOT DENSITIES 82 | if displayflag, clf; display_3D(x); end 83 | end 84 | clf; display_3D(x); 85 | end 86 | % ===================== AUXILIARY FUNCTIONS =============================== 87 | % GENERATE ELEMENT STIFFNESS MATRIX 88 | function [KE] = lk_H8(nu) 89 | A = [32 6 -8 6 -6 4 3 -6 -10 3 -3 -3 -4 -8; 90 | -48 0 0 -24 24 0 0 0 12 -12 0 12 12 12]; 91 | k = 1/72*A'*[1; nu]; 92 | % GENERATE SIX SUB-MATRICES AND THEN GET KE MATRIX 93 | K1 = [k(1) k(2) k(2) k(3) k(5) k(5); 94 | k(2) k(1) k(2) k(4) k(6) k(7); 95 | k(2) k(2) k(1) k(4) k(7) k(6); 96 | k(3) k(4) k(4) k(1) k(8) k(8); 97 | k(5) k(6) k(7) k(8) k(1) k(2); 98 | k(5) k(7) k(6) k(8) k(2) k(1)]; 99 | K2 = [k(9) k(8) k(12) k(6) k(4) k(7); 100 | k(8) k(9) k(12) k(5) k(3) k(5); 101 | k(10) k(10) k(13) k(7) k(4) k(6); 102 | k(6) k(5) k(11) k(9) k(2) k(10); 103 | k(4) k(3) k(5) k(2) k(9) k(12) 104 | k(11) k(4) k(6) k(12) k(10) k(13)]; 105 | K3 = [k(6) k(7) k(4) k(9) k(12) k(8); 106 | k(7) k(6) k(4) k(10) k(13) k(10); 107 | k(5) k(5) k(3) k(8) k(12) k(9); 108 | k(9) k(10) k(2) k(6) k(11) k(5); 109 | k(12) k(13) k(10) k(11) k(6) k(4); 110 | k(2) k(12) k(9) k(4) k(5) k(3)]; 111 | K4 = [k(14) k(11) k(11) k(13) k(10) k(10); 112 | k(11) k(14) k(11) k(12) k(9) k(8); 113 | k(11) k(11) k(14) k(12) k(8) k(9); 114 | k(13) k(12) k(12) k(14) k(7) k(7); 115 | k(10) k(9) k(8) k(7) k(14) k(11); 116 | k(10) k(8) k(9) k(7) k(11) k(14)]; 117 | K5 = [k(1) k(2) k(8) k(3) k(5) k(4); 118 | k(2) k(1) k(8) k(4) k(6) k(11); 119 | k(8) k(8) k(1) k(5) k(11) k(6); 120 | k(3) k(4) k(5) k(1) k(8) k(2); 121 | k(5) k(6) k(11) k(8) k(1) k(8); 122 | k(4) k(11) k(6) k(2) k(8) k(1)]; 123 | K6 = [k(14) k(11) k(7) k(13) k(10) k(12); 124 | k(11) k(14) k(7) k(12) k(9) k(2); 125 | k(7) k(7) k(14) k(10) k(2) k(9); 126 | k(13) k(12) k(10) k(14) k(7) k(11); 127 | k(10) k(9) k(2) k(7) k(14) k(7); 128 | k(12) k(2) k(9) k(11) k(7) k(14)]; 129 | KE = 1/((nu+1)*(1-2*nu))*... 130 | [ K1 K2 K3 K4; 131 | K2' K5 K6 K3'; 132 | K3' K6 K5' K2'; 133 | K4 K3 K2 K1']; 134 | end 135 | % DISPLAY 3D TOPOLOGY (ISO-VIEW) 136 | function display_3D(rho) 137 | [nely,nelx,nelz] = size(rho); 138 | hx = 1; hy = 1; hz = 1; % User-defined unit element size 139 | face = [1 2 3 4; 2 6 7 3; 4 3 7 8; 1 5 8 4; 1 2 6 5; 5 6 7 8]; 140 | set(gcf,'Name','ISO display','NumberTitle','off'); 141 | for k = 1:nelz 142 | z = (k-1)*hz; 143 | for i = 1:nelx 144 | x = (i-1)*hx; 145 | for j = 1:nely 146 | y = nely*hy - (j-1)*hy; 147 | if (rho(j,i,k) > 0.5) % User-defined display density threshold 148 | vert = [x y z; x y-hx z; x+hx y-hx z; x+hx y z; x y z+hx;x y-hx z+hx; x+hx y-hx z+hx;x+hx y z+hx]; 149 | vert(:,[2 3]) = vert(:,[3 2]); vert(:,2,:) = -vert(:,2,:); 150 | patch('Faces',face,'Vertices',vert,'FaceColor',[0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k))]); 151 | hold on; 152 | end 153 | end 154 | end 155 | end 156 | axis equal; axis tight; axis off; box on; view([30,30]); pause(1e-6); 157 | end 158 | 159 | %%---- REINITIALIZATION OF LEVEL-SETFUNCTION ---- 160 | function [lsf] = reinit(struc) 161 | strucFull = zeros(size(struc)+2); 162 | strucFull(2:end-1,2:end-1,2:end-1) = struc; 163 | % Use "bwdist" (Image Processing Toolbox) 164 | lsf = (~strucFull).*(bwdist(strucFull)-0.5) - strucFull.*(bwdist(strucFull-1)-0.5); 165 | end 166 | % 167 | %%----- DESIGN UPDATE ---- 168 | function [struc,lsf] = updateStep(lsf,shapeSens,topSens,stepLength,topWeight) 169 | % Smooth the sensitivities 170 | [shapeSens] = convn(padarray(shapeSens,[1,1,1],'replicate'),ConvolutionN(),'valid'); 171 | [topSens] = convn(padarray(topSens,[1,1,1],'replicate'),ConvolutionN(),'valid'); 172 | % Load bearing pixels must remain solid -Bridge: 173 | % edw nomizw einai karfota gia to paradeigma pou exei. 174 | shapeSens(1:end,1,1:end) = 0; 175 | shapeSens(end,end,1:end) = 0; 176 | topSens(1:end,1,1:end) = 0; 177 | topSens(end,end,1:end) = 0; 178 | % Design update via evolution 179 | [struc,lsf] = evolve(-shapeSens,topSens.*(lsf(2:end-1,2:end-1,2:end-1)<0),lsf,stepLength,topWeight); 180 | end 181 | % 182 | %%---- EVOLUTION OF LEVEL-SET FUNCTION---- 183 | function [struc,lsf] = evolve(v,g,lsf,stepLength,w) 184 | % Extend sensitivites using a zero border 185 | vFull = zeros(size(v)+2); vFull(2:end-1,2:end-1,2:end-1) = v; 186 | gFull = zeros(size(g)+2); gFull(2:end-1,2:end-1,2:end-1) = g; 187 | % Choose time step for evolution based onCFL value 188 | dt = 0.1/max(abs(v(:))); 189 | % Evolve for total time stepLength * CFLvalue: 190 | for i = 1:(10*stepLength) 191 | % Calculate derivatives on the grid 192 | dpx = circshift(lsf,[0,-1,0])-lsf; 193 | dmx = lsf - circshift(lsf,[0,1,0]); 194 | dpy = circshift(lsf,[-1,0,0]) - lsf; 195 | dmy = lsf - circshift(lsf,[1,0,0]); 196 | dpz = circshift(lsf,[0,0,-1]) - lsf; 197 | dmz = lsf - circshift(lsf,[0,0,1]); 198 | % Update level set function using anupwind scheme 199 | lsf = lsf - dt * min(vFull,0).* ... 200 | sqrt( min(dmx,0).^2+max(dpx,0).^2+min(dmy,0).^2+max(dpy,0).^2+min(dmz,0).^2+max(dpz,0).^2 ) ... 201 | - dt * max(vFull,0) .*... 202 | sqrt( max(dmx,0).^2+min(dpx,0).^2+max(dmy,0).^2+min(dpy,0).^2+max(dmz,0).^2+min(dpz,0).^2 )... 203 | - w*dt*gFull; 204 | end 205 | % New structure obtained from lsf 206 | strucFull = (lsf<0); struc = strucFull(2:end-1,2:end-1,2:end-1); 207 | end 208 | % 209 | function matric = ConvolutionN() 210 | matric = zeros(3,3,3); 211 | matric(:,:,1) = 1/6*[0 1 0; 1 2 1;0 1 0]; 212 | matric(:,:,2) = 1/6*[0 1 0; 1 2 1;0 1 0]; 213 | matric(:,:,3) = 1/6*[0 1 0; 1 2 1;0 1 0]; 214 | end -------------------------------------------------------------------------------- /SIMP_3D MMA/top3dmma.m: -------------------------------------------------------------------------------- 1 | function top3dmma(nelx,nely,nelz,volfrac,penal,rmin,type) 2 | % USER-DEFINED LOOP PARAMETERS 3 | maxloop = 200; % Maximum number of iterations 4 | tolx = 0.01; % Termination criterion 5 | displayflag = 1; % Display structure flag 6 | % USER-DEFINED MATERIAL PROPERTIES 7 | E0 = 1; % Young's modulus of solid material 8 | Emin = 1e-9; % Young's modulus of void-like material 9 | nu = 0.3; % Poisson's ratio 10 | % USER-DEFINED LOAD DOFs 11 | il = nelx; jl = 0; kl = 0:nelz; % Coordinates 12 | loadnid = kl*(nelx+1)*(nely+1)+il*(nely+1)+(nely+1-jl); % Node IDs 13 | loaddof = 3*loadnid(:) - 1; % DOFs 14 | % USER-DEFINED SUPPORT FIXED DOFs 15 | [jf,kf] = meshgrid(1:nely+1,1:nelz+1); % Coordinates 16 | fixednid = (kf-1)*(nely+1)*(nelx+1)+jf; % Node IDs 17 | fixeddof = [3*fixednid(:); 3*fixednid(:)-1; 3*fixednid(:)-2]; % DOFs 18 | % PREPARE FINITE ELEMENT ANALYSIS 19 | nele = nelx*nely*nelz; 20 | ndof = 3*(nelx+1)*(nely+1)*(nelz+1); 21 | F = sparse(loaddof,1,-1,ndof,1); 22 | U = zeros(ndof,1); 23 | freedofs = setdiff(1:ndof,fixeddof); 24 | KE = lk_H8(nu); 25 | nodegrd = reshape(1:(nely+1)*(nelx+1),nely+1,nelx+1); 26 | nodeids = reshape(nodegrd(1:end-1,1:end-1),nely*nelx,1); 27 | nodeidz = 0:(nely+1)*(nelx+1):(nelz-1)*(nely+1)*(nelx+1); 28 | nodeids = repmat(nodeids,size(nodeidz))+repmat(nodeidz,size(nodeids)); 29 | edofVec = 3*nodeids(:)+1; 30 | edofMat = repmat(edofVec,1,24)+ ... 31 | repmat([0 1 2 3*nely + [3 4 5 0 1 2] -3 -2 -1 ... 32 | 3*(nely+1)*(nelx+1)+[0 1 2 3*nely + [3 4 5 0 1 2] -3 -2 -1]],nele,1); 33 | iK = kron(edofMat,ones(24,1))'; 34 | jK = kron(edofMat,ones(1,24))'; 35 | % PREPARE FILTER 36 | iH = ones(nele*(2*(ceil(rmin)-1)+1)^2,1); 37 | jH = ones(size(iH)); 38 | sH = zeros(size(iH)); 39 | k = 0; 40 | for k1 = 1:nelz 41 | for i1 = 1:nelx 42 | for j1 = 1:nely 43 | e1 = (k1-1)*nelx*nely + (i1-1)*nely+j1; 44 | for k2 = max(k1-(ceil(rmin)-1),1):min(k1+(ceil(rmin)-1),nelz) 45 | for i2 = max(i1-(ceil(rmin)-1),1):min(i1+(ceil(rmin)-1),nelx) 46 | for j2 = max(j1-(ceil(rmin)-1),1):min(j1+(ceil(rmin)-1),nely) 47 | e2 = (k2-1)*nelx*nely + (i2-1)*nely+j2; 48 | k = k+1; 49 | iH(k) = e1; 50 | jH(k) = e2; 51 | sH(k) = max(0,rmin-sqrt((i1-i2)^2+(j1-j2)^2+(k1-k2)^2)); 52 | end 53 | end 54 | end 55 | end 56 | end 57 | end 58 | H = sparse(iH,jH,sH); 59 | Hs = sum(H,2); 60 | % INITIALIZE ITERATION 61 | x = repmat(volfrac,[nely,nelx,nelz]); 62 | xold1 = x; 63 | xold2 = x; 64 | xPhys = x; 65 | loop = 0; 66 | change = 1; 67 | Lm = zeros(nely,nelx); 68 | Um = zeros(nely,nelx); 69 | % START ITERATION 70 | while change > tolx && loop < maxloop 71 | loop = loop+1; 72 | % FE-ANALYSIS 73 | sK = KE(:)*(Emin+xPhys(:)'.^penal*(E0-Emin)); 74 | K = sparse(iK(:),jK(:),sK(:)); K = (K+K')/2; 75 | tolit=1e-8; 76 | maxit=8000; 77 | M=diag(diag(K(freedofs,freedofs))); 78 | U(freedofs,:) = pcg(K(freedofs,freedofs),F(freedofs,:),tolit,maxit,M); 79 | %U(freedofs,:) = K(freedofs,freedofs)\F(freedofs,:); 80 | % OBJECTIVE FUNCTION AND SENSITIVITY ANALYSIS 81 | ce = reshape(sum((U(edofMat)*KE).*U(edofMat),2),[nely,nelx,nelz]); 82 | c = sum(sum(sum((Emin+xPhys.^penal*(E0-Emin)).*ce))); 83 | dc = -penal*(E0-Emin)*xPhys.^(penal-1).*ce; 84 | dv = ones(nely,nelx,nelz); 85 | % FILTERING AND MODIFICATION OF SENSITIVITIES 86 | dc(:) = H*(dc(:)./Hs); 87 | dv(:) = H*(dv(:)./Hs); 88 | %% Moving Asymptotes 89 | [Lm,Um,a,b] = updateMovingAsymptotes(loop,x,xold1,xold2,Lm,Um,type); 90 | % METHOD OF MOVING ASYMPTOTES 91 | l1 = 0; l2 = 1e9; move = 0.2; 92 | while (l2-l1)/(l1+l2) > 1e-3 93 | lmid = 0.5*(l2+l1); 94 | q = -(x - Lm).^2.*dc; 95 | xnew = max(0,max(x-move,max(a,min(1,min(x+move,min(b,real(sqrt(q./dv/lmid)+Lm))))))); 96 | xPhys(:) = (H*xnew(:))./Hs; 97 | if sum(xPhys(:)) > volfrac*nele, l1 = lmid; else l2 = lmid; end 98 | end 99 | change = max(abs(xnew(:)-x(:))); 100 | % save xold1 and xold2 101 | xold2 = xold1; 102 | xold1 = x; 103 | x = xnew; 104 | % PRINT RESULTS 105 | fprintf(' It.:%5i Obj.:%11.4f Vol.:%7.3f ch.:%7.3f\n',loop,c,mean(xPhys(:)),change); 106 | % PLOT DENSITIES 107 | if displayflag, clf; display_3D(xPhys); end 108 | end 109 | clf; display_3D(xPhys); 110 | end 111 | % ===================== AUXILIARY FUNCTIONS =============================== 112 | % GENERATE ELEMENT STIFFNESS MATRIX 113 | function [KE] = lk_H8(nu) 114 | A = [32 6 -8 6 -6 4 3 -6 -10 3 -3 -3 -4 -8; 115 | -48 0 0 -24 24 0 0 0 12 -12 0 12 12 12]; 116 | k = 1/72*A'*[1; nu]; 117 | % GENERATE SIX SUB-MATRICES AND THEN GET KE MATRIX 118 | K1 = [k(1) k(2) k(2) k(3) k(5) k(5); 119 | k(2) k(1) k(2) k(4) k(6) k(7); 120 | k(2) k(2) k(1) k(4) k(7) k(6); 121 | k(3) k(4) k(4) k(1) k(8) k(8); 122 | k(5) k(6) k(7) k(8) k(1) k(2); 123 | k(5) k(7) k(6) k(8) k(2) k(1)]; 124 | K2 = [k(9) k(8) k(12) k(6) k(4) k(7); 125 | k(8) k(9) k(12) k(5) k(3) k(5); 126 | k(10) k(10) k(13) k(7) k(4) k(6); 127 | k(6) k(5) k(11) k(9) k(2) k(10); 128 | k(4) k(3) k(5) k(2) k(9) k(12) 129 | k(11) k(4) k(6) k(12) k(10) k(13)]; 130 | K3 = [k(6) k(7) k(4) k(9) k(12) k(8); 131 | k(7) k(6) k(4) k(10) k(13) k(10); 132 | k(5) k(5) k(3) k(8) k(12) k(9); 133 | k(9) k(10) k(2) k(6) k(11) k(5); 134 | k(12) k(13) k(10) k(11) k(6) k(4); 135 | k(2) k(12) k(9) k(4) k(5) k(3)]; 136 | K4 = [k(14) k(11) k(11) k(13) k(10) k(10); 137 | k(11) k(14) k(11) k(12) k(9) k(8); 138 | k(11) k(11) k(14) k(12) k(8) k(9); 139 | k(13) k(12) k(12) k(14) k(7) k(7); 140 | k(10) k(9) k(8) k(7) k(14) k(11); 141 | k(10) k(8) k(9) k(7) k(11) k(14)]; 142 | K5 = [k(1) k(2) k(8) k(3) k(5) k(4); 143 | k(2) k(1) k(8) k(4) k(6) k(11); 144 | k(8) k(8) k(1) k(5) k(11) k(6); 145 | k(3) k(4) k(5) k(1) k(8) k(2); 146 | k(5) k(6) k(11) k(8) k(1) k(8); 147 | k(4) k(11) k(6) k(2) k(8) k(1)]; 148 | K6 = [k(14) k(11) k(7) k(13) k(10) k(12); 149 | k(11) k(14) k(7) k(12) k(9) k(2); 150 | k(7) k(7) k(14) k(10) k(2) k(9); 151 | k(13) k(12) k(10) k(14) k(7) k(11); 152 | k(10) k(9) k(2) k(7) k(14) k(7); 153 | k(12) k(2) k(9) k(11) k(7) k(14)]; 154 | KE = 1/((nu+1)*(1-2*nu))*... 155 | [ K1 K2 K3 K4; 156 | K2' K5 K6 K3'; 157 | K3' K6 K5' K2'; 158 | K4 K3 K2 K1']; 159 | end 160 | % DISPLAY 3D TOPOLOGY (ISO-VIEW) 161 | function display_3D(rho) 162 | [nely,nelx,nelz] = size(rho); 163 | hx = 1; hy = 1; hz = 1; % User-defined unit element size 164 | face = [1 2 3 4; 2 6 7 3; 4 3 7 8; 1 5 8 4; 1 2 6 5; 5 6 7 8]; 165 | set(gcf,'Name','ISO display','NumberTitle','off'); 166 | for k = 1:nelz 167 | z = (k-1)*hz; 168 | for i = 1:nelx 169 | x = (i-1)*hx; 170 | for j = 1:nely 171 | y = nely*hy - (j-1)*hy; 172 | if (rho(j,i,k) > 0.5) % User-defined display density threshold 173 | vert = [x y z; x y-hx z; x+hx y-hx z; x+hx y z; x y z+hx;x y-hx z+hx; x+hx y-hx z+hx;x+hx y z+hx]; 174 | vert(:,[2 3]) = vert(:,[3 2]); vert(:,2,:) = -vert(:,2,:); 175 | patch('Faces',face,'Vertices',vert,'FaceColor',[0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k)),0.2+0.8*(1-rho(j,i,k))]); 176 | hold on; 177 | end 178 | end 179 | end 180 | end 181 | axis equal; axis tight; axis off; box on; view([30,30]); pause(1e-6); 182 | end 183 | function [Lm,Um,a,b] = updateMovingAsymptotes(loop,x,xold1,xold2,Lm,Um,w) 184 | switch (w) 185 | case 'Fixed' 186 | s0 = 0.1; 187 | Lm = x - s0; 188 | Um = x + s0; 189 | a = 0.9*Lm + 0.1*x; 190 | b = 0.9*Um + 0.1*x; 191 | case 'Svanberg' 192 | if loop < 3 193 | Lm = x - 1; 194 | Um = x + 1; 195 | else 196 | s = 0.7; 197 | xg1 = sign(x - xold1); 198 | xg2 = sign(xold1 - xold2); 199 | Lm = x - s * (x - Lm) .* (xg1 ~= xg2) - (x - Lm)./s .* (xg1 == xg2); 200 | Um = x + s * (Um - x) .* (xg1 ~= xg2) + (Um - x)./s .* (xg1 == xg2); 201 | end 202 | a = 0.9*Lm + 0.1*x; 203 | b = 0.9*Um + 0.1*x; 204 | case 'Liu&Tovar' 205 | if loop < 3 206 | Lm = (2*x - 1)./2; 207 | Um = Lm + 1; 208 | else 209 | xg = (x - xold1).*(xold1 - xold2); 210 | g = 0.7 * (xg < 0) + 1.2 * (xg > 0) + 1 * (xg == 0); 211 | Lm = (2*x - g)./2; 212 | Um = Lm + g; 213 | end 214 | a = 0.9*Lm + 0.1*x; 215 | b = 0.9*Um + 0.1*x; 216 | case 'Christensen&Klarbring' 217 | if loop < 3 218 | sinit = 0.5; 219 | Lm = x - sinit; 220 | Um = x + sinit; 221 | else 222 | slow = 0.5; 223 | sfast = 1.5; 224 | xg1 = sign(x - xold1); 225 | xg2 = sign(xold1 - xold2); 226 | Lm = x - slow * (x - Lm) .* (xg1 ~= xg2) - sfast * (x - Lm) .* (xg1 == xg2); 227 | Um = x + slow * (Um - x) .* (xg1 ~= xg2) + sfast * (Um - x) .* (xg1 == xg2); 228 | end 229 | mu = 0.5; 230 | a = max(0, Lm + mu*(x - Lm)); 231 | b = min(1, Um - mu*(Um - x)); 232 | end 233 | end -------------------------------------------------------------------------------- /UCOpt3D/Top3dSTL_v3.m: -------------------------------------------------------------------------------- 1 | function Top3dSTL_v3(fout, varargin) 2 | %Top3dSTL_v3 A simple STL writter for Top3d by Liu (Apr 2015) 3 | % Top3dSTL_v3(fout) writes a STL file with name fout using cubic 4 | % representation and binary file format if xPhys exists in Workspace. 5 | % 6 | % Top3dSTL_v3(fout, xPhys) writes a STL file with name fout using cubic 7 | % representation and binary file format 8 | % 9 | % Top3dSTL_v3(___, Name, Value) writes a STL file with one or more Name, 10 | % Value pair argments. Use this option with any of the input argument 11 | % combinations in the prvious syntaxes. 12 | % FORMAT - File is written in 'binary' (default) or 'ascii' format. 13 | % TITLE - Header text (max 80 characters) written to the STL file. 14 | % MODE - Facets are generated using 'cube' (default) or 'iso'. 15 | % CUTOFF - Density cutoff value. default: 0.5 16 | % FACECOLOR - Face color. default: 'cyan' 17 | % ALPHA - Face alpha value. default: 1. 18 | % UNITLENGTH - Vector of element unit length. default: [1 1 1] 19 | % PLOT - Logic flag to display structures. default: true 20 | % 21 | % Example 1: 22 | % Top3dSTL_v3('MyTop3d.stl') % when xPhys is in Workspace 23 | % 24 | % Example 2: 25 | % Top3dSTL_v3('MyTop3d.stl', density, ... 26 | % 'Format', 'ascii', 'Mode', 'iso', 'FaceColor', 'm', 'Plot', false) 27 | % 28 | 29 | % Determine input type 30 | if ~isempty(varargin) && (isnumeric(varargin{1}) || islogical(varargin{1})) 31 | xPhys = varargin{1}; 32 | options = parseInputs(varargin{2:end}); 33 | else 34 | try 35 | xPhys = evalin('base', 'xPhys'); 36 | catch ME 37 | switch ME.identifier 38 | case 'MATLAB:UndefinedFunction' 39 | error('xPhys is not input argument nor exist in workspace'); 40 | otherwise 41 | rethrow(ME) 42 | end 43 | end 44 | options = parseInputs(varargin{:}); 45 | end 46 | 47 | % Generate faces and verts 48 | if strcmp(options.mode, 'cube') 49 | [faces, verts] = getCube(xPhys, options); 50 | else 51 | [faces, verts] = getISO(xPhys, options); 52 | end 53 | % Facets 54 | facets = single(verts); 55 | facets = reshape(facets(faces',:)', 3, 3, []); 56 | % facets: (:,:,1) --> Vertices of face 1, 57 | % facets(:,1,1) --> First vertice of face 1 58 | V1 = squeeze(facets(:,2,:) - facets(:,1,:)); 59 | V2 = squeeze(facets(:,3,:) - facets(:,1,:)); 60 | 61 | % Normal vectors 62 | normals = cross(V1, V2); 63 | clear V1 V2 64 | % Normal vectors normalization 65 | normals = bsxfun(@times, normals, 1 ./ sqrt(sum(normals .* normals, 1))); 66 | 67 | facets = cat(2, reshape(normals, 3, 1, []), facets); 68 | clear normals 69 | 70 | % Write STL 71 | if strcmp(options.format, 'ascii') 72 | writeAscii(facets, fout, options.title); 73 | else 74 | writeBinary(facets, fout, options.title); 75 | end 76 | 77 | end 78 | 79 | function options = parseInputs(varargin) 80 | OP = inputParser; 81 | defaultFormat = 'binary'; 82 | expectedFormat = {'ascii', 'binary'}; 83 | defaultMode = 'cube'; 84 | expectedMode = {'cube', 'iso'}; 85 | defaultTitle = sprintf('Created by Top3dSTL.m %s',datestr(now)); 86 | defaultCutoff = 0.5; 87 | defaultFcolor = 'c'; 88 | defaultAlpha = 1; 89 | defaultUnitLegth = [1, 1, 1]; 90 | defaultPlot = true; 91 | 92 | OP.addParamValue('format', defaultFormat, ... 93 | @(x) any(validatestring(x,expectedFormat))) 94 | OP.addParamValue('mode', defaultMode, ... 95 | @(x) any(validatestring(x,expectedMode))) 96 | OP.addParamValue('title', defaultTitle, @ischar); 97 | OP.addParamValue('cutoff', defaultCutoff, @isnumeric) 98 | OP.addParamValue('facecolor', defaultFcolor, @ischar) 99 | OP.addParamValue('alpha', defaultAlpha, @isnumeric) 100 | OP.addParamValue('unitlength', defaultUnitLegth, ... 101 | @(x) validateattributes(x, {'numeric'}, {'vector'})); 102 | OP.addParamValue('plot', defaultPlot, @islogical) 103 | 104 | OP.parse(varargin{:}); 105 | options = OP.Results; 106 | end 107 | 108 | function [faces, verts] = getCube(xPhys, options) 109 | % Generate Mesh 110 | nx = options.unitlength(1); 111 | ny = options.unitlength(2); 112 | nz = options.unitlength(3); 113 | [nely, nelx, nelz] = size(xPhys); 114 | nele = nelx*nely*nelz; 115 | nodegrd = reshape(1:(nely+1)*(nelx+1),nely+1,nelx+1); 116 | nodeids = reshape(nodegrd(1:end-1,1:end-1),nely*nelx,1); 117 | nodeidz = 0:(nely+1)*(nelx+1):(nelz-1)*(nely+1)*(nelx+1); 118 | nodeids = repmat(nodeids, size(nodeidz))+repmat(nodeidz, size(nodeids)); 119 | enodVec = nodeids(:)+1; 120 | enodMat = repmat(enodVec,1,8)+ ... 121 | repmat([0 nely + [1 0] -1 ... 122 | (nely+1)*(nelx+1)+[0 nely + [1 0] -1]],nele,1); 123 | 124 | % Faces connectivities 125 | enodidx = [... 126 | 1 3 2; 1 4 3; ... % back 127 | 5 6 7; 5 7 8; ... % front 128 | 1 5 8; 1 8 4; ... % left 129 | 6 2 3; 6 3 7; ... % right 130 | 8 7 3; 8 3 4; ... % up 131 | 1 2 6; 1 6 5]; % down 132 | 133 | faces = []; 134 | 135 | % Filter out Low density 136 | xPhys(xPhys < options.cutoff) = 0; 137 | xPhys(xPhys >= options.cutoff) = 1; 138 | 139 | for f = 1:size(enodMat,1) 140 | if xPhys(f) == 0 141 | continue; 142 | end 143 | 144 | % Coordinates 145 | [j, i, k] = ind2sub([nely, nelx, nelz], f); 146 | eFace = enodidx; % element faces connectivities 147 | idx = []; % element faces to be deleted 148 | % Neighbor on back 149 | if (k ~= 1 && xPhys(j, i, k - 1) == 1) 150 | idx = [idx; [1 2]]; 151 | end 152 | % Neighbor on front 153 | if (k ~= nelz && xPhys(j, i, k + 1) == 1) 154 | idx = [idx; [3 4]]; 155 | end 156 | % Neighbor on left 157 | if (i ~= 1 && xPhys(j, i - 1, k) == 1) 158 | idx = [idx; [5 6]]; 159 | end 160 | % Neighbor on right 161 | if (i ~= nelx && xPhys(j, i + 1, k) == 1) 162 | idx = [idx; [7 8]]; 163 | end 164 | % Neighbor on up 165 | if (j ~= 1 && xPhys(j - 1, i, k) == 1) 166 | idx = [idx; [9 10]]; 167 | end 168 | % Neighbor on down 169 | if (j ~= nely && xPhys(j + 1, i, k) == 1) 170 | idx = [idx; [11 12]]; 171 | end 172 | 173 | eFace(idx, :) = []; 174 | tmp = enodMat(f,:); 175 | faces = cat(1, faces, tmp(eFace)); 176 | 177 | end 178 | 179 | % Vertices 180 | [xx, yy, zz] = meshgrid(0:nx:nelx*nx, ... 181 | 0:ny:nely*ny, ... 182 | 0:nz:nelz*nz); 183 | verts = [xx(:) nely-yy(:) zz(:)]; 184 | 185 | % Visualization 186 | if options.plot 187 | dverts = [xx(:) zz(:) yy(:)]; 188 | cla, hold on, view(30,30), rotate3d on, axis equal 189 | axis([0 nelx*nx 0 nelz*nz 0 nely*ny]), box 190 | set(gca,'YDir', 'reverse', 'ZDir', 'reverse', 'ZtickLabel', flipud(get(gca, 'Ztick')')); 191 | patch('faces', faces, 'vertices', dverts, 'FaceColor', options.facecolor, 'FaceAlpha', options.alpha) 192 | xlabel('x'), ylabel('z'), zlabel('y') 193 | end 194 | end 195 | 196 | function [faces, verts] = getISO(xPhys, options) 197 | nx = options.unitlength(1); 198 | ny = options.unitlength(2); 199 | nz = options.unitlength(3); 200 | [nely, nelx, nelz] = size(xPhys); 201 | 202 | aux = zeros(nely+2, nelx+2, nelz+2); 203 | aux(2:end-1,2:end-1,2:end-1) = xPhys; 204 | 205 | [X,Y,Z] = meshgrid(0:nx:nx*(nelx+1), ... 206 | 0:ny:ny*(nely+1), ... 207 | 0:nz:nz*(nelz+1)); 208 | 209 | [faces, verts] = isosurface(X-0.5, Z-0.5, Y-0.5, aux, options.cutoff); 210 | 211 | % Visualization 212 | if options.plot 213 | cla, hold on, view(30,30), rotate3d on, axis equal 214 | axis([0 nx*nelx 0 nz*nelz 0 ny*nely]), box 215 | set(gca, 'YDir', 'reverse', 'ZDir', 'reverse', 'ZtickLabel', flipud(get(gca, 'Ztick')')); 216 | 217 | patch('Faces', faces, 'Vertices', verts,... 218 | 'FaceColor', options.facecolor, 'EdgeColor', 'none', 'FaceAlpha', options.alpha); 219 | camlight, lighting gouraud; 220 | xlabel('x'), ylabel('z'), zlabel('y') 221 | drawnow 222 | end 223 | end 224 | 225 | function writeAscii(facets, fout, title) 226 | % Write ASCII STL file 227 | %{ 228 | FORMAT: 229 | 230 | solid name 231 | facet normal ni nj nk 232 | outer loop 233 | vertex v1x v1y v1z 234 | vertex v2x v2y v2z 235 | vertex v3x v3y v3z 236 | endloop 237 | endfacet 238 | end solid name 239 | 240 | %} 241 | fid = fopen(fout, 'wb+'); 242 | fprintf(fid, [title, '\r\n']); 243 | fprintf(fid,[... 244 | 'facet normal %.7E %.7E %.7E\r\n' ... 245 | 'outer loop\r\n' ... 246 | 'vertex %.7E %.7E %.7E\r\n' ... 247 | 'vertex %.7E %.7E %.7E\r\n' ... 248 | 'vertex %.7E %.7E %.7E\r\n' ... 249 | 'endloop\r\n' ... 250 | 'endfacet\r\n'], facets); 251 | fprintf(fid, ['end ', title, '\r\n']); 252 | fclose(fid); 253 | fprintf('Wrote %d facets to %s\n',size(facets, 3), fout); 254 | end 255 | 256 | function writeBinary(facets, fout, title) 257 | % Write Binary STL file 258 | %{ 259 | FORMAT: 260 | 261 | UINT8[80] ? Header 262 | UINT32 ? Number of triangles 263 | 264 | foreach triangle 265 | REAL32[3] ? Normal vector 266 | REAL32[3] ? Vertex 1 267 | REAL32[3] ? Vertex 2 268 | REAL32[3] ? Vertex 3 269 | UINT16 ? Attribute byte count 270 | end 271 | 272 | %} 273 | fid = fopen(fout, 'wb+'); 274 | fprintf(fid, '%-80s', title); % Title 275 | fwrite(fid, size(facets, 3), 'uint32'); % Number of facets 276 | facets = typecast(facets(:), 'uint16'); % Convert to unit16 277 | facets = reshape(facets, 12*2, []); 278 | facets(end+1, :) = 0; % Add color(0) to the end of each facet 279 | fwrite(fid, facets, 'uint16'); 280 | fclose(fid); 281 | fprintf('Wrote %d facets to %s\n',size(facets, 2), fout); 282 | end 283 | 284 | % ========================================================================= 285 | % === This code was written by K Liu, Dept. of Mechanical Engineering === 286 | % === Indiana University-Purdue University Indianapolis, === 287 | % === Indiana, United States of America === 288 | % === ----------------------------------------------------------------- === 289 | % === Please send your suggestions and comments to: kailiu@iupui.edu === 290 | % === ----------------------------------------------------------------- === 291 | % === This code is an extension for Top3D program that helps users to === 292 | % === generate STL file for 3D printing or post processing === 293 | % === ----------------------------------------------------------------- === 294 | % === This code as well as Top3d program can be downloaded freely from === 295 | % === the website: http://www.top3dapp.com/ === 296 | % === ----------------------------------------------------------------- === 297 | % === Disclaimer: === 298 | % === The authors reserves all rights for the program. === 299 | % === The code may be distributed and used for educational purposes. === 300 | % === The authors do not guarantee that the code is free from errors, and = 301 | % === they shall not be liable in any event caused by the use of the code.= 302 | % ========================================================================= --------------------------------------------------------------------------------