Content uploaded by Yi Min Xie

Author content

All content in this area was uploaded by Yi Min Xie on Jan 15, 2023

Content may be subject to copyright.

Content uploaded by Zicheng Zhuang

Author content

All content in this area was uploaded by Zicheng Zhuang on Dec 29, 2022

Content may be subject to copyright.

1

Article published in

Structural and Multidisciplinary Optimization, Vol. 66 (2023) 11

https://doi.org/10.1007/s00158-022-03464-x

A 172-line Matlab code for structural topology optimization in the body-fitted mesh

Zicheng Zhuang1, Yi Min Xie1, Qing Li2, and Shiwei Zhou1,*

1 Centre for Innovative Structures and Materials, School of Engineering, RMIT University,

Melbourne 3001, Australia

2 School of Aerospace, Mechanical and Mechatronic Engineering, The University of Sydney,

Sydney 2006, Australia

* Corresponding author. E-mail address: shiwei.zhou@rmit.edu.au.

Abstract

Topology optimization has the potential to be widely applied to produce innovative and

efficient structures, allowing engineers to optimize their aesthetics and performance. This

article adopted a 172-line Matlab code TriTOP172 to implement topology optimization in

the unstructured triangular mesh using the bi-directional evolutionary structural optimization

method. Its most significant feature is the elimination of zig-zag boundaries essentially existing

in the commonly-used rectangular mesh. The code uses 40 lines for preliminary setup and

optimization iterations and a 78-line function to obtain the body-fitted mesh by solving the

balance of a truss network. It also has a 20-line function of nonlinear diffusion to further smooth

boundaries and control structure complexity and a 34-line function of ﬁnite element analysis.

Numerical examples of compliance minimization are provided to assist readers in

understanding the algorithm and its implementation. This code can be employed with further

extensions to solve complicated conceptual design problems efficiently in several engineering

fields. The educational Matlab program is accessible on the website and displayed in the

Appendix.

Keywords: Structural Topology Optimization, Educational Matlab Code, Bi-directional

Evolutionary Structural Optimization, Body-fitted Mesh.

2

1. Introduction

In recent decades, topology optimization has become an effective strategy for generating

elegant and innovative forms for additive manufacturing, architectural design, bio-chemical,

and aerospace engineering. Compared to size and shape optimization, structural topology

optimization seeks arbitrary structures with a decent mechanical performance by determining

the optimal layout in a continuum structure instead of dealing with predefined configurations.

For educational purposes, articles with Matlab codes were published to make these complicated

algorithms relatively easier to understand. The numerical implementation of the Solid Isotropic

Material with Penalization (SIMP) method was well explained using a 99-line Matlab code

(Sigmund 2001). A 199-line program capable of tracing the Pareto-optimal curve was

developed by Suresh (2010). It is a practical approach for judging whether a configuration

meets the Pareto-optimality condition. Then, an improved 88-line program was proposed by

Andreassen et al. (2011) to employ the PDE-based method and black-and-white projection

filter in the SIMP method, improving the computational speed and applicability. Afterwards,

an energy-based homogenization approach was proposed for materials with extreme properties

(Xia and Breitkopf 2015). This approach obtains the constitutive parameters regarding element

mutual energies. The SIMP method has also been used to design multiscale composites and

geometrically nonlinear structures (Chen et al. 2019; Gao et al. 2019). An additive hyper

elasticity method was developed to circumvent numerical difficulties in large-displacement

optimization. As an improved version, Ferrari and Sigmund (2020) achieved speedups from

2.55 to 5.5 times based on the previous SIMP program. They also provided an efficient and

compact Matlab code with 125 lines for the 3D compliance minimization problems.

As a discrete optimization approach, Evolutionary Structural Optimization (ESO) method

was initially developed by Xie and Steven (1993; 1996) to generate the optimum structures.

Huang and Xie (2010) updated this method to the Bi-directional Evolutionary Structural

Optimization (BESO) method (2010) with a 101-line Matlab code. Also, a 100-line Python

script (Zuo and Xie 2015) using the soft-kill technique was developed to include efficient

materials and remove inefficient materials. Huang and Xie (2010) conducted a comprehensive

study about the techniques and applications of ESO and BESO methods to show their validity

and effectiveness. The BESO method with the multi-constraints, including the volume and first

principal stress constraint, has been studied in previous literature (Chen et al. 2021; Lin et al.

2020). Recent applications of BESO have addressed geometrically nonlinear optimization

(Han et al. 2021) and structural complexity control. Based on the topology-preserving property

of a thinning algorithm, He et al. (2022) proposed an efficient approach to changing the

geometrical feature of the BESO-optimized structures. Lately, the BESO method has been

combined with the marching geometries to attain smooth structural topologies (Li et al. 2022).

A smoothing technique is employed in the last iteration as a post-processing approach to

improving efficiency.

An alternative approach to topology optimization implicitly represents the solid-void

interfaces by a higher-dimensional embedded function used initially in image segmentation

(Osher and Sethian 1988). The traditional level set method uses the velocity normal to the

interface to solve the Hamilton-Jacobi equation (Allaire et al. 2002; Wang et al. 2003; Wang

et al. 2004). It has high flexibility in controlling topological changes and renders smooth

boundaries. In the last decade, Challis (2010) published a 129-line program for stiffness

optimization, providing insight into applying the level set method by integrating the topological

sensitivities and upwind finite difference scheme. Incorporating the reaction-diffusion equation,

Otomori et al. (2014) published an 88-line Matlab script, which differs from the conventional

level set method. They also considered the boundary condition effects once generating holes

3

inside solid materials. More recently, the radial basis function-based level set method is less

dependent on initial patterns due to its hole-nucleation capability inside the design domain

(Wei et al. 2018). In addition to SIMP, BESO, and level set methods, educational computer

programs for topology optimization using other approaches have been published recently

(Ansola Loyola et al. 2018; Liang and Cheng 2020; Picelli et al. 2021; Sanders et al. 2018;

Smith and Norato 2020).

Most existing codes optimize structures in a fixed structured mesh, which produces zig-zag

boundaries and affects the aesthetic and performance of the optimized configuration. The

automatic adaptive mesh generation is essential to topology optimization as the high-quality

body-fitted mesh can accurately describe and discretize the design domain geometry (Sigmund

and Maute 2013). Talischi et al. (2012) presented a Matlab program for polygonal mesh using

an implicit geometry description. This study provides linear convex polygons for the finite

element analysis and material updating scheme. After that, more works were published to

generate an adaptive mesh with a fluid relaxation analogy (Fu et al. 2019) and a feature-aware

smoothed particle hydrodynamics (Ji et al. 2021). A level-set-based mesh adaption method is

proposed and applied in topology optimization (Allaire et al. 2013; Allaire et al. 2014; Li et al.

2021). The key feature of their study is to move a level set function on an adaptive mesh and

re-mesh the interfaces according to the zero-level isosurface. Many closed-source re-meshing

tools, such as MMG, Rhino, and ZBrush, have been employed to generate the body-fitted mesh.

In our recent works for structural topology optimization in the body-fitted mesh using the

BESO method (Zhuang et al. 2022) and the reaction-diffusion level set methods (Zhuang et al.

2021), the mesh generation algorithm is based on the balance of a truss network. Numerical

examples in these two articles demonstrate that the high-quality unstructured mesh leads to the

accurate computation of the design response and aesthetic configuration.

This article presents a 172-line Matlab program TriTOP172 for the BESO method using

the body-fitted mesh and nonlinear diffusion regularization. It provides the open-source Matlab

code that integrates BESO with body-fitted mesh for the first time. This program was inspired

by published articles on topology optimization (Huang and Xie 2010; Sigmund 2001) and the

body-fitted mesh (Persson and Strang 2004). The positions of the vertices are iteratively

updated by finding a solution to force equilibrium in the bars to generate a high-quality

triangular mesh capturing the boundaries. Meanwhile, Delaunay triangulation is adopted to

connect the calculated nodes to form the body-fitted mesh. The BESO updating scheme

determines whether the solid material should be removed depending on the sensitivity number.

The traditional filter scheme is replaced by a diffusion regularization method to save memory.

Also, the elements filled with void materials are skipped in the finite element method to

decrease computation costs. In this method, the element removal ratio in each iteration for the

2D optimization problem can be defined as 5% to accelerate convergence. The provided 172-

line Matlab code includes the main BESO program (Lines 1–40), body-fitted mesh generator

(Lines 41–111), finite element analysis (Lines 112–153), together with nonlinear diffusion

derivation (Lines 154–173). This method can obtain optimized configurations with various

geometrical complexity by adjusting the element removal ratio, diffusion coefficient, or mesh

sparseness parameters. This code can educate researchers using the body-fitted mesh to

optimize physical problems sensitive to boundary smoothness, such as fluid structures, high-

speed trains, aircraft, buckling problems, and acoustic/optical metamaterials in the near future.

The remainder of this paper consists of the following sections. Section 2 introduces the

unstructured mesh generator and the BESO algorithm for the topology optimization problem.

This algorithm is further explained and implemented in the Matlab program in Section 3,

obtaining the results with improved efficiency and performance. The optimized configurations

4

illustrate the effectiveness and robustness of the provided program. Then, Section 4

summarizes the significance of this paper.

2. Problem Formulation

The proposed algorithm provides a simple solution to the compliance minimization problem

with the volume constraint. The unstructured triangular mesh is created iteratively as the body-

fitted mesh for finite element analysis and optimization procedure simultaneously.

2.1 Body-fitted Mesh Generator

The adaptive triangular mesh generation method originated by Persson and Strang (2004) is

employed in this paper to avoid rough boundaries. Instructively, the node sensitivity field

obtained from the bi-sectioning method is not only used to redistribute the solid and void

domain. It also determines the material boundaries according to its zero-level isosurface. A 2D

Gaussian filter is employed to further smooth the material boundaries in the design domain.

This paper generates a point set on the boundary with the Matlab function contour1,. Before

being fixed as the element vertices, the space between these nodes is adjusted. The points with

narrow spaces are merged to eliminate the singularity. On the other hand, the additional points

are included between the points with ample spaces to precisely capture the smooth interface.

After locating the points on the boundaries, Delaunay triangulation generates an initial

pattern from the uniformly distributed nodes. Then, the positions of nodes are iteratively

changed to satisfy the user-defined mesh density by solving the force-displacement function

for the edges. According to Hooke’s law, repulsive force in bars Fe can be calculated by the

current length l and the expected unextended length l0 of each bar as follows:

0 00

(, ) ( )

e

F ll k l l= −

(1)

where k0 is the modulus of elasticity. The user-defined expected bar length l0 is used to adjust

the mesh density. The resultant force for nodes Fp is the sum of force vectors from the

connected bars. The only exception is that the force at the fixed nodes is zero to prevent

movement. With the node coordinate matrix p, the ODE system can be written as follows:

= ()

d

dt p

pFp

(2)

The approximate solution can be updated iteratively using the forward Euler method starting

from the regularly distributed nodes as:

1

()

nn n

t

+

= +∆

p

p p Fp

(3)

where Δt is the artificial time, set as 0.2 in the Matlab code. After the prescribed maximal

iterations, Fig. 1 displays the elegant triangular mesh with the expected density generated by

the unstructured mesh generator. The red curve denotes the smooth interface between the solid

(yellow) and void (gray) domains. Note that a triangular element is either fully solid or void to

avoid intermediate density in the design domain.

1 1Names in type-writer font refer to Matlab variables, commands, and functions.

5

Fig. 1. The adaptive triangular elements produced by the unstructured mesh generator.

2.2 Topology Optimization

The rectangular design domain D⊂R2 is composed of the body-fitted triangular elements

produced in Section 2.1. Fig. 2 illustrates a compliance minimization optimization problem

with the volume constraint for the solid materials Ω, providing the external load F and fixed

boundaries. The design variable is the element density ρ. The proposed method adds a diffusion

regularization term φ(∇ρ) to the objective functional, eliminating the numerical instability and

checkerboard problem. As a regularization term, we chose the Lorentzian function for the

nonlinear diffusion in this code. As such, Eq. (4) gives the objective functional J for the

optimization problem.

max

11

min : ( ( ) : ( ) ( )) ( ( ))

22

subject to ( ) 0

T

J u u dx dx F u dx

G dV

ΩΩ

ρ

Ω

σ ε τϕ ρ τϕ ρ

ρ ρΩ

= +∇ = +∇

= −≤

∫∫

∫

(4)

where Vmax, u, and τ denote the displacement field, volume threshold value, and diffusion

coefficient, respectively.

6

Fig. 2. The load and boundary conditions for the cantilever beam optimization problem.

Suppose the vectors F and U record the force and displacement on each node in the finite

element framework. In that case, the objective functional J for the body-fitted mesh (N) can be

written as follows:

[ ]

T

1

max

1

min

min : ( )

subject to :

0

,1

N

T

ee ee e

e

N

ee

e

e

J

VV

ρ

τ ρ τϕ ρ

ρ

ρρ

=

=

= = +∇

=

−≤

∈

∑

∑

U KU + E u K u

KU F

(5)

where E denotes the diffusion term for regularization. The detailed derivation of the

triangular/tetrahedral mesh stiffness matrix K is provided in our previous paper. The scalars ρe

and Ve represent the density and volume of the eth element.

2.3 BESO Updating Scheme

The design pattern is iteratively updated by redistributing solid materials depending on the

relative ranking of the sensitivity number (Huang and Xie 2010). As the Lagrange multiplier λ

is introduced to meet the constraint, the sensitivity number for the eth body-fitted element is:

2

T

div( ( ) )

e

e ee e e

e

Cg

ρ τ ρρλ

ρ

∂

= + ∇∇−

∂

K

uu

(6)

The Lorentzian diffusion function g(│∇ρ│2) can be expressed in Eq. (7).

( )

22

1

2

1/ 1 2) /(g

ρ σρ

∇∇+=

(7)

The scale parameter σ1 is a positive coefficient to control the nonlinear diffusivity function.

Large values of this scale parameter will dilate the diffusivity function, impairing the boundary

smoothness. On the other hand, the checkerboard pattern cannot be entirely avoided if the scale

parameter value is too small. After trying various values, we selected 0.8 as the σ1 value in the

proposed program. Then, the diffusion term in the triangular mesh was derived thoroughly

using the matrix calculation. The result is displayed as follows:

7

22 2

() ()

11

div(())= (()) ( ())

e ei ei i Ae sume e

i Ae i Ae

ee

gg g

VV

ρ ρ ρ ωρ ρ ω ρ

∈∈

∇∇ ∇ − ∇

∑∑

(8)

where A(e) denotes all the neighboring points of the node e. Ve denotes the vertex area of this

point. It is defined that ωei and ωsume can be calculated as:

1

= (cot cot )

2

ei i i

ω αβ

+

(9)

()

=

sume ei

i Ae

ωω

∈

∑

(10)

where αi and βi are opposite side angles of the edge ei in two triangles.

Now we obtain the sensitivity number of all body-fitted elements. Then, the bi-section

Lagrangian method is utilized to update the density distribution and restructure the solid-void

interfaces. The maximal/minimal values of the Lagrange multiplier are initially defined as λ1/λ2

at the beginning of each iteration. Next, the proper value of the Lagrange multiplier λmid is

calculated with the bi-section method by multiply solving the following equations:

1 12

2 12

, 0.5( ) if

, 0.5( ) if

mid mid i i max

mid mid i i max

VV

VV

λ λ λ λλ ρ

λ λ λ λλ ρ

==+≤

==+>

∑

∑

(11)

The BESO updating scheme removes the solid materials iteratively according to the element

removal ratio, strictly controlling the volume fraction of the solid materials. Also, the previous

works usually consider all elements during finite element analysis. Since the elastic property

(Young’s modulus) of the void element is considerably smaller than the solid element, only the

degrees of freedom for the nodes of the solid elements are calculated in this work. This method

significantly saves the computational cost of finite element analysis, particularly under the

small volume constraint.

3. Matlab Implementation

This section mainly introduces how to implement the algorithm introduced in the last section

into the Matlab program. The provided Matlab code TriTOP172 is written as a standard

BESO program for the compliance minimization problem with the body-fitted triangular mesh.

The Matlab program is called by the command:

TriTOP172(nx,ny,ER,tau,Vmax,maxedge,minedge,E,nu)

where nx and ny define the physical dimensions of the design domain in x and y-axis

directions, respectively. ER is the element removal ratio employed to control the rate of volume

fraction reduction. The number of iterations to convergence can be controlled by adjusting the

ER value. tau is the diffusion coefficient affecting the geometric complexity of the optimized

configuration. Next, Vmax represents the desired maximum volume fraction. maxedge and

minedge limit the edge length range of the triangular elements to control mesh sparseness

across the design domain. E and nu represent Young’s modulus and Poisson’s ratio of the

linearly elastic material.

This program generates a figure to illustrate the design variable distribution in each iteration.

This section uses yellow and gray to represent solid and void material. The black and white

lines are defined as the edges of the solid and void elements. Fig. 3 presents the resulting

optimized configuration of a 2D cantilever beam using our Matlab code called with the input

line of:

TriTOP172(80,50,0.05,2e-8,0.5,0.2,0.025,1e5,0.3)

8

The optimized structure is achieved after 21 iterations with an objective function value of 1.802.

The volume fraction ratio is 50.01%, very close to the prescribed value (50%). Intel i5-

1145G7@2.60-GHz CPUs are used to run this program in Matlab R2019b for the numerical

examples. The 172-line code comprises four parts: main program, body-fitted mesh generator,

finite element method, and diffusion regularization. These parts are explained individually in

Sections 3.1–3.4. Then, more numerical examples in Section 3.5 demonstrate the efficiency

and robustness of the proposed program.

Fig. 3. The optimized design of the cantilever beam generated by the proposed program.

3.1 Main Program (Lines 1–40)

The proposed method assumes that the rectangular domain is discretized with the body-fitted

triangular elements. After parameter check in Lines 2–3, an initial pattern of the structure is

obtained in Lines 4–7 by distributing the solid material. BDY in the code represents the exterior

boundaries of the design domain. The proposed algorithm can start from either a perforated or

hole-free pattern, where the input parameters must be adjusted depending on the specific

situation of the initial pattern. The appropriate selection of the parameters can guarantee the

efficiency and robustness of the proposed algorithm.

The main loop starts with the body-fitted mesh generator (Lines 8–11), producing the node

positions p containing the node coordinates in the structure. Triangle indices t, t1, and t2

store the connectivity of all elements, void elements, and solid elements, respectively. The

mesh generator also provides the volume of the body-fitted elements in matrix Ve. Next, the

finite element subroutine in Line 14 calculates the displacement, the objective function value,

and the volume fraction of the solid material. The derivative of the nonlinear diffusion term

derived from the regularization subroutine in Line 12 is added to the interpolated node

sensitivity (Line 16). The stability of the structural optimization also depends on the tau value

because the unsuitable value will break the structures during the optimization process. The

resulting node sensitivity is averaged with the values in the last iteration to obtain a stable

convergence (Lines 17–19). Then, we employed the BESO method to update the optimized

pattern across the design domain in Lines 27–38. The bi-sectioning algorithm is utilized to

calculate the Lagrange multiplier value, which gives this code the potential to achieve

converged results within fewer iterations. Besides, the 2D Gaussian filtering function in Line

9

31 further eliminates the zig-zag shapes around the structure boundaries. The call for the mesh

generator in Line 33 strictly controls the volume fraction to meet the constraint.

Meanwhile, the node moving process in the mesh generator is accelerated by setting the

maxiter input as one, improving the efficiency. The redistributed solid and void elements

are plotted using different colors by Lines 20–22. Line 23 prints the objective function and

volume fraction values. The convergence check is achieved by Lines 24–26. The optimization

repeats until the objective function differences between current and previous iterations are less

than 0.5 percent, respectively.

3.2 Body-fitted Mesh Generator (Lines 41–118)

Before using the mesh generator, three subroutines in the Matlab code need to be introduced.

The subroutine Uniquenode (Lines 86–95) aims to remove the repeated and unused nodes

in the body-fitted mesh. The generated node coordinate matrix p and the connectivity matrix

t are used as the input of this subroutine. First, the volume of the triangular element is

calculated according to the vertices coordinates in Lines 88–90. Then, the command in Lines

91–92 removes the repeated nodes and the nodes not included in the connectivity matrices t.

Since the node are renumbered after the Matlab operator unique, we employed a loop over

triangular elements to match the updated node number in the connectivity matrix t (Lines 93–

95). The updated node coordinate matrix P and the connectivity matrix T are used as the result

of the body-fitted mesh generator.

Another subroutine Redispoints (Lines 96–111) is introduced in the code to

redistribute the points on the material boundaries. As mentioned, the points found on contour

C must be redistributed before the Delaunay triangulation. In practice, too-narrow point

distribution may lead to singularity. Thus, the space between the points should be controlled in

a user-defined range d1–d2 to generate a high-quality mesh. The distances between

neighboring points in C are calculated in Line 99 as the matrix CL. Lines 100–103 remove one

of the neighboring points whose distance is less than d1. Then, the space between updated

points CL2 is used to put additional points if the space is too large (Lines 105–111). Now, the

obtained points set C1 can be used for triangulation in the main program.

The subroutine E2N (Lines 112–118) calculates the node sensitivity number or density

value. In a loop over all nodes in the framework, the find operator is employed to sort out all

the triangular elements that include a specific node. Then, the weighted mean of element

sensitivity according to the volume/area of these elements is calculated as the sensitivity

number of this node in Line 117.

Lines 41–85 represent the Matlab implementation of a body-fitted mesh generator. Inspired

by the previous educational paper, this code moves the vertex nodes by solving the force-

displacement function. Firstly, the command in Line 43 creates an initial pattern pi with the

uniform distribution of nodes in the design domain. The zero-level contour of the smoothed

sensitivity field dN is found using the Matlab operator contour in Line 44. As mentioned,

these points are redistributed on the solid-void interface using the subroutine Redispoints

(Lines 45–49) to avoid singularity problems and obtain a higher mesh quality. Then, the

distance d between vertex nodes and their nearest points on the solid-void interface is

calculated. Line 56 rejects points with a probability proportional to 1/d2. The points on the

material boundaries are fixed in the node positions p.

10

Afterward, this code employs a loop to iteratively improve the mesh quality by moving the

vertex nodes and triangulation. The input maxiter is used to define the loop number to

control algorithm efficiency and preciseness. If the vertex node positions vary greatly

compared with the last iteration, a Delaunay triangulation is used to update the node

connectivity (Lines 59–63). After finding all edges of the triangles (Line 61), the midpoints

(Line 64) and actual length (Line 69) of the edges are calculated. The distance between the

midpoints of the edges (bars) and the nearest points on the solid-void interface is used to obtain

the desired edge length. Using the difference between actual bar (edge) length L and desired

bar length L0, we can easily achieve the repulsive bar force Fe in the edges. The resultant

force for nodes Fp is the sum of force vectors from the connected bars. Note that the force is

defined as zero for the fixed points to prevent movement. Once the force resultant is obtained,

the node position can be updated in Line 75 by multiplying the force with a parameter (0.2 in

this work). Before entering the next iteration, Lines 76–77 ensure that the points are drawn

back to the design domain. After the prescribed maximum iteration, the repeated and excluded

nodes are removed in Line 79 using the subroutine Uniquenode. Then, the density field dN

is interpolated into the element centroids using the Matlab operator interp2. The void

element t1 and solid element t2 are separated according to the interpolated value dE. Lastly,

the volume/area of each body-fitted mesh is calculated in Lines 83–85.

3.3 Finite Element Analysis (Lines 119–152)

Based on the body-fitted triangular mesh, the stiffness matrix is derived in Lines 147–152.

Unlike the structured rectangular mesh in the conventional methods, the element stiffness

matrix for solid material in the unstructured mesh varies according to the vertex coordinates.

The Jacobian J is calculated using the coordinates of the triangle vertices (Line 150), provided

by the body-fitted mesh generator. Next, the strain matrix Be is assembled in Line 151 using

the Jacobian. After getting elasticity matrix D using the defined E and nu, the stiffness matrix

of the three-nodal element Ke is calculated in Line 152. Then, the finite element subroutine is

provided in Lines 119–146, which returns the objective function value and element sensitivity.

The element stiffness matrices are derived using the mentioned subroutine GetmatrixKe in

Lines 121–125. The node coordinate matrix p and the element connectivity matrix t are used

as the input for solid elements. The global stiffness matrix NK is assembled using the sparse

function in Lines 129–133. Since the void elements only have negligible influence on the result,

we considered only solid elements to improve efficiency. All nodes and elements are numbered

by the sequence in the mesh generator. As each node has degrees of freedom on the x and y-

axis, the degree of freedom included in the solid domain SolidDof is found in Line 137.

Thus, the loads and supports can be applied to the structure by finding the load and support

points/areas in Lines 134–135. The degrees of freedom for the supporting areas are eliminated

as the Dirichlet boundary condition. Then, the Matlab operator setdiff is employed to find

the unconstrained degrees of freedom. The command in Line 140 defines the magnitude and

the direction of the load, which defines the non-homogenous Neumann boundary. Then, the

displacement vector U is provided in Line 141 using the force vector F and the global stiffness

matrix NK. At last, a loop over all solid mesh determines the objective function, volume fraction,

and element sensitivities in Lines 142–146.

3.4 Nonlinear Diffusion Term (Lines 153–172)

This work employs a nonlinear diffusion term instead of a conventional filter to regularize the

optimization problem and avoid the checkerboard pattern. The derivative of the Lorentzian

11

diffusion is derived and added to the interpolated node sensitivity in the main program. The

command in Line 155 calls the subroutine E2N to calculate the density value at each node

across the design domain. Next, a loop over all nodes calculates the diffusion term in the body-

fitted mesh. For a specific node (A0), its neighboring points can be found in Lines 157–158.

For each neighboring point (A1), we need to find all triangles that include points A0 and A1.

The third point of the triangle is defined as point A2. The command in Line 164 calculates the

interior angles of the triangles at various points A2. Since the Lorentzian function generates

better results than the other functions (Zhuang et al. 2022), the Lorentzian diffusion function g

is obtained in Line 166. The product of the density difference value, infamous cotangent

weights, and diffusion function is calculated in Lines 167–169. According to Eq. (8), the

discrete formulation of the Laplace operator on the density field is calculated using the sum of

the Lf values between point A0 and its neighboring points. Thus, the per-vertex expression of

the diffusion term derivative can be expressed as nonlidiff(A0) in Line 171. The diffusion

term derivative values are then added to the node sensitivity for the BESO updating scheme.

Matrix calculation can also be employed in this subroutine to assemble the diffusion term,

reducing the length of the Matlab code.

Fig. 4. The optimization results of the cantilever beam obtained by various inputs.

3.5 Extensions

The Matlab script in the Appendix solves the cantilever beam optimization problem. This code

provides multiple parameters that can be manually defined to improve robustness and obtain

various solutions. First and foremost, the nine input variables of the code can be adjusted

according to the requirement. It should be noted that the change of the physical dimensions

12

should be accompanied by the edge length range change maxedge and minedge. The

element removal ratio ER should not be larger than 0.1 to improve stability. The value of the

diffusion coefficient tau should depend on Young’s modulus value E. For example, Fig. 4(a)

presents the resulting configuration with a 0.3 volume constraint using the Matlab code called

with the command of:

TriTOP172(80,50,0.05,2e-8,0.3,0.2,0.025,1e5,0.3)

Fig. 4(b) presents the configuration with a different design domain size called with the input

line of:

TriTOP172(50,80,0.05,2e-8,0.5,0.2,0.025,1e5,0.3)

Fig. 4(c) presents the configuration with the same-size mesh called with the input line of:

TriTOP172(80,50,0.05,2e-8,0.5,0.022,0.022,1e5,0.3)

Fig. 4(d) presents the resulting optimized configuration called with the input line of:

TriTOP172(50,50,0.05,2e-8,0.3,0.2,0.025,1e5,0.3).

Except for the input parameters, other commands can also affect the optimization results in

the code, improving flexibility. The initial pattern can be defined manually in Line 7. Besides,

we can define the distance range between the neighboring points on the contour in Lines 47

and 49. In addition, the parameters in Lines 6, 11, 29, 56, 75, and 166 can also potentially

improve the quality of the optimized configuration if it is not satisfactory enough.

On the other hand, the load and boundary conditions can be edited manually by modifying

Lines 134–140 under different situations. Here, an MBB beam optimization problem is

considered using the symmetrical right-half structure. The downward external load F is applied

on the lower left corner, and the lower right corner is fixed in the vertical direction. The

optimized configuration of the half MBB beam is presented in Fig. 5 using the following

commands to replace commands in Lines 134–140:

fixedNodes1 = find(p(:,1)==BDY(1,1));

fixedDof1 = 2*fixedNodes1-1;

fixedNodes2 = find(p(:,1)==BDY(2,1) & p(:,2)==BDY(1,2));

fixedDof2 = 2*fixedNodes2;

fixedDof = [fixedDof1;fixedDof2];

forceNodes = find(p(:,1)==BDY(1,1) & p(:,2)==BDY(1,2));

SolidDof = [2*unique(sort(t2(:)))-1; 2*unique(sort(t2(:)))];

freeDofs = setdiff(SolidDof,fixedDof);

U = zeros(2*length(p),1);

F = sparse(2*forceNodes,1,-50,2*length(p),1);

The initial pattern is changed in Line 7 to accelerate the convergence as follows:

dN = sin(xn/BDY(2,1)*6*pi).*cos(yn/BDY(2,1)*6*pi)+0.5; dN (1:5,:)= 1;

As a result, Fig. 5 presents the resulting optimized configuration called with the input line of:

TriTOP172(120,40,0.05,2e-8,0.5,0.2,0.025,1e5,0.3).

13

Fig. 5. The optimized design of the MBB beam generated by the proposed program.

The MBB beam example shows that the algorithm converges within 19 iterations with an

objective function value of 2.263 and a volume fraction ratio (50.00%) identical to the

prescribed value. Note that the boundary smoothness of the optimized structure is improved

significantly, generating efficient and elegant patterns.

Fig. 6. The optimized design of the L-bracket example generated by the proposed program.

14

Some regions are prescribed void or solid in certain optimization problems, resulting in

passive solid/void elements. Like TOP99, TriTOP172 can easily handle this issue by a few

Lines in the mesh generation part. For instance, the following commands are added after Line

43 to make the upper right part of the design domain passive void for the L-bracket optimization

problem:

px = 0.2 * BDY(1,1); py = 0.2 * BDY(1,2);

[xp,yp] = meshgrid(px,py:0.01:BDY(2,2));

[xp2,yp2] = meshgrid(px:0.01:BDY(2,1),py);

Forcepts = [BDY(2,1) py; BDY(2,1)-0.01 py ;BDY(2,1)-0.02 py ;BDY(2,1)-0.03

py ;BDY(2,1)-0.04 py; BDY(2,1)-0.05 py];

P = [xp(:),yp(:); xp2(:),yp2(:)];

The command in Line 55 should be replaced by:

pfix=[C'; P; Forcepts; BDY(2,1) BDY(1,2); BDY(1,1) BDY(2,2); BDY(1,1)

BDY(1,2); BDY(2,1) BDY(2,2)];

A bar length control command should be included for the non-design domain after Line 69 as:

L = min(max(0.001,L),0.15);

Then, Line 82 is replaced to separate non-design passive elements tp, other void elements tv

and solid elements t2 as:

tnp = t(~(pmid(:,1)>px & pmid(:,2)>py),:);

tp = t((pmid(:,1)>px & pmid(:,2)>py),:);

dEnp = dE(~(pmid(:,1)>px & pmid(:,2)>py),:);

tv = tnp(dEnp<0,:);

t1 = [tp; tnp(dEnp<0,:)];

t2 = tnp(dEnp>0,:);

t = [t1;t2];

Thus, the passive elements have been defined in the mesh generator. Lines 123–124 should be

replaced by:

for i = 1:NT

if i<=length(t1) x=1e-5; else x=1; end

KK(:,6*i-5:6*i) = x*GetKe(p(t(i,:),1),p(t(i,:),2),E,nu);

After changing the load and boundary condition, the BESO scheme updates the material

distribution across the design and non-design domains. Lines 134–140 can be replaced by:

fixedNodes=find(p(:,2)==BDY(2,1));

fixedDof = [2*fixedNodes-1; 2*fixedNodes];

SolidDof = 1:2*length(p);

forceNodes = find(p(:,1)<=BDY(2,1) & p(:,1)>=BDY(2,1)-0.05 &

p(:,2)==0.2*BDY(1,2));

freeDofs = setdiff(SolidDof,fixedDof);

U = zeros(2*length(p),1);

F = sparse(2*forceNodes,1,-0.1,2*length(p),1);

The initial pattern is changed in Line 7 to accelerate the convergence as:

dN = sin(xn/BDY(2,1)*4*pi).*cos(yn/BDY(2,1)*4*pi)+0.5;

Then, the L-bracket can be optimized with the command below:

TriTOP172(100,100,0.05,2e-13,0.4,0.2,0.025,2,0.3)

15

Table 1. Optimization result comparison between TriTOP172 and TOP99, SBESO, and

LEVELSET88 codes.

Numerical Examples

Cantilever

Beam

MBB Beam

L-

bracket

TriTOP

172

Iterations 21 19 20

Mean

Compliance

1.802 2.263 11.804

Optimal

Design

SBESO

101

Iterations 79 71 41

Mean

Compliance 1.864 2.373 11.905

Improvement

Ratio 3.33% 4.64% 0.85%

Optimal

Design

SIMP

TOP99

Iterations 71 50 41

Mean

Compliance 1.917 2.517 12.223

Improvement

Ratio 6.00% 10.09% 3.43%

Optimal

Design

LEVEL

SET

88

Iterations 104 108 108

Mean

Compliance 1.896 2.372 11.867

Improvement

Ratio 4.96% 4.60% 0.53%

Optimal

Design

16

After fixing the left part of the top edge and imposing downward loads (blue arrows) on the

part, as shown in Fig. 6, the code can yield an optimized structure in 20 iterations with mean

compliance of 11.804 and a volume fraction of 40.00%.

Table 1 shows the performance comparison of the proposed method TriTOP172 with

TOP99 using the SIMP method (Sigmund 2001), SBESO with soft-kill BESO method

(Huang and Xie 2010), and LEVELSET88 of the reaction diffusion-based level set (RDLS)

method (Otomori et al. 2014). With the same design domain, loads, and boundary conditions,

TriTOP172 produces structures with satisfactory objective function values and improves

efficiency while ensuring boundary smoothness. The mean compliance values of the designs

generated by the previous codes are larger than the proposed code TriTOP172 by 0.53%–

10.09%, which is represented by the improvement ratios in Table 1. Additionally, it can be

found that the presented code significantly decreases the iterations to convergence, improving

the optimization efficiency.

4. Conclusions

Usually, mesh generators are complex codes that are used as black boxes. The previous related

works (Desai et al. 2021; Li et al. 2021) integrated the meshing software with topology

optimization on the body-fitted mesh. This paper aims to provide a concise and straightforward

Matlab code for students and newcomers to learn and directly extend topology optimization. A

body-fitted mesh generator compacted in 45-line Matlab code is displayed in the Appendix to

produce fine body-fitted mesh to discretize the design domain. The optimized designs with

lower mean compliance and higher efficiency can be obtained using the SIMP, BESO, and

level set methods. The Matlab code can be downloaded in the supplementary material and is

proposed for educational purposes. With the body-fitted tetrahedral mesh, this code can be

easily extended to 3D conditions to produce aesthetic designs with high performance. The

body-fitted mesh has advantages in optimizing physical problems sensitive to boundary

smoothness, such as fluid structures, high-speed trains, aircraft, buckling problems, and

acoustic/optical metamaterials.

Conflict of Interest Statement

On behalf of all authors, the corresponding author states that there is no conflict of interest.

Acknowledgments

This project was supported by the Australian Research Council (DP200102190, FL190100014).

Reference

Allaire G, Jouve F and Toader A-M (2002) A level set method for shape optimization.

Comptes Rendus Mathematique 334:1125–1130. https://doi.org/10.1016/S1631-

073X(02)02412-3

Allaire G, Dapogny C and Frey P (2013) A mesh evolution algorithm based on the level set

method for geometry and topology optimization. Structural and Multidisciplinary

Optimization 48(4):711-715. https://doi.org/10.1007/s00158-013-0929-2

Allaire G, Dapogny C and Frey P (2014) Shape optimization with a level set based mesh

evolution method. Computer Methods in Applied Mechanics and Engineering 282:22-53.

https://doi.org/10.1016/j.cma.2014.08.028

17

Andreassen E, Clausen A, Schevenels M, Lazarov BS and Sigmund O (2011) Efficient

topology optimization in MATLAB using 88 lines of code. Structural and Multidisciplinary

Optimization 43(1):1-16. https://doi.org/10.1007/s00158-010-0594-7

Ansola Loyola R, Querin OM, Garaigordobil Jiménez A and Alonso Gordoa C (2018) A

sequential element rejection and admission (SERA) topology optimization code written in

Matlab. Structural and Multidisciplinary Optimization 58(3):1297-1310.

https://doi.org/10.1007/s00158-018-1939-x

Challis VJ (2010) A discrete level-set topology optimization code written in Matlab.

Structural and Multidisciplinary Optimization 41(3):453-464. https://doi.org/10.1007/s00158-

009-0430-0

Chen A, Cai K, Zhao Z-L, Zhou Y, Xia L and Xie M (2021) Controlling the maximum first

principal stress in topology optimization. Structural and Multidisciplinary Optimization

63(1):327-339. https://doi.org/10.1007/s00158-020-02701-5

Chen Q, Zhang X and Zhu B (2019) A 213-line topology optimization code for geometrically

nonlinear structures. Structural and Multidisciplinary Optimization 59(5):1863-1879.

https://doi.org/10.1007/s00158-018-2138-5

Desai J, Allaire G, Jouve F and Mang C (2021) Topology optimization in quasi-static

plasticity with hardening using a level-set method. Structural and Multidisciplinary

Optimization 64(5):3163-3191. https://doi.org/10.1007/s00158-021-03034-7

Ferrari F and Sigmund O (2020) A new generation 99 line Matlab code for compliance

topology optimization and its extension to 3D. Structural and Multidisciplinary Optimization

62(4):2211-2228. https://doi.org/10.1007/s00158-020-02629-w

Fu L, Han L, Hu XY and Adams NA (2019) An isotropic unstructured mesh generation

method based on a fluid relaxation analogy. Computer Methods in Applied Mechanics and

Engineering 350:396-431. https://doi.org/10.1016/j.cma.2018.10.052

Gao J, Luo Z, Xia L and Gao L (2019) Concurrent topology optimization of multiscale

composite structures in Matlab. Structural and Multidisciplinary Optimization 60(6):2621-

2651. https://doi.org/10.1007/s00158-019-02323-6

Han Y, Xu B and Liu Y (2021) An efficient 137-line MATLAB code for geometrically

nonlinear topology optimization using bi-directional evolutionary structural optimization

method. Structural and Multidisciplinary Optimization 63(5):2571-2588.

https://doi.org/10.1007/s00158-020-02816-9

He Y, Zhao Z-L, Cai K, Kirby J, Xiong Y and Xie YM (2022) A thinning algorithm based

approach to controlling structural complexity in topology optimization. Finite Elements in

Analysis and Design 207:103779. https://doi.org/10.1016/j.finel.2022.103779

Huang X and Xie YM (2010) Evolutionary Topology Optimization of Continuum Structures:

Methods and Applications. Wiley, Chichester. https://doi.org/10.1002/9780470689486.ch2

Huang X and Xie YM (2010) A further review of ESO type methods for topology

optimization. Structural and Multidisciplinary Optimization 41:671-683.

https://doi.org/10.1007/s00158-010-0487-9

Ji Z, Fu L, Hu X and Adams N (2021) A feature-aware SPH for isotropic unstructured mesh

generation. Computer Methods in Applied Mechanics and Engineering 375:113634.

https://doi.org/10.1016/j.cma.2020.113634

Li H, Yamada T, Jolivet P, Furuta K, Kondoh T, Izui K and Nishiwaki S (2021) Full-scale

3D structural topology optimization using adaptive mesh refinement based on the level-set

method. Finite Elements in Analysis and Design 194:103561.

https://doi.org/10.1016/j.finel.2021.103561

Li Z, Lee T-U, Yao Y and Xie YM (2022) Smoothing topology optimization results using

pre-built lookup tables. Advances in Engineering Software 173:103204.

https://doi.org/10.1016/j.advengsoft.2022.103204

18

Liang Y and Cheng G (2020) Further elaborations on topology optimization via sequential

integer programming and Canonical relaxation algorithm and 128-line MATLAB code.

Structural and Multidisciplinary Optimization 61(1):411-431. https://doi.org/10.1007/s00158-

019-02396-3

Lin H, Xu A, Misra A and Zhao R (2020) An ANSYS APDL code for topology optimization

of structures with multi-constraints using the BESO method with dynamic evolution rate

(DER-BESO). Structural and Multidisciplinary Optimization 62(4):2229-2254.

https://doi.org/10.1007/s00158-020-02588-2

Osher S and Sethian JA (1988) Fronts propagating with curvature-dependent speed:

Algorithms based on Hamilton-Jacobi formulations. Journal of Computational Physics

79(1):12-49. https://doi.org/10.1016/0021-9991(88)90002-2

Otomori M, Yamada T, Izui K and Nishiwaki S (2014) Matlab code for a level set-based

topology optimization method using a reaction diffusion equation. Structural and

Multidisciplinary Optimization 51:1159-1172. https://doi.org/10.1007/s00158-014-1190-z

Persson P-O and Strang G (2004) A simple mesh generator in MATLAB. SIAM Review

46:329-345. https://doi.org/10.1137/S0036144503429121

Picelli R, Sivapuram R and Xie YM (2021) A 101-line MATLAB code for topology

optimization using binary variables and integer programming. Structural and

Multidisciplinary Optimization 63(2):935-954. https://doi.org/10.1007/s00158-020-02719-9

Sanders ED, Pereira A, Aguiló MA and Paulino GH (2018) PolyMat: an efficient Matlab

code for multi-material topology optimization. Structural and Multidisciplinary Optimization

58(6):2727-2759. https://doi.org/10.1007/s00158-018-2094-0

Sigmund O (2001) A 99 line topology optimization code written in Matlab. Structural and

Multidisciplinary Optimization 21(2):120-127. https://doi.org/10.1007/s001580050176

Sigmund O and Maute K (2013) Topology optimization approaches. Structural and

Multidisciplinary Optimization 48(6):1031-1055. https://doi.org/10.1007/s00158-013-0978-6

Smith H and Norato JA (2020) A MATLAB code for topology optimization using the

geometry projection method. Structural and Multidisciplinary Optimization 62(3):1579-1594.

https://doi.org/10.1007/s00158-020-02552-0

Suresh K (2010) A 199-line Matlab code for Pareto-optimal tracing in topology optimization.

Structural and Multidisciplinary Optimization 42(5):665-679. https://doi.org/10.1007/s00158-

010-0534-6

Talischi C, Paulino GH, Pereira A and Menezes IFM (2012) PolyMesher: a general-purpose

mesh generator for polygonal elements written in Matlab. Structural and Multidisciplinary

Optimization 45(3):309-328. https://doi.org/10.1007/s00158-011-0706-z

Wang MY, Wang X and Guo D (2003) A level set method for structural topology

optimization. Computer Methods in Applied Mechanics and Engineering 192:227–246.

https://doi.org/10.1016/S0045-7825(02)00559-5

Wang MY, Zhou S and Ding H (2004) Nonlinear diffusions in topology optimization.

Structural and Multidisciplinary Optimization 28:262-276. https://doi.org/10.1007/s00158-

004-0436-6

Wei P, Li Z, Li X and Wang MY (2018) An 88-line MATLAB code for the parameterized

level set method based topology optimization using radial basis functions. Structural and

Multidisciplinary Optimization 58(2):831-849. https://doi.org/10.1007/s00158-018-1904-8

Xia L and Breitkopf P (2015) Design of materials using topology optimization and energy-

based homogenization approach in Matlab. Structural and Multidisciplinary Optimization

52(6):1229-1241. https://doi.org/10.1007/s00158-015-1294-0

Xie YM and Steven GP (1993) A simple evolutionary procedure for structural optimization.

Computers & Structures 49(5):885-896. https://doi.org/10.1016/0045-7949(93)90035-C

19

Xie YM and Steven GP (1996) Evolutionary structural optimization for dynamic problems.

Computers & Structures 58(6):1067-1073. https://doi.org/10.1016/0045-7949(95)00235-9

Zhuang Z, Xie YM and Zhou S (2021) A reaction diffusion-based level set method using

body-fitted mesh for structural topology optimization. Computer Methods in Applied

Mechanics and Engineering 381:113829. https://doi.org/10.1016/j.cma.2021.113829

Zhuang Z, Xie YM, Li Q and Zhou S (2022) Body-fitted bi-directional evolutionary

structural optimization using nonlinear diffusion regularization. Computer Methods in

Applied Mechanics and Engineering 396:115114. https://doi.org/10.1016/j.cma.2022.115114

Zuo ZH and Xie YM (2015) A simple and compact Python code for complex 3D topology

optimization. Advances in Engineering Software 85:1-11.

https://doi.org/10.1016/j.advengsoft.2015.02.006

20

Appendix – Matlab Code

1 function TriTOP172(nx,ny,ER,tau,Vmax,maxedge,minedge,E,nu)

2 %% PARAMETER CHECK

3 if (tau/E>1e-12) || (ER>0.1) error('Improper input'); end

4 %% INITIALIZATION

5 BDY = [-.5*(nx) -.5*(ny); .5*(nx), .5*(ny)]/100;

6 [xn,yn] = meshgrid(BDY(1,1):(BDY(2,1)-BDY(1,1))/(nx):BDY(2,1),

BDY(1,2):(BDY(2,2)-BDY(1,2))/(ny):BDY(2,2));

7 dN = sin(xn/BDY(2,1)*6*pi).*cos(yn/BDY(2,1)*6*pi)+0.5;

8 %% MAIN LOOP

9 for iterNum = 1:200

10 %% GENERATE MESH AND NONLINEAR DIFFUSION TERM

11 [p,t,t1,t2,Ve] = GenerateMesh(xn,yn,dN,maxedge,minedge,BDY,80);

12 [nonlidiff] = NonlinearDiffsion(p,t,t1,Ve);

13 %% FINITE ELEMENT ANALYSIS AND SENSITIVITY

14 [Ce,J,vol] = FEA(t,t1,t2,p,Ve,BDY,E,nu);

15 V = max(Vmax,vol-ER);

16 Cn = E2N(t,p,Ce,Ve)+tau*nonlidiff';

17 if iterNum > 1 Cnlast =

griddata(pold(:,1),pold(:,2),Cnold,p(:,1),p(:,2),'cubic'); end

18 Cnold = Cn; pold = p;

19 if iterNum >1 Cn = 0.5*(Cn+Cnlast); end

20 %% PRINT RESULTS

21 clf; patch('Faces',t1,'Vertices',p,'EdgeColor',[250 250

250]/255,'FaceColor',[192 192 192]/255); hold on;

22 patch('Faces',t2,'Vertices',p,'EdgeColor','k','FaceColor',[255 255/2

0]/255); axis off equal; pause(1e-3);

23 disp(['It.: ' num2str(iterNum) ' Obj.: ' sprintf('%6.4f',J) ' Vol.: '

sprintf('%6.4f' ,vol) ]);

24 %% CONVERGENCE CHECK

25 if iterNum>10 && abs(vol-Vmax)<0.005 && all(abs(Obj(end)-Obj(end-5:end-

1)) <0.005*abs(Obj(end)))

26 return; end

27 %% DESIGN UPDATE USING BESO METHOD

28 l1 = 0; l2 = 1e-3;

29 while ((l2-l1)/l2 > 1e-3)

30 CnNew = Cn-(l1+l2)/2;

31 dN = imgaussfilt(griddata(p(:,1),p(:,2),CnNew,xn,yn,'cubic'),0.8);

32 if isempty(contour(xn,yn,dN,[0 0]))==0

33 [~,~,t1,~,Ve] = GenerateMesh(xn,yn,dN,maxedge,minedge,BDY,1);

34 Vtemp = 1-sum(Ve(1:length(t1)))/sum(Ve);

35 else Vtemp = dot(max(0,sign(mean(CnNew(t),2))),Ve)/sum(Ve);

36 end

37 if Vtemp > V l1 = (l1+l2)/2; else l2 = (l1+l2)/2; end

38 end

39 Obj(iterNum) = J;

40 end

41 %% MESH GENERATOR

42 function [p,t,t1,t2,Ve] = GenerateMesh(xn,yn,dN,maxedge,minedge,

BDY,maxiter)

43 x = xn; x(2:2:end,:) = x(2:2:end,:)+0.005; pi = [x(:),yn(:)];

44 C = contour(xn,yn,dN,[0 0]); C1 = [];

45 dump = find((C(1,:)==0) & (C(2,:)>=2));

46 for i = 1:length(dump)-1

47 C1 = [C1 (RedisPoints (C(:,dump(i)+1:dump(i+1)-1),0.004,0.01))'];

48 end

49 C = [C1 (RedisPoints (C(:,dump(end)+1:end),0.004,0.01))'];

50 d = zeros(size(pi,1),1);

51 for i = 1:size(pi,1)

21

52 d(i) = sqrt(min((pi(i,1)-C(1,:)).^2+(pi(i,2)-C(2,:)).^2));

53 end

54 r0 = 1./min(max(minedge,d),maxedge).^2;

55 pfix=[C'; BDY(2,1) BDY(1,2); BDY(1,1) BDY(2,2); BDY(1,1) BDY(1,2);

BDY(2,1) BDY(2,2); BDY(2,1),0];

56 p = [pfix; pi(r0./max(r0)>0.5,:)];

57 p1 = 0; warning off;

58 for i = 1:maxiter

59 if max(sum((p-p1).^2,2))>1e-6

60 t = delaunayn(p);

61 edges = unique(sort([t(:,[1,2]);t(:,[1,3]); t(:,[2,3])],2),'rows');

62 p1 = p;

63 end

64 midpoint = (p(edges(:,1),:)+p(edges(:,2),:))/2;

65 d = zeros(size(midpoint,1),1);

66 for j = 1:size(midpoint,1)

67 d(j) = sqrt(min((midpoint(j,1)-C(1,:)).^2+(midpoint(j,2)-

C(2,:)).^2));

68 end

69 L = sqrt(sum((p(edges(:,1),:)-p(edges(:,2),:)).^2,2));

70 L1 = min(max(minedge,d),maxedge);

71 L0 = 1.2*L1*sqrt(sum(L.^2)/sum(L1.^2));

72 Fe = max(L0-L,0)./L *[1,1].*(p(edges(:,1),:)-p(edges(:,2),:));

73 Fp = full(sparse(edges(:,[1,1,2,2]),ones(size(d)) *[1,2,1,2],[Fe,-

Fe],size(p,1),2));

74 Fp(1:size(pfix,1),:) = 0;

75 p = p+0.2*Fp;

76 p(:,1) = min(BDY(2,1),max(BDY(1,1),p(:,1)));

77 p(:,2) = min(BDY(2,2),max(BDY(1,2),p(:,2)));

78 end

79 [p, t] = UniqueNode(p,t);

80 pmid = (p(t(:,1),:)+p(t(:,2),:)+p(t(:,3),:))/3;

81 dE = interp2(xn,yn,dN,pmid(:,1),pmid(:,2),'cubic');

82 t1 = t(dE<0,:); t2 = t(dE>=0,:); t = [t1;t2];

83 for kk = 1:length(t)

84 Ve(kk) = 0.5.*det([ones(3,1) p(t(kk,:),:)]);

85 end

86 %% REMOVE REPEATED NODES

87 function [P,T] = UniqueNode(p,t)

88 for kk = 1:length(t)

89 Ve(kk) = 0.5.*det([ones(3,1) p(t(kk,:),:)]);

90 end

91 t((Ve==0),:) = [];

92 P=unique(p(unique(sort(t(:))),:),'rows');

93 for i = 1:length(t)

94 for j = 1:3 T(i,j) = find(P(:,1)==p(t(i,j),1)&P(:,2)==p(t(i,j),2));

end

95 end

96 %% CONTOUR POINTS DISTANCE ADJUST

97 function [C1] = RedisPoints(C,d1,d2)

98 C = C'; C1 = C;

99 CL = sqrt(sum(diff(C1,1,1).^2,2));

100 for i = 1:(size(C,1)-1)

101 if CL(i) < d1 C1(i,:) = [0;0]; C1((i+1),:) =

0.5*(C(i,:)+C((i+1),:)); end

102 end

103 C1(all(C1==0,2),:) = [];

104 CL2 = sqrt(sum(diff(C1,1,1).^2,2));

105 Cmid = [];

106 for i = 1:(size(C1,1)-1)

107 if CL2(i) > d2 Cmid = [Cmid; 0.5*(C1(i,:)+C1((i+1),:))]; end

22

108 end

109 if isempty(Cmid)==0

110 C1 = union(C1,Cmid,'rows');

111 end

112 %% CALCULATE NODE SENSITIVITY

113 function [dN] = E2N(t,p,x,Ve)

114 dN = zeros(length(p),1);

115 for i = 1:length(p)

116 [row,~] = find(t==i);

117 dN(i) = dot(Ve(row),x(row))/sum(Ve(row));

118 end

119 %% FINITE ELEMENT ANALYSIS

120 function [Ce,J1,vol] = FEA(t,t1,t2,p,Ve,BDY,E,nu)

121 NT = length(t);

122 KK = zeros(6,6*NT);

123 for i = length(t1)+1:NT

124 KK(:,6*i-5:6*i) = GetKe(p(t(i,:),1),p(t(i,:),2),E,nu);

125 end

126 elemDof = zeros(NT,6);

127 elemDof(:,[1 3 5]) = 2*t-1;

128 elemDof(:,[2 4 6]) = 2*t;

129 iK = reshape(kron(elemDof,ones(6,1))',36*NT,1);

130 jK = reshape(kron(elemDof,ones(1,6))',36*NT,1);

131 sK = reshape(KK,36*NT,1);

132 NK = sparse(iK,jK,sK,2*length(p),2*length(p));

133 NK = (NK+NK')/2;

134 fixedNodes = find(p(:,1)==BDY(1,1));

135 forceNodes = find(p(:,1)==BDY(2,1) & p(:,2)==0);

136 fixedDof = [2*fixedNodes-1; 2*fixedNodes];

137 SolidDof = [2*unique(sort(t2(:)))-1; 2*unique(sort(t2(:)))];

138 freeDofs = setdiff(SolidDof,fixedDof);

139 U = zeros(2*length(p),1);

140 F = sparse(2*forceNodes,1,-100,2*length(p),1);

141 U(freeDofs,:) = NK(freeDofs,freeDofs) \ F(freeDofs,1);

142 for i = length(t1)+1:NT

143 Ce(i) = 0.5 .* sum((U(elemDof(i,:))'*KK(:,6*i-

5:6*i)).*U(elemDof(i,:))',2);

144 end

145 J1 = sum(Ce);

146 vol = 1-sum(Ve(1:length(t1)))/sum(Ve);

147 %% ELEMENT STIFFNESS MATRIX

148 function [Ke] = GetKe(X,Y,E0,nu)

149 D = E0/(1-nu^2)*[1 nu 0; nu 1 0; 0 0 (1-nu)/2];

150 J = [X(1)-X(3) Y(1)-Y(3);X(2)-X(3) Y(2)-Y(3)];

151 Be = 1/det(J)*[J(2,2) 0 -J(1,2) 0 -J(2,2)+J(1,2) 0; 0 -J(2,1) 0 J(1,1)

0 J(2,1)-J(1,1); -J(2,1) J(2,2) J(1,1) -J(1,2) J(2,1)-J(1,1) -

J(2,2)+J(1,2)];

152 Ke = 1/2*det(J)*Be'*D*Be;

153 %% NONLINEAR DIFFUSION TERM DERIVATION

154 function [nonlidiff] = NonlinearDiffsion(p,t,t1,Ve)

155 f = E2N(t,p,sparse(length(t1)+1:length(t),1,1,length(t),1),Ve);

156 for A0 = 1:length(p)

157 Lf = []; [row , ~] = find(t==A0); ts = t(row,:);

158 PT = setdiff(ts,A0);

159 for i = 1:length(PT)

160 angl = [];

161 [secp , ~] = find(ts==PT(i));

162 for k = 1:length(secp)

163 A1 = PT(i); A2 = setdiff(ts(secp(k),:),[A0 A1]);

164 angl(k) = atan2(2*Ve(secp(k)),dot(p(A0,:)-p(A2,:),p(A1,:)-

p(A2,:)));

23

165 end

166 sigma = .8; g = 1/(1+((f(A1)-f(A0))^2/sigma^2));

167 if length(angl)==2

168 Lf(i) = (cot(angl(1))+cot(angl(2)))*(f(A1)-f(A0))*g;

169 else Lf(i) = (2*cot(angl(1)))*(f(A1)-f(A0))*g; end

170 end

171 nonlidiff(A0) = 1/(2*sum(Ve(row)))*sum(Lf);

172 end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% This Matlab code was written by ZC. Zhuang, YM. Xie, Q. Li and SW. Zhou %

% Centre for Innovative Structures and Materials, RMIT University %

% Please send your comments to: zhuanginmelbourne@gmail.com %

% %

% The program is proposed for educational purposes and is introduced in %

% the paper - A 172-line Matlab code for structural topology %

% optimization in the body-fitted mesh, SMO, 2022 %

% %

% Disclaimer: %

% The authors reserve all rights but do not guarantee that the code is %

% free from errors. Furthermore, we shall not be liable in any event. %

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% CANTILEVER BEAM OPTIMIZATION

% TriTOP172(80,50,0.05,2e-8,0.5,0.2,0.025,1e5,0.3)

%% MBB BEAM OPTIMIZATION

% TriTOP172(120,40,0.05,2e-8,0.5,0.2,0.025,1e5,0.3)

%% INITIAL PATTERN (REPLACE LINE 7)

% dN = sin(xn/BDY(2,1)*6*pi).*cos(yn/BDY(2,1)*6*pi)+0.5; dN (1:5,:)= 1;

%% LOAD AND BOUNDARY CONDITIONS (REPLACE LINES 134-140)

% fixedNodes1 = find(p(:,1)==BDY(1,1));

% fixedDof1 = 2*fixedNodes1-1;

% fixedNodes2 = find(p(:,1)==BDY(2,1) & p(:,2)==BDY(1,2));

% fixedDof2 = 2*fixedNodes2;

% fixedDof = [fixedDof1;fixedDof2];

% forceNodes = find(p(:,1)==BDY(1,1) & p(:,2)==BDY(1,2));

% SolidDof = [2*unique(sort(t2(:)))-1; 2*unique(sort(t2(:)))];

% freeDofs = setdiff(SolidDof,fixedDof);

% U = zeros(2*length(p),1);

% F = sparse(2*forceNodes,1,-50,2*length(p),1);

%% L-BRACKET OPTIMIZATION

% TriTOP172(100,100,0.05,2e-13,0.4,0.2,0.025,2,0.3)

%% INITIAL PATTERN (REPLACE LINE 7)

% dN = sin(xn/BDY(2,1)*4*pi).*cos(yn/BDY(2,1)*4*pi)+0.5;

%% PASSIVE ELEMENTS DEFINITION (ADD AFTER LINE 43)

% px = 0.2 * BDY(1,1); py = 0.2 * BDY(1,2);

% [xp,yp] = meshgrid(px,py:0.01:BDY(2,2));

% [xp2,yp2] = meshgrid(px:0.01:BDY(2,1),py);

% Forcepts = [BDY(2,1) py; BDY(2,1)-0.01 py ;BDY(2,1)-0.02 py ;BDY(2,1)-

0.03 py ;BDY(2,1)-0.04 py; BDY(2,1)-0.05 py];

% P = [xp(:),yp(:); xp2(:),yp2(:)];

%% PASSIVE ELEMENTS DEFINITION (REPLACE LINE 55)

% pfix=[C'; P; Forcepts; BDY(2,1) BDY(1,2); BDY(1,1) BDY(2,2); BDY(1,1)

BDY(1,2); BDY(2,1) BDY(2,2)];

%% PASSIVE ELEMENTS DEFINITION (ADD AFTER LINE 69)

% L = min(max(0.001,L),0.15);

%% PASSIVE ELEMENTS DEFINITION (REPLACE LINE 82)

% tnp = t(~(pmid(:,1)>px & pmid(:,2)>py),:);

% tp = t((pmid(:,1)>px & pmid(:,2)>py),:);

24

% dEnp = dE(~(pmid(:,1)>px & pmid(:,2)>py),:);

% tv = tnp(dEnp<0,:);

% t1 = [tp; tnp(dEnp<0,:)];

% t2 = tnp(dEnp>0,:);

% t = [t1;t2];

%% LOAD AND BOUNDARY CONDITIONS (REPLACE LINES 123-124)

% for i = 1:NT

% if i<=length(t1) x=1e-5; else x=1; end

% KK(:,6*i-5:6*i) = x*GetKe(p(t(i,:),1),p(t(i,:),2),E,nu);

%% LOAD AND BOUNDARY CONDITIONS (REPLACE LINES 134-140)

% fixedNodes=find(p(:,2)==BDY(2,1));

% fixedDof = [2*fixedNodes-1; 2*fixedNodes];

% SolidDof = 1:2*length(p);

% forceNodes = find(p(:,1)<=BDY(2,1) & p(:,1)>=BDY(2,1)-0.05 &

p(:,2)==0.2*BDY(1,2));

% freeDofs = setdiff(SolidDof,fixedDof);

% U = zeros(2*length(p),1);

% F = sparse(2*forceNodes,1,-0.1,2*length(p),1);