Zuo Xie 2015 Python Code Published PDF
Zuo Xie 2015 Python Code Published PDF
a r t i c l e
i n f o
Article history:
Received 13 December 2014
Accepted 11 February 2015
Keywords:
Topology optimization
BESO
Python
Abaqus
NumPy
Large deection
a b s t r a c t
This paper presents a 100-line Python code for general 3D topology optimization. The code adopts the
Abaqus Scripting Interface that provides convenient access to advanced nite element analysis (FEA).
It is developed for the compliance minimization with a volume constraint using the Bi-directional Evolutionary Structural Optimization (BESO) method. The source code is composed of a main program controlling the iterative procedure and ve independent functions realizing input model preparation, FEA,
mesh-independent lter and BESO algorithm. The code reads the initial design from a model database
(.cae le) that can be of arbitrary 3D geometries generated in Abaqus/CAE or converted from various
widely used CAD modelling packages. This well-structured code can be conveniently extended to various
other topology optimization problems. As examples of easy modications to the code, extensions to multiple load cases and nonlinearities are presented. This code is useful for researchers in the topology optimization eld and for practicing engineers seeking automated conceptual design tools. With further
extensions, the code could solve sophisticated 3D conceptual design problems in structural engineering,
mechanical engineering and architecture practice. The complete code is given in the appendix section and
can also be downloaded from the website: www.rmit.edu.au/research/cism/.
2015 Elsevier Ltd. All rights reserved.
1. Introduction
Structural topology optimization is a topic concerning the best
locations for cavities in a structure design domain. This topic has
been intensively investigated in the past three decades. During this
time, several educational articles were published aimed at introducing fundamentals of various algorithms by presenting computer program implementations, such as the Matlab codes by Sigmund
[19] for the Solid Isotropic Material with Penalization (SIMP)
method [2,25] and Challis [5] for the level-set method [16,21]. Also
an 88-line Matlab code was developed by Andreassen et al. [1] as
an extension to Sigmunds 99-line Matlab code with improved efciency. These works demonstrated basic 2D compliance minimization based on a rectangular design domain discretized into linear
4-noded elements and served the educational purposes well.
Huang and Xie [10] also published a Matlab code for 2D compliance minimization using the Bi-directional Evolutionary Structural
Optimization (BESO) method [7,11]. Recently Liu and Tovar [15]
presented a Matlab implementation using a modied SIMP model
for 3D topology optimization for linear structures with regular
min :
X
CX FT U UT KU
subject to :
X fxe g; xe 1 or xmin
F KU
VX
X
xe v e V
8 e 1; . . . ; N
2
3
4
ae
@C
@xe
p
xe
ae pxp1
uTe k0 ue xpe uTe k0 ue p
e
Ee
xe
wr ej aj X wrej
P
aj
j wr ej
j wr ej
j
ab e Pj
wr ej max0; r min r ej
gj aj
ae e
ab ke ab k1
e
2
V k1 V k 1 ert
10
Size: 202040
Fig. 1. Pseudocode of the bisection algorithm used in BESO for nding the
sensitivity threshold.
Then the element update is based on the optimality criteria for softkill BESO [10] that the sensitivities of solid elements (xe = 1) are
always lower than those of void elements (xe = xmin), for a
minimization problem. The update scheme is then devised according to the target volume and the sensitivities: a threshold th shall be
determined so that elements with a sensitivity lower than the
threshold are switched to solid (if void) and elements with a sensitivity higher than the threshold are switched to void (if solid), the
result of which achieves the target volume. The threshold can be
determined using a simple bisection method that changes the
threshold progressively as shown in Fig. 1. In the Python code, this
update algorithm is dened in the function BESO.
3. Python implementation
This section explains the basic form of the Python code which is
given in Appendix A in full. The code is to be called in Abaqus/CAE
through the menu command File->Run Script.
The Python code makes no assumption on the geometry of the
design domain. The design domain and required parameters are
transferred to the program as input arguments through two
prompt dialogues: the rst dialogue allows the user to input the
predened parameters for the target nal volume fraction, the lter radius and the evolutionary volume ratio; the second dialogue
lets the user to specify a model database le (.cae) that contains
the model of the design domain (also as the initial structure) of
an arbitrary geometry. Fig. 2 shows a 3D cantilever as an example
with a lter radius of 4 and target volume fraction of 10%. Note that
the input model database shall be prepared such that it contains a
model named Model-1 with a dependent part named Part-1 and
a static analysis step named Step-1.
3.1. Header (lines 24)
As a common programming practice, a header exists at the
beginning of the script to import a number of modules and functions: the module math is imported for arithmetic functions such
as sqrt and fabs (line 2); customKernel (line 2) is an Abaqus extended Python module for storing custom data in a model database;
getInput and getInputs (line 3) are two functions imported from
the Abaqus module for parsing the input parameters; and openOdb
(line 4) is a function imported from the odbAccess module for
accessing the FEA results in an Abaqus output database. The modules Abaqus and odbAccess are two common modules for most
Python scripts employing ASI and are standard components of
the Abaqus software.
3.2. Main program (lines 68100)
The main program denes the global execution ow. The main
program locates at the end of the source code since the Python
Fig. 2. Topology optimization of a 3D cantilever: (top) the initial full design as the
design domain; (middle and bottom) side and perspective views of the optimized
solution.
models
odb
Model 1
steps
parts
Model 2
...
parts
materials
Step
...
loads
Frame
steps
fieldOutputs
fieldOutputRequests
historyRegions
HistoryRegion
historyOutputRequests
...
mdb object model
frames
historyOutputs
Fig. 3. Abaqus object model hierarchy for (left) model database mdb; (right) output database odb.
According to the SIMP model [3], the Youngs modulus of the soft
material is set to 0.001 103 (line 12) based on xmin = 0.001 and
p = 3. Then the solid section is assigned to an element set containing all the elements (line 14) as the BESO procedure will start with
the initial full design. In the end, FEA outputs are requested for the
element strain energies (line 16) using the Abaqus keyword ELEDEN, and for the external work (line 17) using the keyword
ALLWK that is equivalent to the objective function (compliance)
considering no energy dissipation.
3.4. Finite element analysis: FEA (lines 1827)
This function runs the nite element analysis in the iteration
and outputs the element sensitivities Ae in the argument list and
the compliance as the function return value. The program submits
the analysis job to Abaqus (line 20) and waits till the analysis is nished (line 21). An output database (.odb) is automatically produced by Abaqus after the analysis and is opened by the program
(line 22). The element elastic strain energies are retrieved (line
23) according to the odb object model in Fig. 3 and using the Abaqus keyword ESEDEN. Then the element sensitivities are
obtained by modifying the element strain energies (line 24)
according to Eq. (6). Note that for the computational simplicity
Ae is not multiplied with the penalty exponent p in the implementation since this will not affect the optimization solution [9]. Finally the objective function compliance is retrieved (line 25) using the
keyword ALLWK and returned by the function.
3.5. Mesh-independent ltering: preFlt (lines 2844) and tAe (lines
4550)
The function preFlt prepares the lter scheme and is called only
once in the program to save the computational cost. For each element e, this function nds out the surrounding elements j within
the sphere centred at the centroid of the element e with the radius
rmin; and then calculates the weight factor gj according to Eqs. (7)
and (8). For each element e, the labels of elements j and the weight
factor gj are stored as lists; these two lists map with the label of
element e and form a pair in a dictionary that contains all such
pairs over the design domain. This dictionary is saved and later
used by tAe in the iteration. In the implementation, the centre
coordinates of each element is rst calculated and stored in a dictionary c0 (lines 3134); then in a double-loop, each over all the
elements, the distances between element centres and the relevant
weight factors are calculated and stored in the mapping dictionary
Fm (lines 3644).
The function tAe applies the lter scheme to the element sensitivities according to Eq. (7). In a loop over all elements, the modied sensitivities are obtained (lines 4850) by multiplying gj with
the raw sensitivities (line 47) based on the lter mapping dictionary Fm.
3.6. Element updating: BESO (lines 5167)
This function implements the BESO optimizer and is the core of
the Python code. This function rst determines the sensitivity
threshold th (lines 5359) following the bisection algorithm shown
in Fig. 1; during this procedure the design variables Xe are also set
by assigning 1.0 to solid elements and 0.001 to void elements.
According to the design variables, the labels of all elements are
grouped into two lists: slb for solid elements and vlb for void elements (lines 6164). Then the solid and void sections are assigned
to the two element sets that are created using the lists slb and vlb
respectively (lines 6667).
It should be noted that the above BESO optimizer can be
replaced by another 01 optimizer for test and comparison purposes. The replacement can be conveniently done, with lines 6067
remaining in the current form.
Accordingly for FEA, the modication takes place for the block of
reading the analysis outputs. Using a loop, the element sensitivities
and the objective function are summed up over all analysis steps;
in other words, the weight factors for all steps are identical and the
objective function is dened as follows.
obj
X
Ci
11
where Ci is the compliance of the ith load case. The Python implementation is realized by replacing lines 2325 with the following
block.
023
obj = 0
for k in Xe.keys(): Ae[k] = 0.0
for stp in opdb.steps.values():
seng = stp.frames[-1].eldOutputs[ESEDEN].values
for en in seng: Ae[en.elementLabel]+=en.data/
Xe[en.elementLabel]
obj += stp.historyRegions[Assembly
ASSEMBLY].historyOutputs[ALLWK].data[-1][1]
An example is given in Fig. 4 where the 3D cantilever has the identical geometry as that in Fig. 2 but includes an additional load case.
A lter radius of 4 and target nal volume fraction of 10% are used
in this example.
4.3. Geometric restrictions
Geometric restrictions such as a design domain of specic shape
and non-designable areas can be readily taken into account by the
proposed Python implementation. Using the graphical interface
Abaqus/CAE, arbitrary shaped geometries can be created and then
directly taken as the design domain. It is noted that the previous
Matlab implementations (e.g. [19,10,1,15]) are based on regular
design domains of 2D square or 3D cube shapes with the concept
of passive elements to create initial cavities, which is indirectly
realized by changing the source codes.
Additionally, non-designable areas are solid and allow no cavities to be created inside. Since the current Python code takes only
the part Part-1 in model Model-1 in the model database as the
design domain, any other parts are automatically regarded nondesignable. Therefore, a non-designable domain can be easily realized by dening an addition part besides Part-1.
Load case 2
Size: 202040
Load case 1
Fig. 4. Topology optimization of a 3D cantilever with two load cases: (top) the
initial full design as the design domain; (middle and bottom) side and perspective
views of the optimized solution.
Fig. 5 shows an example with both initial voids and a non-designable layer. Due to symmetry, only one quarter of the full structure is considered in Abaqus/CAE. The designable Part-1 in green
colour1 is attached to the non-designable Part-2 in white colour
using a tie-constraint. Two voids are cut off at the bottom of Part1 to create an extrusive pier that is xed at the base. A uniform
pressure is applied on the top surface of Part-2. A lter radius of
4 times the element size and a target nal volume fraction of 20%
are used in this example.
Fig. 6 shows an example of a gear design with a circular shaped
design domain and non-designable inner- and outer-rings; the designable Part-1 in green colour1 is attached to the non-designable
Part-2 in white colour using a tie-constraint. Three load cases
are applied as surface tractions, each being two concentrated forces
of 100 N on the outer-ring. The inner ring is xed on the internal surface. A lter radius of 2 and a target nal volume fraction of 20% are
used.
According to literature [4,8], the element sensitivity of nonlinear compliance minimization can be obtained as the sum of the
total elastic strain energy Ee and plastic strain energy Ep in the
element as follows.
020
ae Eee Epe
Fig. 5. Topology optimization with initial voids and a non-designable part: (top)
the design domain (one quarter model); (middle and bottom) side and perspective
views of the optimized solution of the full bridge.
try:
Mdb.Job(Design_Job+str(Iter),Model-1).submit()
Mdb.jobs[Design_Job+str(Iter)].waitForCompletion()
except AbaqusException, message:
print Error occured:, message
sys.exit(1)
12
For interpretation of colour in Figs. 5 and 6, the reader is referred to the web
version of this article.
LC
-3
LC-1
t=6
-2
LC
t=4
t: thickness
LC: load case
LC-1
-2
LC
2.5
2.5
LC
-3
20
Fig. 6. Topology optimization with geometric restrictions: (top) the design domain and boundary conditions; (bottom) a perspective view of the optimized solution of the
gear.
Size: 16020
P
5. Conclusions
Fig. 7. Topology optimization of a double clamped beam: (top) the initial full
design as the design domain; (middle) linear solution; (bottom) geometrically
nonlinear solution.
This paper presents a simple Python code for topology optimization of general 2D and 3D structures. The compact 100-lined
code is developed for the compliance minimization with a volume
constraint. With simple modications, the basic Python code has
been extended to enhance computational efciency and to consider multiple load cases and nonlinearities. More importantly, the
code provides a convenient platform upon which further extensions such as new functions and different optimizers could be easily built. In doing so, the user may experiment with various
algorithms and tackle a wide range of problems. The Python code
is presented for educational and engineering practice purposes.
Moreover, with extensions such as those presented in this paper
and with the Abaqus FEA/modelling power, the Python code is capable of solving further engineering design problems using topology
optimization by generating complex conceptual designs. The complete codes are given in the appendix section for users to copy and
save as .py les to run with Abaqus/CAE. These codes may also be
downloaded from the website: www.rmit.edu.au/research/cism/.
General 3D topology optimization code based on BESO by Zhi Hao Zuo and Yi Min Xie. Note that the CAE le shall contain a
model Model-1 with a dependent part Part-1 and a static step Step-1.
import math,customKernel
from abaqus import getInput,getInputs
from odbAccess import openOdb
## Function of formatting Abaqus model for stiffness optimization
def fmtMdb(Mdb):
mdl = Mdb.models[Model-1]
part = mdl.parts[Part-1]
# Build sections and assign solid section
mdl.Material(Material01).Elastic(((1.0, 0.3),))
mdl.HomogeneousSolidSection(sldSec,Material01)
mdl.Material(Material02).Elastic(((0.0013, 0.3),))
mdl.HomogeneousSolidSection(voidSec,Material02)
part.SectionAssignment(part.Set(ss,part.elements),sldSec)
# Dene output request
mdl.FieldOutputRequest(SEDensity,Step-1,variables=(ELEDEN,))
mdl.HistoryOutputRequest(ExtWork,Step-1,variables=(ALLWK,))
## Function of running FEA for raw sensitivities and objective function
def FEA(Iter,Mdb,Xe,Ae):
Mdb.Job(Design_Job+str(Iter),Model-1).submit()
Mdb.jobs[Design_Job+str(Iter)].waitForCompletion()
opdb = openOdb(Design_Job+str(Iter)+.odb)
seng = opdb.steps[Step-1].frames[-1].eldOutputs[ESEDEN].values
for en in seng: Ae[en.elementLabel]=en.data/Xe[en.elementLabel]
obj=opdb.steps[Step-1].historyRegions[Assembly ASSEMBLY].historyOutputs[ALLWK].data[-1][1]
opdb.close()
return obj
## Function of preparing lter map (Fm={elm1:[[el1,el2,...],[wf1,wf2,...]],...})
def preFlt(Rmin,Elmts,Nds,Fm):
# Calculate element centre coordinates
c0 = {}
for el in Elmts:
nds = el.connectivity
c0[el.label]=[sum([Nds[nd].coordinates[i]/len(nds) for nd in nds]) for i in range(3)]
# Weighting factors
for el in Elmts:
Fm[el.label] = [[],[]]
for em in Elmts:
dis=math.sqrt(sum([(c0[el.label][i]-c0[em.label][i])2 for i in range(3)]))
if dis<Rmin:
Fm[el.label][0].append(em.label)
Fm[el.label][1].append(Rmin - dis)
sm = sum(Fm[el.label][1])
for i in range(len(Fm[el.label][0])): Fm[el.label][1][i] /= sm
## Function of ltering sensitivities
def tAe(Ae,Fm):
raw = Ae.copy()
for el in Fm.keys():
Ae[el] = 0.0
for i in range(len(Fm[el][0])): Ae[el]+=raw[Fm[el][0][i]]Fm[el][1][i]
## Function of optimality update for design variables and Abaqus model
def BESO(Vf,Xe,Ae,Part,Elmts):
lo, hi = min(Ae.values()), max(Ae.values())
tv = Vflen(Elmts)
while (hi-lo)/hi > 1.0e-5:
th = (lo+hi)/2.0
for key in Xe.keys(): Xe[key] = 1.0 if Ae[key]>th else 0.001
if sum(Xe.values())-tv>0: lo = th
else: hi = th
# Label elements as solid or void
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
028
10
This is a complete script used to automatically display results generated by the Python code in this paper.
import customKernel
from caeModules import
## Function of plotting optimization results
def pltRslts(mddb):
itern = len(mddb.customData.History[obj])
# Plot volume fraction history
vp1 = session.Viewport(Volume history,origin=(10,10),width=150,height=100)
xyPlot1 = session.XYPlot(Volume fraction)
chart1 = xyPlot1.charts.values()[0]
volDat = [(k,mddb.customData.History[vol][k]) for k in range(itern)]
xydv = session.XYData(Volume fraction,volDat)
chart1.setValues(curvesToPlot=[session.Curve(xydv)])
chart1.axes1[0].axisData.setValues(title=Iteration)
chart1.axes2[0].axisData.setValues(title=Volume fraction)
vp1.setValues(displayedObject=xyPlot1)
# Plot objective function history
vp2 = session.Viewport(Objective history,origin=(20,20),width=150,height=100)
xyPlot2 = session.XYPlot(Objective function)
chart2 = xyPlot2.charts.values()[0]
objDat = [(k,mddb.customData.History[obj][k]) for k in range(itern)]
xydo = session.XYData(Objective function,objDat)
chart2.setValues(curvesToPlot=[session.Curve(xydo)])
chart2.axes1[0].axisData.setValues(title=Iteration)
chart2.axes2[0].axisData.setValues(title=Objective function)
vp2.setValues(displayedObject=xyPlot2)
# Display nal design
vp3 = session.Viewport(Final design, origin=(30,30),width=150, height=100)
p = mddb.models[Model-1].parts[Part-1]
vp3.setValues(displayedObject=p)
vp3.partDisplay.setValues(mesh=ON)
vp3.partDisplay.displayGroup.remove(leaf=dgm.LeafFromSets(sets=(p.sets[vs],)))
## ====== MAIN PROGRAM ======
if __name__ == __main__:
mddb = openMdb(getInput(Input CAE le:,default=Final_Design.cae))
pltRslts(mddb)
References
[1] Andreassen E, Clausen A, Schevenels M, Lazarov BS, Sigmund O. Efcient
topology optimization in Matlab using 88 lines of code. Struct Multidisc Optim
2011;43(1):116.
[2] Bendse MP. Optimal shape design as a material distribution problem. Struct
Optim 1989;1:193202.
[3] Bendse MP, Sigmund O. Topology optimization: theory, methods and
applications. Berlin: Springer-Verlag; 2003.
[4] Buhl T, Pedersen CBW, Sigmund O. Stiffness design of geometrically nonlinear
structures using topology optimization. Struct Multidisc Optim
2000;19:93104.
[5] Challis VJ. A discrete level-set topology optimization code written in Matlab.
Struct Multidisc Optim 2010;41:45364.
[6] Dassault
Systemes;
2014.
<http://www.3ds.com/products-services/
simulia/portfolio/abaqus/overview/>.
[7] Huang X, Xie YM. Convergent and mesh-independent solutions for the bidirectional evolutionary structural optimization method. Finite Elem Anal Des
2007;43:103949.
[8] Huang X, Xie YM. Bidirectional evolutionary topology optimization for
structures with geometrical and material nonlinearities. AIAA J
2007;45(1):30813.
[9] Huang X, Xie YM. Bi-directional evolutionary topology optimization of
continuum structures with one or multiple materials. Comput Mech
2009;43:393401.
[10] Huang X, Xie YM. A further review of ESO type methods for topology
optimization. Struct Multidisc Optim 2010;41:67183.
[11] Huang X, Xie YM. Evolutionary topology optimization of continuum
structures: methods and applications. Chichester: John Wiley & Sons; 2010.
11
[26] Zuo ZH, Huang X, Rong JH, Xie YM. Multi-scale design of composite materials
and structures for maximum natural frequencies. Mater Des
2013;51:102334.
[27] Zuo ZH, Xie YM, Huang X. Evolutionary topology optimization of structures
with multiple displacement and frequency constraints. Adv Struct Eng
2012;15(2):38598.