You are on page 1of 64

Topology and shape optimization for non-linear problems Edward de Boer MT 11.

10
Sydney, December 2010

Contents
1 Introduction 2 Bi-directional evolutionary structural optimization 3 Topology optimization of energy-absorbing structures 3.1 Objective of the optimization for energy-absorbing structures 3.1.1 Sensitivity number at end displacement . . . . . . . . 3.1.2 Sensitivity number for whole displacement history . . 3.1.3 Evolutionary history of sensitivity number . . . . . . . 3.2 Checker-boarding suppression algorithm . . . . . . . . . . . . 3.3 Material removal/addition criterion . . . . . . . . . . . . . . . 3.4 Implementation using Abaqus . . . . . . . . . . . . . . . . . . 3.5 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.1 Example 1 . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.2 Example 2 . . . . . . . . . . . . . . . . . . . . . . . . . 4 Inverse shape optimization 4.1 Objective of the optimization method . . . . . . 4.1.1 Evolutionary history of indicator number 4.2 Material removal/addition criterion . . . . . . . . 4.3 Implementation . . . . . . . . . . . . . . . . . . . 4.4 Examples . . . . . . . . . . . . . . . . . . . . . . 4.4.1 Example 1 . . . . . . . . . . . . . . . . . . 4.4.2 Example 2 . . . . . . . . . . . . . . . . . . 4.4.3 Example 3 . . . . . . . . . . . . . . . . . . 4.4.4 Example 4 . . . . . . . . . . . . . . . . . . 5 Conclusion A Python code A.1 Topology optimization of energy-absorbing structures . . . . . . . . . . . . . . . A.2 Inverse shape optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 3 4 5 5 7 7 8 8 9 10 11 14 18 18 20 20 21 23 23 24 28 30 34 37 37 51

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

Chapter 1

Introduction
A stent is a mesh-like, dilatable structure which is inserted into various natural passages/conduits in the human body to counteract a disease-induced ow constriction. In order to insert a stent into the human body, it is only dilated (by means of ination) after insertion. During ination, the diameter of the stent is typically increased by a factor of two. The shape of the deformed stent is critical to its ability to function. Therefore there is need for an algorithm to optimize the nal shape of the stent. In this report, a simple algorithm is developed to optimize the initial shape of a material such that under large deformation, the material deforms to a desired shape (so called inverse shape optimization). It is assumed that the design criteria for the stent can be translated into a combination of simple shapes such as circular and rectangular holes in a planar design domain. This way the algorithm can be used on a thin-walled cylinder to optimize the shape of a stent. The algorithm that is developed, is based on the bi-directional evolutionary structural optimization (BESO) method. The BESO method has been developed for the topology optimization of structures in for example automotive. BESO has received a lot of attention because it can be easily implemented and linked to existing nite element analysis (FEA) packages. The BESO method is further explained in chapter 2. In order to get familiar with the BESO method and to serve as a benchmark, two examples from a paper by Huang, Xie and Lu [4] on topology optimization of energy-absorbing structures are reproduced in chapter 3. A combination of Abaqus with the python interface is used to do the optimization. Finally the inverse shape optimization method is introduced in chapter 4. Some examples demonstrate the functionality and limitations of the algorithm under large deformation compression and tension. A non-linear elasto-plastic material is used for all examples.

Chapter 2

Bi-directional evolutionary structural optimization


Research in structural topology optimization has lead to the development of the evolutionary structural optimization [2] (ESO) method and as an extension to that, to the bi-directional evolutionary structural optimization [3, 5] (BESO) method. Both methods have received a lot of attention [7, 6, 8, 9, 1] because they are easily implemented and linked to nite element analysis (FEA) packages. In the ESO process, the design domain is discretized in elements. From a full design domain, redundant elements are then removed in order to achieve an optimal design. The optimum solution can obviously not be achieved in one step. Therefore an evolutionary procedure has to be adopted. Only a small number of elements is removed in every iteration step. The number of elements that is to be removed each iteration is prescribed by the evolutionary ratio (ER). The evolutionary ratio is the number of elements to be removed divided by the total number of elements in the initial design. ESO is limited by the fact that removed elements cannot be added back to the design. To overcome this, the BESO (bi-directional evolutionary structural optimization) method was developed. In the BESO method, elements can be either added or removed. The number of elements that is removed or added is determined by the evolutionary ratio (ER) and the admission volume ratio (AR). The admission volume ratio is the number of added elements divided by the total number of elements in the initial design. Usually one of the optimization criteria is a volume constraint. The BESO algorithm continues until the target volume is reached. In order to determine what elements should be removed or added, sensitivity numbers are used. The sensitivity numbers can be derived mathematically by dierentiating the objective to the design variable. Present elements that are least favorable to the objective are removed, while void elements that will be most favorable to the objective are added to the design.

Chapter 3

Topology optimization of energy-absorbing structures


Energy absorbing structures are useful in automotive, where collision may cause severe injuries to vehicle occupants. In order to prevent injuries, there are several constraints on the energy absorbing structure. A structure that is too sti is undesirable because the forces in that structure could exceed the maximum tolerable crushing force. A too exible structure is also undesirable because it may have a long crushing distance, and therefore some parts of the structure may intrude and penetrate the human compartment. The goal of the presented optimization method is to design a structure that operates within the prescribed limits of force and displacement, and can absorb as much energy per unit of volume as possible.
Max. allowable crushing force

F*
Stiff structure Max. crushing distance Feasible optimal structure

Flexible structure

U*

Crushing distance

Figure 3.1: Load-displacement curve for three typical energy absorbing structures.

3.1

Objective of the optimization for energy-absorbing structures


Maximize
x

The objective is dened as f (x) = Fmax E V = F

subject to xj {0, 1},

(3.1)

Umax = U

j = 1, . . . , M.

where E is the strain energy, V is the (undeformed) volume of the structure, F is the external force and U is the displacement. F and U are threshold values for the force and displacement respectively. The design variable xj declares the presence (1) or absence (0) of an element. M is the total number of elements in the design domain. Typically, a non-linear material must be considered. The crush behavior is simulated by gradually increasing the applied displacement up to the maximum allowable crushing displacement (Umax ). In every displacement step, the equilibrium equation must be satised Ri = Fi Fiint = 0 (3.2)

where Ri is the residual force at displacement step i, Fi is the external force vector at step i and Fiint is the internal force vector at step i. The internal force vector can be expressed as Fiint =
M J =1

C jT Fij

(3.3)

where C jT represents a matrix that transforms the nodal internal force vector for the j th element into a global internal force vector.

3.1.1

Sensitivity number at end displacement

In order to nd the optimal design, the derivative of the objective is evaluated. 1 dE E dV df (x) = 2 dx V dx V dx (3.4)

According to the principle of energy conservation, the strain energy is equal to the applied work (see gure 3.2). The strain energy can be expressed as E = W = lim 1 T [(Ui UiT 1 )(Fi + Fi1 )] n 2
n i=1

(3.5)

where n is the total number of displacement steps. To calculate the variation in strain energy, a new equation is introduced by adding a series of Lagrangian multipliers. 1 T T E = W = lim [(Ui UiT 1 )(Fi + Fi1 ) i (Ri + Ri1 )] n 2
n i=1

(3.6)

Because the residual forces are equal to zero, the modied equation (3.6) is still the same as equation (3.5). The variation of strain energy now becomes dUiT dE 1 T dFi dFi1 dUiT dRi dRi1 1 = lim [(Ui UiT )( + ) + ( )(Fi + Fi1 ) T ( + )] 1 i n 2 dx dx dx dx dx dx dx
n i=1

(3.7) 5

Before element removal

Fi Fi-1

After element removal

Ui-1

Ui

Un

Displacement
Figure 3.2: Force-displacement curves before and after element removal. At the nodes where the displacement is prescribed, dU dx = 0 (the displacement will not vary over the design variable) and at all other nodes there is no external force (F = 0). Therefore the second set of terms is equal to zero. For a small loading step, a linear force-displacement relationship can be assumed. Fi Fi1 = Kit (Ui Ui1 ) Therefore the variation of the external force can be approximated by Fi Ui Ui1 dFi = + Kit Kit dx x x x dFi1 Fi1 U Ui1 i = Kit + Kit dx x x x And so dFi dFi1 Fi Fi1 + = + dx dx x x In a similar fashion it can be shown that dRi dRi1 Ri Ri1 + = + dx dx x x The above equations can be substituted into equation (3.7). dE 1 T Fi Fi1 Fi Fiint Fi1 Fiint 1 = lim [(Ui UiT )( + ) T ( + )] 1 i n dx 2 x x x x x x
n i=1

(3.8)

(3.9) (3.10)

(3.11)

(3.12)

(3.13)

Fi1 i where F x and x are the only remaining unknowns. The variable i is chosen such that these unknowns are eliminated.

i = Ui Ui1 6

(3.14)

By substituting i into equation (3.13), the variation of external work can be written as dE 1 T Fii nt Fiint 1 = lim [(Ui UiT + )] )( 1 n 2 dx x x
n i=1

(3.15)

In this optimization method, the topology can evolve by the removal or addition of elements. The variation in the objective, energy and volume upon element removal can be expressed as f (x) = 1 V (E E) V V n 1 T i int E = lim [(Ui UiT 1 )(Fi nt + Fi1 )] n 2
i=1

(3.16) (3.17) (3.18)

V = Vj

where Vj is the volume of the j th element. By rewriting equation (3.16) to a dimensionless form, the sensitivity number at end displacement can be expressed as
j n = j Vj En V E

(3.19)

The sensitivity number can have a positive or a negative value, which indicates that the objective function may decrease or increase upon element removal or addition. To maximize the objective function, solid elements (xj = 1) with the highest positive sensitivity number should be removed while void elements (xj = 0) with the lowest values should be added to the structure.

3.1.2

Sensitivity number for whole displacement history

The eects of removing an element on the objective will be dierent for various crushing distances. In order to achieve a high eciency for absorbing energy over the whole displacement history, the sensitivity number for the whole displacement history is dened. j =
n i=1 j i

(3.20)

In this chapter the crushing displacement will be gradually increased from 0 to Umax in 10 steps. The sensitivities will be calculated in every step. By using equation (3.20) for the calculation of the sensitivity number, the nal topology will have a high eciency for absorbing energy over the whole displacement history.

3.1.3

Evolutionary history of sensitivity number

To further increase the stability of the optimization process, the sensitivity number can be averaged as j =
k + k 1 j j

(3.21)

k is the sensitivity for the current (k -th) iteration and k1 is the sensitivity in the where j j previous (k 1th) iteration.

3.2

Checker-boarding suppression algorithm

Checkerboard patterns are quite common in various xed grid nite element based topology optimization methods. The BESO procedure is driven by elemental reference factors. In a continuum structure which is discretized using low order bilinear (2D) or trilinear (3D) elements, these reference factors could become discontinuous and result in checker-boarding as well as mesh-dependency. To prevent this, a simple checker-boarding suppression algorithm [5] will be adopted. In this method the elemental reference factors are smoothed out locally. First, the reference factors are calculated at every node by averaging the values of the elements connected to the node. M 1 l j l=1 Vl En en = (3.22) M1 V l l=1 where ej n represents nodal strain energies (without any physical meaning) of the j -th node and l represent the l-th M 1 denotes the total number of elements connected to the node. Vl and En elements initial volume and strain energy at the n-th increment respectively. Secondly the nodal strain energies are further averaged in order to calculate the improved elemental strain energies.
j En i i=1 w (rij )en = M2 i=1 w (rij )

M 2

(3.23)

where w(rij ) is a weighting factor and M 2 denotes the total number of nodes connected to the j -th element. The smoothing technique works as a lter based on a length-scale rmin . The weighting factor is dened as w(rij ) = rmin rij , (i = 1, 2, . . . , M 2) (3.24)

where rij is the distance from the center of the j th element to the ith node. In eect the lter smooths out the strain energies with a radius of rmin . As a rule of thumb the value for rmin should be at least two times larger than the element size to prevent checker-boarding. The lter also serves as a way to extrapolate the elemental reference factor to void elements.

3.3

Material removal/addition criterion

Conventional BESO methods (like in [3]) use a volume constraint. In the energy-absorption problem however there is only a constraint on the maximum crushing force. In order to satisfy that constraint, the volume is either decreased or increased. By decreasing the material volume, the part generally becomes more compliant and the maximum crushing force is consequently decreased. Vk+1 = Vk (1 ER) (3.25)

where ER is the evolutionary volume ratio. In this chapter ER = 0.01 is used. Similarly if the crushing force is below the maximum allowable crushing force, it can be increased by increasing the volume. Vk+1 = Vk (1 + ER) (3.26)

To ensure not too many elements are added in a single iteration, the admission volume ratio (AR) is introduced. The admission volume ratio is dened as the volume of added elements

divided by the total volume in the current design. The admission volume ratio must not be larger than the maximum admission volume ratio. AR ARmax (3.27)

where ARmax = 0.02 is used in this chapter. The sensitivities are calculated for all elements (both solid and void) and then sorted according to their value. Void elements (xj = 0) are switched on if
th j < add

(3.28)

And solid elements (xj = 1) are removed if


th j del

(3.29)

th and th are the sensitivity threshold values for the removal and addition of elements. where del add The threshold values are determined by the following simple steps: th = th = th . th can be determined by V Step 1: Let del k+1 . For example, if there are add 4000 identical elements in the design domain and 1 < 2 . . . < 4000 and Vk+1 corresponds to a design with 2300 elements then th = 2300 .

Step 2: Calculate the admission volume ratio. If AR ARmax skip step 3, otherwise th and th as in step 3. recalculate del add
th by rst sorting the sensitivity number of void elements (x = 0). Step 3: Calculate add j The volume of elements to be switched from 0 to 1 will be equal to ARmax multiplied th is the sensitivity number of the element by the total volume in the current design. add th is then determined so that the removed ranked just above the last added element. del volume is equal to (Vk+1 minus Vk plus the volume of the added elements).

3.4

Implementation using Abaqus

For the implementation of the mentioned optimization method, a combination of Abaqus with the python interface is used. The python script sets the initial design to a pre-made Abaqus model. Abaqus is then used to calculate forces and deformation of the model. These values are then used to calculate the sensitivity number for every element. The volume of the next design is determined by evaluating the crushing force, and the new design can be determined by evaluating the sensitivites. The new design can now be solved using FEA and the proces repeats itself untill convergence of the objective is reached. Figure 3.3 shows a ow chart of the iterative process.

Assign initial guess design

Solve model using FEA

Calculate sensitivities (j)

Determine volume next design (Vk+1) by evaluating the maximum crushing force (Fmax)

No

Determine admission volume ratio (AR)

Determine threshold sensitivity number (th)

Remove and add elements to assign new design

Has convergence been reached? Yes Current design (Vk) is optimal

Figure 3.3: Schematic of the topology optimization method for energy-absorbing structures. In practice, removing and then adding elements back into the model is very dicult. Therefore instead of actually deleting elements, its material properties (e.g. Youngs modulus and hardening modulus) can be reduced by a factor of 104 . The material properties of the deactivated elements will then approximately compare to the activated elements as air does to steel. The python script that is used to interface with Abaqus is included in appendix A.1.

3.5

Examples

In order to test the implementation of the optimization method, the examples discussed in [4] are used as a benchmark. The example in section 3.5.1 demonstrates how the optimization method can be used from an initial full design to nd an optimal design using both sensitivities for the end displacement (criterion 1) and for the whole displacement history (criterion 2). The second example (section 3.5.2) demonstrates how an initial guess design can be used to reduce computational time in nding the optimal design.

10

3.5.1

Example 1
U = 20 mm

20 mm 40 mm 40 mm

100 mm

Figure 3.4: Design domain, dimensions and boundary conditions for example 1. The gray area denotes the initial full design. A 100mm by 20mm beam is supported at 2 positions at the bottom (see gure 3.4) and a displacement load of U = 20mm is applied at the center of the top edge. The material is elastoplastic with Youngs modulus E = 200GP a, Poisson ratio v = 0.3, yield stress y = 300M P a and plastic hardening modulus Ep = 0.3E . The maximum allowable crushing force is set to 20kN and maximum crushing distance is set to 20mm. The design domain is discretized in 200 40 4-node plane stress elements. The evolutionary volume ratio is set to ER = 0.01, the admission volume ratio is ARmax = 0.02 and the mesh-independent lter radius is Rc = 3mm. The initial design has 100% of the solid material in the design domain. The evolutionary history of the optimization using both the sensitivity for end displacement (criterion 1) and the sensitivity for the whole displacement history (criterion 2) are shown in gure 3.5. BESO searches for an optimal design by removing and adding material. In both cases the absorbed energy per unit of volume generally increases as the volume decreases. The crushing force for the initial design is larger than the maximum allowable crushing force (see gure 3.6), therefore the volume is gradually decreased in order to meet the requirement. As the topology evolves, trusses emerge and are later destroyed. These changes in topology cause bumps in the absorbed energy per unit of volume.

11

80

40

64

0.8

32

E/V [MN/M ]

32

0.4

16

16

0.2

Vf Fmax E/V

20

40 60 Iteration []

80

0 100 50

80

64

0.8

40

E/V [MN/M ]

32

0.4

20

16

0.2

Vf Fmax E/V

10

20

40 60 Iteration []

80

0 100

Figure 3.5: Evolutionary histories of the volume fraction Vf , the absorbed energy per unit volume E/V and the maximum crushing force Fmax for example 1 using criterion 1 (top) and criterion 2 (bottom). As the volume is decreased the energy per unit of volume appears to converge to a maximum value for both cases. Eventually the requirement for the maximum crushing force is met. For criterion 2 this means the volume starts to vibrate as the crushing force goes below and above the maximum crushing force. For criterion 1 the volume increases a bit further as the crushing force remains below the maximum crushing force. Further iterations are required to nd the 12

Fmax [kN]

48 Vf []

0.6

30

Fmax [kN]

48 Vf []

0.6

24

optimal design for criterion 1.


40 Initial design Final Design criterion 1 Final Design criterion 2 30

Force [kN]

20

F=F*

10

0 0

10 Displacement [mm]

15

20

Figure 3.6: Force-displacement curves for optimal and initial full designs of example1. It is also noted that some iterations have no data points shown in gure 3.5. For criterion 1, the FEA simulations for designs 81, 92, 94, 95 and 97 did not converge. And for criterion 2, only designs 30, 33 and 60 are problematic. Because in this report elements are not actually removed but instead have reduced material properties, some designs may lead to FEA simulations that are very dicult to solve. To illustrate this problem, designs for two consecutive iterations are shown in gure 3.7. After iteration 93, some elements in the truss at the bottom are removed. This means that the elements Youngs modulus and hardening modulus are reduced by a factor of 10 4. As a result these elements become very compliant and show very large deformation because of the structures topology, making it dicult to solve the FEA simulation. The sensitivity numbers are still calculated from the last succesfull increment of the failed FEA simulation, and so the BESO program can continue.

Figure 3.7: Design for criterion 1 after 93 iterations (left) and design after 94 iterations (right) The nal designs for both the sensitivity for end displacement and the sensitivity for the whole displacement history are displayed in gure 3.8. Figure 3.9 shows the deformed nal designs. The nal design for criterion 1 is very simular to the result presented in the paper by X. Huang and Y.M. Xie [4]. The evolutionary history looks similar, and only deviates after about 50 iterations. The dierences in these result can be attributed to the problems in solving some designs. There are various ways to remove elements other than reducing its material parameters. Even the reduction factor (this study uses 104 ) can play a great role in the solvability of the design. Despite the dierences in evolutionary history it is very likely that with further iterations, the design after 100 iterations will evolve to the nal design presented in the paper by X. Huang and Y.M. Xie. The nal design using the sensitivity for the whole displacement history (criterion 2 in gures 3.8 and 3.9) is identical to the results in [4].

13

Figure 3.8: Final design for criterion 1 (top) and criterion 2 (bottom).

Figure 3.9: Final design for criterion 1 (top) and criterion 2 (bottom) after deformation.

3.5.2

Example 2
10 mm

U = 20 mm
\\\\\\\\\\\\\\\\\\

30 mm

200 mm

Figure 3.10: Design domain, dimensions and boundary conditions for example 2. The gray area denotes the initial guess design. A 200mm by 30mm beam is xed at both ends (see gure 3.10) and a rigid object impacts at the center of the top edge. The material is elastoplastic with Youngs modulus E = 1GP a, Poisson ration v = 0.3, yield stress y = 1M P a and plastic hardening modulus Ep = 0.1E . The maximum allowable crushing force is set to 70N and the maximum crushing distance is 14

set to 20mm. The design domain is discretized in 400 60 4-node plane stress elements. The evolutionary volume ratio is set to ER = 0.01, the admission volume ratio is ARmax = 0.02 and the mesh-independent lter radius is Rc = 3mm. In order to save computational time, an initial guess design can be set. In this example the initial design has 50% of the material in the design volume, as can be seen in gure 3.10.
25 1 100

20

0.8

80

E/V [kN/M ]

15 Vf []

0.6

60 Fmax [N]

10

0.4

40

0.2

Vf Fmax E/V

20

20

40 60 Iteration []

80

0 100 100

25

20

0.8

80

E/V [kN/M ]

15 Vf []

0.6

60 Fmax [N]

10

0.4

40

0.2

Vf Fmax E/V

20

20

40 60 Iteration []

80

0 100

Figure 3.11: Evolutionary histories of the volume fraction Vf , the absorbed energy per unit volume E/V and the maximum crushing force Fmax for example 2 using criterion 1 (top) and criterion 2 (bottom). 15

The evolutionary history of the optimization using both the sensitivity for end displacement (criterion 1) and the sensitivity for the whole displacement history (criterion 2) are shown in gure 3.11. This example illustrates how an initial guess design can save computational time. Both cases show how the energy per unit of volume converges to a maximum value after about 40 iterations. Just like in example 1 some designs are problematic to solve using FEA (design 7 for criterion 1 an design 21 for criterion 2), but the BESO program is able to continue by using data from the solved increments. The initial guess design satises the force requirement (as shown in gure 3.12), and therefore the volume is initially increased. Eventually the force requirement is violated and the volume is decreased in order to satisfy the requirement again. Finally convergence is reached and the volume vibrates within 1% of the current volume as the force constraint is satised and violated in two successive iterations.

70

F=F*

52.5 Force [N]

Initial design Final Design criterion 1 Final Design criterion 2

35

17.5

0 0

10 Displacement [mm]

15

20

Figure 3.12: Force-displacement curves for optimal and initial full designs of example2. The nal designs for both criteria are displayed in gure 3.13 (undeformed) and gure 3.14 (deformed). The designs and the evolutionary history are very similar to the results by by X. Huang and Y.M. Xie [4]. The initial guess design had a volume very close to the volume of the nal design, and convergence is reached quite fast. This shows how an initial guess design can save computational time.

Figure 3.13: Ultimate design for criterion 1 (top) and criterion 2 (bottom).

16

Figure 3.14: Ultimate design for criterion 1 (top) and criterion 2 (bottom) after deformation.

17

Chapter 4

Inverse shape optimization


Inverse shape optimization aims to optimize the design or shape of an initial congurations so that its deformed shape agrees to certain desirable criteria. Inverse shape optimization is especially useful for stent design. A stent is a mesh-like, dilatable structure which is inserted into various natural passages/conduits in the human body to counteract a disease-induced ow constriction. In order to insert a stent into the human body, it is only dilated (by means of ination) after insertion. The shape of the deformed stent is critical to its ability to function inside the human body. Therefore there is need for an algorithm to optimize the nal shape of the stent. In this chapter a simple algorithm for inverse shape optimization using Bi-directional Evolutionary Structural Optimization (BESO) [3, 1, 6] is presented.

4.1

Objective of the optimization method

In order to pose constraints on the structures deformed shape, it is assumed the design criteria can be translated into a combination of simple desired shapes such as circular and rectangular holes in a planar design domain (such as a the shell of a thin walled cylinder). The objective of the optimization will be to gradually minimize the distance of the border of these holes to the desired border. Similar to the BESO method used in Chapter 3, the design domain is divided into M elements that can either be removed or added to the design. The solution of the optimization can be expressed as xj {0, 1}, j = 1, . . . , M (4.1)

where the design variable xj declares the presence (1) or absence (0) of an element. Instead of mathematically dening the objective and deriving the sensitivities, so called indicator values will be used to determine which elements should be added or removed in an optimization process that is inspired by the BESO method. Indicator number for a circular hole For a circular hole with radius Rc , the indicator number is dened as j = Rc Sj Rc (4.2)

where j is the indicator of the j -th element and Sj is the distance from the center of element j to the center of the desired circular hole (see gure 4.1). The indicator number is dened such that elements near the center of the circle will have the highest positive values. Elements close to the center of the circle that are active (xj = 1) should 18

be the rst to be removed for a stable evolutionary process. Similarly, void (xj = 0) elements outside of the desired circle with the highest negative values should be the rst to be added. Furthermore an element is said to be inside the circle if the elements center is located inside the circular hole. Indicator number for a rectangular hole For a rectangular hole the indicator number is dened similarly as j = Rj Sj Rj (4.3)

where Rj is now the shortest distance from the center of the desired hole to the point on the border of the rectangle that is closest to the center of the j -th element (see gure 4.1). Similar to equation (4.2), elements close the the center of the rectangle will be the rst to
\ \\

\\

\\\

\\\\\\\\\\\\\\

\\

\\

\\

\\

\\
\\
\\

\\

\\

\\\

Rc

\\

\\\\\\\\\\\\\\\\\\\\\\\\\\\

\\

\\\

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

\\\\\\\\\\\\\\\\\\\\\\\\\\\

\\\\\\\\\\

\\\\\
\\\\\\\\

Rj

\\\\

\\\

\\\

\\ \

\ \\

\\

\\

Figure 4.1: Denitions of the distances used in equations (4.2) and (4.3) be deleted and elements outside of the square will have negative values proportional to their distance to the square. Figure 4.2 shows a contour-plot of the indicator numbers for a domain with a circular and a rectangular hole.
0 .6

50
1.

40 35 30

0
0.3

0
0

40 35 30 y 25 20
0 .6

0.3

25
1

0.5

0.3

20 15

0.5

15
1

.5

10 5

0 .5

0.3 0

10 5

10

20

30 x

40

50

60

70

10

20

30 x

40

50

0.

0.3

60

.3

0.6

0.3

45

0.5

50
1

5 0.

45

Figure 4.2: Contour graph of indicator numbers for a domain with a circular hole (left) with Rc = 15 and a 35 35 rectangular hole (right), both with the center at (35,25).

Combination of simple shapes In order to combine multiple simple holes of dierent size and shape, the indicator numbers of every element are calculated for each hole and the maximum value will be selected as the

19

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

\\

\\

\\

\\\

\\\\

\\\\\\\

\\\\ \\

\\

\\

\\

0.3

5 1.

0.3

0.5

0.6

0.5

0.6

0.3

0.5

0.5

0.3

0.6

0 .6

1 . 5

.6 0

.3

70

indicator number.
1 3 N j = max(j , j , . . . , j )

(4.4)

N is the elements indicator number where j is the indicator number for the j -th element, and j for the N -th circular or rectangular hole. Figure 4.3 shows an example of combined simple holes.

50
0.6
0.3

45 40 35 30 y 25
0

0 0
0.3

0.6

0.3

0.3

0.3

0.3
0 .3

0.6

0.6
0.3 0
0.3
0 .3
0.3
0.3

. 0 6

20 15 10

0.6

5 0.6

10

20

30 x

40

50

Figure 4.3: Indicator numbers for a domain with a 35 35 rectangular hole and a circular hole with Rc = 10 on one of its corners.

4.1.1

Evolutionary history of indicator number

To further increase the stability of the optimization process, the indicator number can be averaged as j =
k + k 1 j j

0. 3 0. 6

k is the indicator number for the current (k -th) iteration. k1 is the indicator number where j j in the previous iteration.

.6 0

(4.5)

4.2

Material removal/addition criterion

Similar to the method discussed in chapter 3, there is no volume constraint for this problem since the shape of the undeformed design is completely unknown. A volume constraint on the deformed volume is also problematic. A stent in a blood vessel is typically dilated by an applied pressure (for example with an inated balloon). The outer radius of the stent will become equal to the radius of the blood vessel, but the inner radius of the stent remains unknown. Instead of a volume constraint, the deformed shape is evaluated to determine if the volume needs to be increased or decreased. If the holes in the deformed shape are too large, than the volume of the design will be increased. Similarly the volume will be decreased when the holes in the deformed shape are too small. The indicator numbers are calculated for all elements (both solid and void) and then sorted according to their value. Void elements (xj = 0) are switched on if
th j < add

(4.6)

20

And solid elements (xj = 1) are removed if


th j del

(4.7)

th and th are threshold values for the removal and addition of elements respectively. where del add The threshold values are determined by the following simple steps: th = th = th . th can be determined by V Step 1: Let del k+1 . For example, if there add are 4000 same-size elements in the design domain and 1 < 2 . . . < 4000 and Vk+1 corresponds to a design with 2300 elements then th = 2300 .

Step 2: Calculate the admission volume ratio. If AR ARmax skip step 3, otherwise th and th as in step 3. recalculate del add
th by rst sorting the sensitivity number of void elements (x = 0). Step 3: Calculate add j The volume of elements to be switched from 0 to 1 will be equal to ARmax multiplied th is the sensitivity number of the element by the total volume in the current design. add th is then determined so that the removed ranked just above the last added element. del volume is equal to (Vk+1 Vk + the volume of the added elements).

In order to determine if the volume needs to be increased or decreased, the threshold indicator k number of the previous iteration is recalculated in the current design (prev.th. ). Consequently if in the current design there are deactivated elements located outside of the desired holes k (prev.th. < 0), the volume is increased: Vk+1 = Vk (1 + ER) (4.8)

Similarly the volume will be decreased when in the current design, activated elements are located k inside the desired holes (prev.th. 0). Vk+1 = Vk (1 ER) (4.9)

Unlike the previous chapter, the evolutionary volume ratio (ER) is now not xed. In order to increase stability and to prevent oscillating phenomena, the evolutionary volume ratio now depends linearly on the threshold indicator number of the previous iteration.
k ERk = ERinit prev.th.

(4.10)

where in this chapter the initial value for the evolutionary volume ratio is chose as ERinit = 0.05. k As the optimization converges, prev.th. will be come closer to zero and so ER will decrease. To prevent large changes in the design that may lead to instabilities, the volume addition ratio is introduced. AR ARmax (4.11)

where AR is dened as the volume of added elements divided by the total volume in the current design. ARmax = 0.02 is used in this chapter.

4.3

Implementation

For the implementation of the mentioned optimization method, a combination of Abaqus with the python interface is used. The python script sets the initial design to a pre-made Abaqus model. Abaqus is then used to calculate deformation of the model. The deformed coordinates of the elements are then used to calculate the indicator numbers for every element. The volume of the next design is determined by evaluating the threshold indicator number of the previous 21

iteration, and the new design can be determined by evaluating the indicator numbers. The new design can now be solved using FEA and the process repeats itself until convergence of the volume is reached. Figure 3.3 shows a ow chart of the iterative process.
Assign initial guess design

Solve model using FEA

Calculate indicator numbers (j)

Calculate the evolutionary volume ratio (ERk+1)

Determine volume next design (Vk+1) by k evaluating prev.th. No Determine admission volume ratio (AR)

Determine threshold indicator number (th)

Remove and add elements to assign new design

Has convergence been reached? Yes Current design (Vk) is optimal

Figure 4.4: Schematic of the inverse shape optimization method. Similar to chapter 3, elements are not actually removed. Instead their material properties (e.g. Youngs modulus and hardening modulus) are reduced by a factor of 104 . The python script that is used to interface with Abaqus is included in appendix A.2.

22

4.4
4.4.1

Examples
Example 1

U = 20 mm

50 mm

30 mm 70 mm 50 mm

Figure 4.5: Example 1: Dimensions and boundary conditions for the undeformed unknown shape (left) and the desired shape (right). A 70mm by 30mm plate is completely xed at the center of the left side and is xed in one direction along the rest of that side. The plate is compressed to a width of 50mm. The material is elastoplastic with Youngs modulus E = 210GP a, Poisson ration v = 0.3, yield stress y = 400M P a and plastic hardening modulus Ep = 0.2E . The design domain is discretized using 100 140 4-node plain stress elements. The goal of the optimization method is to create a design that will deform to a shape with a circular hole with a diameter of D = 30mm in its center. The initial design has 100% of the material.
10 1 1

0.8

0.8

ER [%]

V []

Vf k prev.th. ER

0.4

0.4

0.2

0.2

10

20

30 Iteration []

40

50

Figure 4.6: Example 1: Volume fraction, threshold value for the indicator number and evolutionary volume ratio. 23

prev.th. []

6
f

0.6

0.6

Figure 4.7: Example 1: Undeformed (left) and deformed shape (right) of the nal design.
k Figure 4.6 shows the evolutionary history of the optimization process. Initially prev.th. =1 k and therefore the volume is decreased in order to increase the size of the hole. As prev.th. approaches 0, the evolutionary volume ratio (ER) decreases as well. As a result the volume k decreases more slowly until prev.th. 0 and the evolutionary volume ratio becomes so small that no more elements can be added or removed. The nal shape after 50 iterations is presented in gure 4.7. The initial elliptical hole deforms under compression to an almost circular hole. The design can be further improved by decreasing the element-size. This result shows that the method is very successful for the inverse shape optimization of circular holes under compression.

4.4.2

Example 2

Example 2A

U = 20 mm

50 mm

35 mm

35 mm 70 mm 50 mm

Figure 4.8: Example 2A: Dimensions and boundary conditions for the undeformed unknown shape (left) and the desired shape (right). A 70mm by 30mm plate is completely xed at the center of the left side and is xed in one direction along the rest of that side. The plate is compressed to a width of 50mm. The material is elastoplastic with Youngs modulus E = 210GP a, Poisson ration v = 0.3, yield stress y = 400M P a and plastic hardening modulus Ep = 0.2E . The design domain is discretized using 100 140 4-node plain stress elements. The goal of the optimization method is to create a design that will deform to a shape with a rectangular hole with a dimensions: 35mm by 35mm in its center. The initial design has 100% of the material. 24

10

1 V
f k prev.th.

0.8

0.8

ER

0.6

0.4

0.2

0.2

20

40 60 Iteration []

80

0.2 100

Figure 4.9: Example 2A: Volume fraction, threshold value for the indicator number and evolutionary volume ratio. The deformed designs of iteration 94 and 95 are displayed to illustrate the oscillating behavior. The evolutionary history in gure 4.9 shows oscillations in the threshold value for the indicator number. This indicates that the size of the hole in the deformed material oscillates. The k volume fraction does not show this behavior. The volume keeps decreasing because prev.th. remains larger than zero. Therefore it must be concluded that the oscillatory behavior is caused by the way the geometry deforms.

Figure 4.10: Example 2A: Deformed shape of the design for two consecutive iterations. 94 iterations (left) and 95 iterations (right). Figure 4.10 shows the deformed shape of two consecutive iterations. After 94 iterations the deformed shape is very close to the desired shape, and the top and bottom edges buckle away from the center. Because there are some elements inside the desired hole at iteration 94, most of them are removed for the next iteration. As a result of this removal the new design now buckles in opposite direction. Because of the buckling in opposite direction, the deformed shape 25

prev.th. []

6 ER [%] V []
f

0.6

0.4

of design 95 is now more undesirable than design 94 was. Again the elements inside the desired shape that are closest to the center will be removed rst, and a shape similar to design 94 will emerge. This periodic occurrence is clearly visible in gure 4.9.

Figure 4.11: Example 2A: Undeformed (left) and deformed shape (right) of the design after 100 iterations. Figure 4.11 shows the nal design after 50 iterations. The deformed shape shows buckling both towards the center and away from the center. This is caused by a slight a-symmetry, and can be prevented by optimizing only a quarter of the design. This example illustrates how buckling is a severe limitation for the inverse shape optimization of rectangular holes under compression. The magnitude of the problem will depend on the size of the hole in relation to the part and the amount of compression. For example the problem will not exist if the same plate will be used for the inverse shape optimization of a very small rectangular hole. Example 2B

U = 20 mm

50 mm

20 mm
20 mm 50 mm

70 mm

Figure 4.12: Example 2B: Dimensions and boundary conditions for the undeformed unknown shape (left) and the desired shape (right). This example will demonstrate how buckling does not cause problems with inverse shape optimization of relatively small rectangular holes under compression. Similar to example 2A, a 70mm by 30mm is completely xed at the center of the left side and is xed in one direction along the rest of that side. The loading conditions and material properties are as before. The goal of the optimization method is to create a design that will deform to a shape with a rectangular hole with a dimensions: 20mm by 20mm in its center. The initial design has 100% of the material.

26

10

0.8

0.8

0.6

ER [%]

V []

Vf k prev.th. ER

0.4

0.2

0.2

10

20

30 Iteration []

40

50

0.2

Figure 4.13: Example 2B: Volume fraction, threshold value for the indicator number and evolutionary volume ratio. The evolutionary history is displayed in gure 4.13. Materials is removed and after 50 k iterations prev.th. 0. Buckling only takes place away from the center, and the nal design in gure 4.14 has an almost perfect rectangular hole.

Figure 4.14: Example 2B: Undeformed (left) and deformed shape (right) of the design after 50 iterations.

27

prev.th. []

6
f

0.6

0.4

4.4.3

Example 3

U = 40 mm

100 mm

40 mm

40 mm

80 mm

Figure 4.15: Example 3: Dimensions and boundary conditions for the undeformed unknown shape (left) and the desired shape (right). A 40mm by 100mm plate is completely xed at the center of the left side and is xed in one direction along the rest of that side. Tension is applied on the right side of the plate to increase its width to 80mm. The material is elastoplastic with Youngs modulus E = 210GP a, Poisson ration v = 0.3, yield stress y = 400M P a and plastic hardening modulus Ep = 0.2E . The design domain is discretized using 20 50 4-node plain stress elements. The goal of the optimization process is to create a design that under tension will deform to a shape with a circular hole of diameter of D = 40mm in its center. The initial design will be a projection of the desired shape on the elements, assuming they all deform uniformly.

28

10

0.6

0.8

0.3

0.4

0.3

0.2

Vf k prev.th. ER

0.6

10

20

30 Iteration []

40

50

0.9

Figure 4.16: Example 3: Volume fraction, threshold value for the indicator number and evolutionary volume ratio. The designs at some iterations are also displayed to illustrate the shape evolution.
k The evolutionary history (4.16) shows that as prev.th. initially approaches zero very rapidly, the value then begins to change periodically. During this periodic occurrence the volume fraction changes only slightly as the evolutionary volume ratio is very small. As a result only a few elements are removed or added in these iteration steps. The periodic occurrence is caused by elements that in one iteration become candidates for removal because they are inside the desired hole, while on the next iteration the deformation is slightly dierent and the elements are now outside the desired hole and again candidates to be added back to the design. The initial design has a volume fraction of Vf = 0.79, but does not appear to be a good guess for the nal design. k Initially the hole is too large as prev.th. < 0, and therefore material is added. The nal design after 50 iterations (gure 4.17) has a volume fraction of Vf 1 and is basically a gap the length of diameter of the desired circle.

29

prev.th. []

6 ER [%] V []
f

0.6

Figure 4.17: Example 3: Undeformed (left) and deformed shape (right) of the design after 100 iterations. Because the desired shape has a circular hole, there will be stress concentrations above and below the hole. Therefore the elements in that area will have a lot of deformation (see gure 4.17) while other element show little deformation. Since the removed elements are very compliant, they show extreme deformation. As a result the solution simply is a gap in the plate, creating a hole that is close to a circular shape. Optimization with a full initial design yields similar results.

4.4.4

Example 4

U = 40 mm

100 mm

40 mm

40 mm

40 mm

80 mm

Figure 4.18: Example 4: Dimensions and boundary conditions for the undeformed unknown shape (left) and the desired shape (right). A 40mm by 100mm plate is completely xed at the center of the left side and is xed in one direction along the rest of that side. Tension is applied on the right side of the plate to increase its width to 80mm. The material is elastoplastic with Youngs modulus E = 210GP a, Poisson ration v = 0.3, yield stress y = 400M P a and plastic hardening modulus Ep = 0.2E . The design domain is discretized using 20 50 4-node plain stress elements. 30

The goal of the optimization process is to create a design that under tension will deform to a shape with a rectangular hole with dimensions: 40mm by 40mm in its center. The optimization is done for an initial full design and an initial guess design. The initial guess design will be a projection of the desired shape on the elements, assuming they all deform uniformly.

10

0.9

0.8 Vf ER

0.6

0.4

0.2

0.3

10

20

30 Iteration []

40

50

0.6

Figure 4.19: Example 4 with full initial design: Volume fraction, threshold value for the indicator number and evolutionary volume ratio.

Figure 4.20: Example 4 with full initial design: Undeformed (left) and deformed shape (right) of the design after 100 iterations. 31

prev.th. []

6 ER [%] V []
f

0.6

prev.th.

0.3

The evolutionary history for the full design shows that the design initially decreases in volume and eventually increases to about 97% of the design domain. The nal design in gure 4.20 deforms to have a rectangular hole of the desired dimensions. Similar to the previous example the design has a gap the width of one element. Because a rectangular hole has no stress concentrations above and below the hole, the deformation does not localize.
10 1 0.9

0.8 Vf ER

0.6

0.4

0.2

0.3

10

20

30 Iteration []

40

50

0.6

Figure 4.21: Example 4 with initial guess design: Volume fraction, threshold value for the indicator number and evolutionary volume ratio.

32

prev.th. []

6 ER [%] V []
f

0.6

prev.th.

0.3

Figure 4.22: Example 4 with initial guess design: Undeformed (left) and deformed shape (right) of the design after 100 iterations. The nal result for optimization with the initial guess design is very similar. However because of the dierence in evolutionary history, the gap in the nal design now has a width of two elements. The initial guess design is not very close to the nal design, and therefore even more iterations are needed for convergence that with the initial full design. It is noted that the nodes to the left and right of the rectangular hole in both solutions show little deformation. Therefore if the goal would have been a rectangular hole with a smaller width, a satisfactory solution may not have been found (if it even exists at all).

33

Chapter 5

Conclusion
In this report a new shape optimization method (called inverse shape optimization) is introduced that can be used to optimize the geometry of stents. The method is based on the bi-directional evolutionary structural (BESO) optimization method. The implementation of the BESO method was benchmarked by reproducing the results from a paper by Huang, Xie and Lu [4] on topology optimization of energy-absorbing structures. The topology optimization examples discussed in chapter 3 lead to results that are almost identical as the paper by Huang et. al.. In this report the BESO method is implemented in such a way that elements are not actually removed, but instead their Youngs and hardening modulus are reduced by a factor 10 4. Removed elements become extremely compliant, and this becomes problematic when some designs have extreme deformation of these removed elements. These designs are very dicult to solve using FEA. But despite some failed FEA simulations, the BESO method is still able to continue and optimal designs are found. The inverse shape optimization method aims to optimize the undeformed shape of a product such that its deformed shape agrees to certain criteria. In order to pose constraints on the structures deformed shape, it is assumed the design criteria can be translated into a combination of simple desired shapes such as circular and rectangular holes in a planar design domain (such as a the shell of a thin walled cylinder). The objective of the optimization is to gradually minimize the distance of the border of these holes to the desired border. So called indicator numbers are calculated for elements in the design domain to determine what elements should be removed or added. Elements close to the center of a desired hole will be the rst be removed, and elements outside the desired hole that are the farthest away from the center will be the rst to be added back to the design. The examples in chapter 4.4 demonstrate the inverse shape optimization method under large deformation in both compression and tension. The examples show that the method is very successful for the inverse shape optimization of circular holes under compression. Inverse shape optimization of rectangular holes under compression is limited because of the deformation mechanism. If the size of the rectangular hole in relation to the entire part is too large, the method becomes unstable because the direction of buckling may change with very small changes to the design. This does not occur when the size of the rectangular hole is suciently small with respect to the entire part. Inverse shape optimization of a circular hole under tension is problematic. The circular shape of the desired hole causes stress concentrations. Elements near the stress concentrations will have a lot of deformation, and as a result the nal design of the optimization method is a gap the with of one element. After deformation this gap does not deform to a perfect circle.

34

This problem does not occur with the inverse shape optimization of a rectangular hole. There are no stress concentrations in the nal design, and after deformation the shape is very close to a rectangular hole.

35

Bibliography
[1] T. Buhl, C.B.W. Pedersen, and O. Sigmund. Stiness design of geometrically nonlinear structures using topology optimization. Struct. Multidisc. Optim., 19:93104, 2000. [2] D. Nha Chu, Y.M. Xie, A. Hira, and G.P. Steven. Evolutionairy stuctural optimization for problems with stiness constraints. Finite Elements in Analysis and Design, 21:239251, 1996. [3] X. Huang and Y.M. Xie. Evolutionary topology optimization of continuum structures: methods and applications. Wiley, 2010. [4] X. Huang, Y.M. Xie, and G. Lu. Topology optimization of energy-absorbing structures. Int. j. Crashworthiness, 12:663675, 2007. [5] Q. Li, G.P. Stevens, and Y.M. Xie. A simple checkerboard suppression algorithm for evolutionary structural optimization. Struct. Multidisc. Optim., 22:230239, 2001. [6] C.B.W. Pedersen. Topology optimization for crashworthiness of frame structures. Int. j. Crashworthiness, 8:2939, 2003. [7] C.B.W. Pedersen. Topology optimization of 2d-frame structures with path-dependent response. Int. j. Numer. Methods. Engrg., 57:14711501, 2003. [8] C.B.W. Pedersen. Crashworthiness design of transient frame structures using topology optimization. Comput. Methods Appl. Mech. Engrg., 193:653678, 2004. [9] C.B.W. Pedersen, T. Buhl, and O. Sigmund. Topology synthesis of large-displacement compliant mechanisms. Int. j. Numer. Methods. Engrg., 50:26832705, 2001.

36

Appendix A

Python code
A.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

Topology optimization of energy-absorbing structures

# ############################################################ ## Topology optimization of energy - absorbing structures ## ## - Sydney , January 15 th 2010 by Edward de boer ## ## ## # # This script optimizes the topology of a 2 D discretized ## # # model in Abaqus by removing and adding back elements to ## # # maximize the structure s energy absorption . ## # # The script is based on the paper by X . Huang , Y . M . Xie ## # # and G . Lu : " Topology optimization of energy - absorbing ## # # structures " , and is created as a benchmark on research ## # # on shape optimization by Edward de Boer . ## ## ## # # In order to run the script succesfully , all the ## # # parameters under the header " INPUT PARAMETERS " need to ## # # be set in accordance with the Abaqus model used . ## ## ## # # Warning : To be used with Abaqus 6.7 only . Newer ## # # versions of Abaqus ( I . E . 7.9) have been known to crash ## # # without warning during long simulations . ## # ############################################################ from abaqus import * from abaqusConstants import * from math import * import sys print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # print ###### starting python sctipt ###### print ###### Created by Edward de Boer ###### print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ############################################################ # -- STARTING UP -- # from part import * from material import * from section import * from assembly import * from step import * from interaction import * from load import * from mesh import * from job import *

37

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

from sketch import * from visualization import * from connec torBeh avior import * import regionToolset # ############################################################ # -- INPUT PARAMETERS -- # OutputDirectory = / home / chaiy / Desktop / Edward / Example2_Case1 / # OutputDirectory is where the output txt - files are stored . WorkDirectory = OutputDirectory # WorkDirectory is where the job files are stored . AssignSections = 0 # AssignSections = [0 or 1] : Assign materials to mesh - elements . C al cu l ate C o n n e c t i v i t y = 0 # C a lc u lat e C o n n e c t i v ity = [0 or 1] : Make a large matrix with # elemental and nodal connectivity , required for simulation . Continue = 0 # Continue = [0 or 1] : Continue a simulation at the next iteration . # The topology of the current iteration is read from the materials # in the Abaqus model . EvaluateElements = 1 # EvaluateElements = [0 or 1] : Create sets with the # activated and deactivated elements , to be used for visualization . Criterion = 1 # Criterion = [1 or 2] : Calculate sensitivity at end displacement (1) # or calculate sensitivities at whole displacement history (2). Example = 2 # Example = [1 or 2] : Use the model for example 1 or 2. MaxIter = 100 # Maxiimum number of iterations . ConvLimit = 0.0001 # Convergence limit . Convergence = 1 # Initial value for Convergence . Rmin = 3 # Mesh independent filter radius in [ mm ]. ER = 0.01 # Evolutionary volume ratio . ARMax = 0.02 # Maximum Admission volume ratio : Volume of added elements divided by # the total volume in the current design . # Example 1 and 2 use different models and materials if Example == 1: # Abaqus model paramters :

38

100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157

NumberOfElems =4000 NumberOfNodes =4141 JobNamePrefix = Exa mple _1_ _ C r ite rio n _ + str ( Criterion )+ __ PartName = Example1 # Material paramters : YM = 200 e3 ReducedYM = 0.0001 * YM PR = 0.3 SY = 300 YMP = 0.3 * YM ReducedYMP = 0.3 * ReducedYM FStar = 20 e3 / 2 # Fstar is half ( because half of the beam is modelled ) of # the maximum crushing force in [ N ] TotalV0 = 100.0 * 20.0 / 2 # TotalV0 is half of the total initial ( undeformed ) volume [ mm ^2]. elif Example == 2: # Abaqus model paramters : NumberOfElems =12000 NumberOfNodes =12261 JobNamePrefix = Exa mple _2_ _ C r ite rio n _ + str ( Criterion )+ __ PartName = Example2 # Material paramters : YM = 1 e3 ReducedYM = 0.0001 * YM PR = 0.3 SY = 1 YMP = 0.1 * YM ReducedYMP = 0.1 * ReducedYM FStar = 70 / 2 # Fstar is half of the maximum crushing force in [ N ] TotalV0 = 200.0 * 30.0 / 2 # TotalV0 is half of the total initial ( undeformed ) volume # Names used in Abaqus : ModelName = EnergyAbsorption StepName = Displacement SetName = Displaced # ############################################################ # -- SETTING UP INITIAL GEOMETRY -- # if Example == 1: X = [1 for a in range ( NumberOfElems )] # X is an array that holds the presence of every element [0 or 1]. # For example 1 , every element is initially present InitialV0 = TotalV0 # InitialV0 is the volume of the present elements elif Example == 2: X = [1 for a in range ( NumberOfElems )] # X is an array that holds the presence of every element [0 or 1].

39

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215

EN = 1 # Element Number while EN <= NumberOfElems : if EN <= NumberOfElems /2: x = 0 else : x = 1 X [ EN -1] = x EN = EN + 1 # For example 2 , half of the elements are initially present InitialV0 = TotalV0 / 2 # InitialV0 is the volume of the present elements # ############################################################ # -- CREATE MATERIALS -- # PlasticP roper ties = (( SY , 0.0) , ( SY + YMP * 1 , 1)) R e d u c e d Pl a s t i c P r o p e r t i es = (( SY , 0.0) , ( SY + ReducedYMP * 1 , 1)) EN = 1 if Continue == 1: # To Continue the script , the last iteration is taken as the current . InitialIter = Iter # The abaqus model s materials are read to determine absent elements . while EN <= NumberOfElems : MN = Material - E + str ( EN ) print Now reading Material number , EN Elastic Prope rties = mdb . models [ ModelName ]. materials [ MN ]. elastic # Elast icProperties refers to the elastic properties of the # EN - th element if Elastic Properties . table [0][0] == ReducedYM : X [ EN -1] = 0 EN = EN + 1 else : EN = EN +1 else : # If the script is not continued , it starts at iteration 1 InitialIter = 1 Iter = InitialIter V0 = InitialV0 while EN <= NumberOfElems : # Every element has an identical material assigned to it . # Array X is read to determine the material properties . MN = Material - E + str ( EN ) print Now assigning Material number , EN mdb . models [ ModelName ]. Material ( name = MN ) if X [ EN -1] == 1: mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( YM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = PlasticProp erties ) else : mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( ReducedYM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = R e d u ce d P l a s t i c Pr o p e r t i e s ) EN = EN +1 # ############################################################ # -- ASSIGN SECTIONS -- #

40

216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273

if AssignSections == 1: # The materials need to be assigned to sections ( elements ) in Abaqus EN = 1 while ( EN <= NumberOfElems ): SN = Section - E + str ( EN ) MN = Material - E + str ( EN ) print Now assigning Section number , EN mdb . models [ ModelName ]. H om o ge ne o us S o l i d S e c t i o n ( name = SN , material = MN , thickness =1) element = mdb . models [ ModelName ]. parts [ PartName ]. elements [ EN -1: EN ] region = regionToolset . Region ( elements = element ) mdb . models [ ModelName ]. parts [ PartName ]. Secti onAssi gnment ( region = region , sectionName = SN ) EN = EN + 1 else : print No need to assign any Sections ! # -- CALCULATING NODAL AND ELEMENTAL CONNECTIVITY -- # if C al c ul a t e C o n n e c t i vi ty == 1: Noda lConne ctivit y = [[] for b in range ( NumberOfNodes )] # NodalCon nectiv ity [ NN -1] is a matrix that shows which elements # ( EN ) are connected to a node ( NN ). El e men t a l C o n n e c t ivit y = [[] for b in range ( NumberOfElems )] # El em e n t a l C o n n e c tivi ty [ EN -1] is a matrix that shows which nodes # ( NN ) are connected to an element ( EN ). EN = 1 while EN <= NumberOfElems : Element = mdb . models [ ModelName ]. parts [ PartName ]. elements [ EN -1] connectivity = Element . connectivity i = 0 while i < 4: El e m e n t a lCo nnec tivit y [ EN -1]. append ( connectivity [ i ]+1) Nod alConnectivity [ connectivity [ i ]]. append ( EN ) i = i + 1 EN = EN + 1 W = [[[] for b in range ( NumberOfElems )] for a in range ( NumberOfNodes )] # W [ EN -1][ NN -1] is a matrix that contains weighting factors used for # the mesh - independent filter . # -- CALCULATE W ( Rij ) FOR EVERY NODE - VERY TIME - COSTLY EN = 1 while EN <= NumberOfElems : print Now calculating connectivity for Element : , EN k = 1 coor = [[] for b in range (4)] # coor is an array that contains the coordinates for all 4 # nodes connected to the element EN . while k <= 4: NN = E l e men talC onne c t i vi t y [ EN -1][ k -1] Node = mdb . models [ ModelName ]. parts [ PartName ]. nodes [ NN -1] coor [k -1] = Node . coordinates k = k + 1 k = 1 xc = [0 ,0 ,0] # xc is array with the coordinates of the center of element EN .

41

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331

while k <= ncn : i = 1 while i <= 3: xc [i -1] = xc [i -1] + (1/ ncn ) * coor [k -1][ i -1] i = i + 1 k = k + 1 NN = 1 a = 0 b = 0 # Next W [ EN -1][ NN -1] is calculated . while NN <= NumberOfNodes : Node = mdb . models [ ModelName ]. parts [ PartName ]. nodes [ NN -1] xn = Node . coordinates Rij = sqrt (( xn [0] - xc [0])**2+( xn [1] - xc [1])**2 +( xn [2] - xc [2])**2) if Rij > Rmin : W [ NN -1][ EN -1] = 0 else : W [ NN -1][ EN -1] = Rmin - Rij NN = NN + 1 EN = EN + 1 else : print No need to calculate connectivity ! # ############################################################ # -- WRITE TO OUTPUT - FILES -- # MyO ut p utF i le I t e r D a t a = open ( OutputDirectory + IterData . txt , w ) # IterData . txt is updated after every iteration . MyOu t put S ym m a ry F i le = open ( OutputDirectory + Summary . txt , w ) MyOu t put S ym m a ry F i le . write ( Example =%6 d Criterion =%6 d F *=%6 d \ n %( Example , Criterion , FStar )) MyOu t put S ym m a ry F i le . write ( NumberOfElems =%6 d NumberOfNodes =%6 d MaxIter =%6 d \ n %( NumberOfElems , NumberOfNodes , MaxIter )) MyOu t put S ym m a ry F i le . write ( ER =%6 d ARMax =%6 d Rmin =%6 d \ n %( ER , ARMax , Rmin )) MyOu t put S ym m a ry F i le . write ( YM =%8 f ReducedYM =%8 f PR =%8 f \ n %( YM , ReducedYM , PR )) MyOu t put S ym m a ry F i le . write ( YMplastic =%6 d ReducedYMplastic =%6 d SY =%6 d \ n %( YMP , ReducedYMP , SY )) MyOu t put S ym m a ry F i le . close () # Symmary . txt contains information on the initial parameters . MyOutputFile = open ( OutputDirectory + Output . txt , w ) # MyOutputFile contains all lines that are printed in Abaqus F = [[] for b in range ( MaxIter )] # F is an array that contains the magnitude of the objective for # every iteration . # ############################################################ # -- START OF ITERATION LOOP -- # print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # print ###### Start of the iteration loop ###### print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # while ( Iter <= MaxIter ):

42

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389

# ############################################################ # -- MAKING " SET " LISTS OF ACTIVE AND INACTIVE ELEMENTS -- # if EvaluateElements == 1: # X is evaluated and arrays with present and absent elements # are made . These arrays are then stored in sets in Abaqus . Activat edEle ments = [] De ac t i va t e dE lements = [] EN = 1 print Now Evaluating the state of the Elements while EN <= NumberOfElems : if X [ EN -1] == 1: ActivatedElements . append ( EN ) else : De ac tivatedElemen t s . append ( EN ) EN = EN + 1 mdb . models [ ModelName ]. parts [ PartName ]. S e t F r o m E l e m e n t L a b e l s ( name = A ctivatedElements _ + str ( Iter ) , elementLabels = Ac tivatedEleme nts ) mdb . models [ ModelName ]. parts [ PartName ]. S e t F r o m E l e m e n t L a b e l s ( name = D e activatedEl eme n ts_ + str ( Iter ) , elementLabels = Deac t ivat ed El em e n ts ) else : print Skipping the evaluation of elements . # ############################################################ # -- CREATING A JOB -- # JobName = JobNamePrefix + str ( Iter ) mdb . Job ( name = JobName , model = ModelName , type = ANALYSIS , explici tPrec ision = SINGLE , no d alO u t p u t P r e c i s i o n = SINGLE , description = , p a r a l l e l i z a t i o n M e t h o d E x p l i c i t = DOMAIN , mu lt i p ro c e ss ingMode = DEFAULT , numDomains =4 , userSubroutine = , numCpus =4 , st a n d a r d M e m o ryPolicy = MODERATE , scratch = , echoPrint = OFF , modelPrint = OFF , contactPrint = OFF , historyPrint = OFF ) # ############################################################ # -- SUBMITTING THE JOB -- # mdb . jobs [ JobName ]. submit ( con s iste nc yC he c k in g = OFF ) mdb . jobs [ JobName ]. waitForCompletion () # ############################################################ # -- OPENING THE RESULTS -- # myOdb = openOdb ( path = JobName + . odb ) DisplacementStep = myOdb . steps [ StepName ] SE = [[] for b in range ( len ( DisplacementStep . frames ))] # SE [I -1]: array that contains the strainenergy for every increment . ISE = [[] for b in range ( len ( DisplacementStep . frames ))] # ISE [I -1]: array that contains the improved total strainenergy # for every increment . V = [[] for b in range ( len ( DisplacementStep . frames ))] # V [I -1]: array that contains the deformed volume for every incr . EV = [[] for b in range ( len ( DisplacementStep . frames ))]

43

390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447

# EV [I -1][ EN -1]: a matrix with the elemental volumes at every incr . IESE = [[] for b in range ( len ( DisplacementStep . frames ))] # IESE [I -1][ EN -1]: a matrix with the elemental improved strain # energies at every increment . MaxRF = [[] for b in range ( len ( DisplacementStep . frames ))] # MaxRF [I -1]: an array with the crushing force for every incr . # ############################################################ # -- LOOP OVER INCREMENTS -- # Increment = 1 while Increment <= len ( DisplacementStep . frames ): CurrentFrame = DisplacementStep . frames [ Increment -1] # ############################################################ # -- GETTING OUTPUT FROM ABAQUS -- # ReactionForce = CurrentFrame . fieldOutputs [ RT ] Re ac t i on F o rc eValues = ReactionForce . values EStrainEnergy = CurrentFrame . fieldOutputs [ ELSE ] ES tr a i nE n e rg yValues = EStrainEnergy . values NodalCoordinates = CurrentFrame . fieldOutputs [ COORD ] MyRF = [] MyESE = [] MyNX1 = [] MyNX2 = [] MyEV = [] for v in NodalCoordinates . values : MyNX1 . append ( v . data [0]) MyNX2 . append ( v . data [1]) # MyNX1 and MyNX2 contain nodal coordinates for all nodes . for v in R ea ctionForce Valu es : MyRF . append ( v . data [1]) # MyRF contains the reaction force in y direction for all nodes . for v in E St rainEnergy Valu es : MyESE . append ( v . data ) # MyESE contains the strain energies for all elements . # ############################################################ # -- PROCESSING OUTPUT -- # EN = 1 while EN <= NumberOfElems : k = 1 coor = [[] for b in range (4)] # coor [k -1] is an array that holds the coordinates for all # nodes connected to element EN while k <= 4: NN = Elem enta lC o n n e cti vit y [ EN -1][ k -1] coor [k -1] = ( MyNX1 [ NN -1] , MyNX2 [ NN -1] ,0) k = k + 1 k = 1 xe = [0 ,0 ,0]

44

448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505

# xe : Array with coordinates of the center of element EN . while k <= 4: i = 1 while i <= 3: xe [i -1] = xe [i -1] + (1/ ncn ) * coor [k -1][ i -1] i = i + 1 k = k + 1 # Next the 2 D volume of the element is calculated because # Abaqus s " EVOL " value doesnt give the deformed volume for # a 2 D problem . The 2 D elemental volumes are stored in the # array MyEV . AC = ( coor [2][0] - coor [0][0] , coor [2][1] - coor [0][1] , coor [2][2] - coor [0][2]) BD = ( coor [3][0] - coor [1][0] , coor [3][1] - coor [1][1] , coor [3][2] - coor [1][2]) VV = [[] for a in range (3)] VV [0] = AC [1]* BD [2] - AC [2]* BD [1] VV [1] = AC [2]* BD [0] - AC [0]* BD [2] VV [2] = AC [0]* BD [1] - AC [1]* BD [0] ev = 0.5 * sqrt (( VV [0])**2+( VV [1])**2+( VV [2])**2) MyEV . append ( ev ) EN = EN + 1 MyNSE = [] # MyNSE [ NN -1] is an array with nodal strain energies . NN = 1 while NN <= NumberOfNodes : k = 1 a = 0 b = 0 while k <= len ( NodalConn ectivi ty [ NN -1]): if X [ NodalConnectivity [ NN -1][ k -1] -1] == 1: ESE = MyESE [ NodalConnecti vity [ NN -1][ k -1] -1] a = a + ( TotalV0 / NumberOfElems ) * ESE b = b + ( TotalV0 / NumberOfElems ) k = k + 1 else : k = k + 1 if b == 0: MyNSE . append (0) else : MyNSE . append ( a / b ) NN = NN + 1 MyIESE = [] # MyIESE [ EN -1] : Array with improved elemental strain energies . EN = 1 while EN <= NumberOfElems : a = 0 b = 0 NN = 1 while NN <= NumberOfNodes : a = a + W [ NN -1][ EN -1] * MyNSE [ NN -1] b = b + W [ NN -1][ EN -1] NN = NN + 1 MyIESE . append ( a / b )

45

506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563

EN = EN + 1 Volume = 0 StrainEnergy = 0 Im p r o v e d S t r a inEnergy = 0 # The total volume and strain energie can now be calculated by # summing the elements . Note that only solid element contribute # to the volume , while void elements do contribute to the strain # energy . StrainEnergy and I m pro v e d S t r a i n E n e r g y should be equal . EN =1 while EN <= NumberOfElems : if X [ EN -1] == 1: Volume = Volume + MyEV [ EN -1] else : Volume = Volume StrainEnergy = StrainEnergy + MyESE [ EN -1] I m p r o v e d StrainEnergy = I mpr o v e d S t r a i n E n e r g y + MyIESE [ EN -1] EN = EN + 1 MaxReactionForce = 0 # MaxReactionForce is the crushing force , and is the sum # of the reactionforces in y diraction in the nodes where the # displacement is applied . SetName is a set that contains all # nodes where the displacement is applied . i = 1 NodeSet = mdb . models [ ModelName ]. parts [ PartName ]. allSets [ SetName ] while i <= len ( NodeSet . nodes ): EN = NodeSet . nodes [i -1]. label MaxReactionForce = MaxReactionForce + MyRF [ EN -1] i = i + 1 # All important values for this increment are stored in arrayw . SE [ Increment -1] = StrainEnergy V [ Increment -1] = Volume EV [ Increment -1] = MyEV MaxRF [ Increment -1] = MaxReactionForce ISE [ Increment -1] = Imp rov e dSt r ain E n e r g y IESE [ Increment -1] = MyIESE Increment = Increment + 1 # In order to determine the volume ratio later on , it is important # to store the deformed volume of the initial design . if Iter == 1: InitialVolume = Volume # ############################################################ # -- CALCULATING SENSITIVITY NUMBERS -- # Alpha = [] # Alpha [ EN -1] is an array containing the sensitivities per element # and the element number ( EN ). EN =1 alpha = 0 while EN <= NumberOfElems : Increment = 1 while Increment <= len ( DisplacementStep . frames ): vj = TotalV0 / NumberOfElems # Same - size elements are used . ejn = IESE [ Increment -1][ EN -1]

46

564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621

v = V0 e = SE [ Increment -1] if e == 0: # To prevent division by 0 , make alpha = 0. Ealpha = 0 else : Ealpha = vj / v - ejn / e # Sensitivity for criterion 1 & 2 are calculated differently . if Criterion == 1: alpha = Ealpha else : alpha = alpha + Ealpha if Increment == len ( DisplacementStep . frames ): if Iter > 1: # Starting from the 2 nd iteration , the sensitivities # are averaged with values from previous iteration . alpha = ( alpha + OldAlpha [ EN -1][0]) / 2 else : alpha = alpha Alpha . append ([ alpha , EN ]) alpha = 0 else : alpha = alpha Increment = Increment + 1 EN = EN + 1 # ############################################################ # -- REMOVING AND ADDING ELEMENTS -- # SortedAlpha = sorted ( Alpha ) # The sensitivities are sorted from low to high . CrushingForce = abs ( min ( MaxRF )) # CrushingForce is the maximum ( largest negative value ) crushing # force . This is not always the crushing force after last increment . if CrushingForce > FStar : V0k = V0 *(1 - ER ) else : V0k = V0 *(1 + ER ) TH = int (( V0k / TotalV0 ) * NumberOfElems ) + 1 # TH is the number of elements in the new design . AlphaTH = SortedAlpha [ TH -1][0] # AlphaTH is the threshold sensitivity value . SI = 1 AR = 0 # AR is the admission volume ratio . while SI < TH : EN = SortedAlpha [ SI -1][1] if X [ EN -1] == 0: AR = AR + ( TotalV0 / NumberOfElems ) / V0 else : AR = AR SI = SI + 1 print # ... At Iteration # , Iter , CrushingForce = , CrushingForce ,\ , AR = ,AR , , and TH = ,TH , and Convergence = , Convergence , ... MyOutputFile . write ( # ... At Iteration # + str ( Iter ) + CrushingForce = + str ( CrushingForce )+ , AR = + str ( AR )

47

622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679

+ , and TH = + str ( TH )+ and Convergence = + str ( Convergence ) + ...\ n ) SI = 1 if AR <= ARMax : # If not too many elements are added in this iteration , elements # can be removed and added . The volume is immediately updated . while SortedAlpha [ SI -1][0] < AlphaTH : EN = SortedAlpha [ SI -1][1] if X [ EN -1] == 0: print # ... , at Iteration # , Iter ,\ - Adding Element Number : ,EN , with SI = ,SI ,\ V0 = ,V0 , and V0k = ,V0k , ... MyOutputFile . write ( # ... + at Iteration # + str ( Iter ) + - Adding Element Number : + str ( EN )+ with SI = + str ( SI )+ V0 = + str ( V0 )+ and V0k = + str ( V0k ) + ...\ n ) MN = Material - E + str ( EN ) mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( YM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = PlasticP roperties ) X [ EN -1] = 1 Volume = Volume + EV [ -1][ EN -1] V0 = V0 + TotalV0 / NumberOfElems SI = SI + 1 else : SI = SI + 1 SI = NumberOfElems while SortedAlpha [ SI -1][0] >= AlphaTH : EN = SortedAlpha [ SI -1][1] if X [ EN -1] == 1: print # ... , at Iteration # , Iter ,\ - Removing Element Number : ,EN , with SI = ,SI ,\ V0 = ,V0 , and V0k = ,V0k , ... MyOutputFile . write ( # ... + at Iteration # + str ( Iter )+ - Removing Element Number : + str ( EN ) + with SI = + str ( SI )+ V0 = + str ( V0 ) + and V0k = + str ( V0k )+ ...\ n ) MN = Material - E + str ( EN ) mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( ReducedYM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = R e du c e d Pl a s t i c P r o p e r t i e s ) X [ EN -1] = 0 Volume = Volume - EV [ -1][ EN -1] V0 = V0 - TotalV0 / NumberOfElems SI = SI - 1 else : SI = SI - 1 else : i = 1 k = 1 while i <= ( ARMax * NumberOfElems ): AddElem = SortedAlpha [k -1][1] if X [ AddElem -1] == 0: print # ... , at Iteration # , Iter ,\ - Adding Element Number : , AddElem ,\

48

680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737

V0 = ,V0 , and V0k = ,V0k , ... MyOutputFile . write ( # ... + at Iteration # + str ( Iter ) + - Adding Element Number : + str ( EN )+ V0 = + str ( V0 )+ and V0k = + str ( V0k )+ ...\ n ) MN = Material - E + str ( AddElem ) mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( YM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = PlasticP roperties ) X [ AddElem -1] = 1 Volume = Volume + EV [ -1][ AddElem -1] V0 = V0 + TotalV0 / NumberOfElems i = i + 1 k = k + 1 else : k = k + 1 i = 1 while V0 > V0k : DelElem = SortedAlpha [ - i ][1] if X [ DelElem -1] == 1: print # ... , at Iteration # , Iter ,\ - Removing Element Number : ,\ DelElem , V0 = ,V0 , and V0k = ,V0k , ... MyOutputFile . write ( # ... + at Iteration # + str ( Iter ) + - Removing Element Number : + str ( EN )+ V0 = + str ( V0 )+ and V0k = + str ( V0k )+ ...\ n ) MN = Material - E + str ( DelElem ) mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( ReducedYM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = R e du c e d Pl a s t i c P r o p e r t i e s ) X [ DelElem -1] = 0 i = i + 1 Volume = Volume - EV [ -1][ DelElem -1] V0 = V0 - TotalV0 / NumberOfElems else : i = i +1 # ############################################################ # -- WRITING SOME OUTPUT -- # My O utp u t F i l e I t e r Data . write ( str ( Iter )+ + str ( SE [ -1])+ + str ( SE [ -1] / V [ -1]) + + str ( CrushingForce )+ + str ( V0 / TotalV0 )+ \ n ) MyOutputFileIter = open ( OutputDirectory + ITER_ + str ( Iter ) + . txt , w ) MyOutputFileIter . write ( Iter =%6 d E =%8 f F =%8 f V =%8 f Vf =%8 f V0 =%8 f + V0f =%8 f Convergence =%8 f \ n %( Iter , SE [ -1] , CrushingForce , Volume , Volume / InitialVolume , V0 , V0 / TotalV0 , Convergence )) MyOutputFileIter . close () # ITER_ #. txt is created every # - th iteration and contains strain # energy and volume fractions . MyOutputFileX = open ( OutputDirectory + X_ + str ( Iter )+ . txt , w ) EN =1 while EN <= NumberOfElems : MyOutputFileX . write (( str ( EN )+ + str ( X [ EN -1])+ \ n ))

49

738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795

EN = EN +1 MyOutputFileX . close () # X_ #. txt is created every # - th iteration and contains the array # X which is the variable that needs to be optimized MyOutputFileF = open ( OutputDirectory + FMax_ + str ( Iter )+ . txt , w ) Increment =1 while Increment <= len ( DisplacementStep . frames ): MyOutputFileF . write (( str ( Increment )+ + str ( MaxRF [ Increment -1])+ \ n )) Increment = Increment +1 MyOutputFileF . close () # FMax_ #. txt is created every # - th iteration and contains the # maximum crushing force at every displacement - increment . MyOu tputFi leAlph a = open ( OutputDirectory + Alpha_ + str ( Iter )+ . txt , w ) EN =1 while EN <= NumberOfElems : MyOutpu tFile Alpha . write (( str ( EN )+ + str ( Alpha [ EN -1][0])+ \ n )) EN = EN +1 MyOu tputFi leAlph a . close () # Alpha_ #. txt is created every # - th iteration and contains the # sensitivity for all elements . # ############################################################ # -- CLOSING THE RESULTS IN ABAQUS -- # session . odbs [ WorkDirectory + JobName + . odb ]. close () F [ Iter -1] = SE [ -1] / V [ -1] # Convergence of the design variable F [ Iter -1] is calculated by # averaging over 10 past isterations . if Iter < InitialIter + 11: Convergence = 100 else : N = 5 i = 1 a = 0 b = 0 while i <= N : a = a + abs ( F [ Iter - i ] - F [ Iter -N - i ]) b = b + F [ Iter - i ] i = i + 1 Convergence = a / b OldAlpha = Alpha Iter = Iter + 1

# ############################################################ # -- CLOSING OUTPUT TXT - FILE -- # MyO ut p utF i le I t e r D a t a . close () MyOutputFile . write ( # ... Convergence = + str ( Convergence ) + after + str ( Iter -1)+ Iterations ...\ n ) MyOutputFile . close () print # ... Convergence = , Convergence , after , Iter , Iterations ... print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

50

796 797

print ###### Script has completed succesfully ! ###### print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

A.2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

Inverse shape optimization

# ############################################################ ## Inverse shape optimization ## ## - Sydney , January 15 th 2010 by Edward de boer ## ## ## # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## ## ## # # In order to run the script succesfully , all the ## # # parameters under the header " INPUT PARAMETERS " need to ## # # be set in accordance with the Abaqus model used . ## ## ## # # Warning : To be used with Abaqus 6.7 only . Newer ## # # versions of Abaqus ( I . E . 7.9) have been known to crash ## # # without warning during long simulations . ## # ############################################################ from abaqus import * from abaqusConstants import * from math import * import sys print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # print ###### starting python sctipt ###### print ###### Created by Edward de Boer ###### print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ############################################################ # -- STARTING UP -- # from part import * from material import * from section import * from assembly import * from step import * from interaction import * from load import * from mesh import * from job import * from sketch import * from visualization import * from connec torBeh avior import * import regionToolset # ############################################################ # -- INITIATE VARIABLES -- # OutputDirectory = D :/ Edward / Test / Output / # OutputDirectory is where the output txt - files are stored . WorkDirectory = D :/ Edward / Test / Raw / # WorkDirectory is where the job files are stored . AssignSections = 0 # AssignSections = [0 or 1] : Assign materials to mesh - elements .

51

52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

C al cu l ate C o n n e c t i v i t y = 0 # C a lc u lat e C o n n e c t i v ity = [0 or 1] : Make a large matrix with # elemental and nodal connectivity , required for simulation . Continue = 0 # Continue = [0 or 1] : Continue a simulation at the next iteration . # The topology of the current iteration is read from the materials # in the Abaqus model . EvaluateElements = 1 # EvaluateElements = [0 or 1] : Create sets with the # activated and deactivated elements , to be used for visualization . Example = 1 # Example = [1 ,2 ,3 or 4] : Use the model for example 1 ,2 ,3 or 4. MaxIter = 50 # Maxiimum number of iterations . ConvLimit = 0.001 # Convergence limit . Convergence = 1 # Initial value for Convergence . ARMax = 0.02 # Maximum Admission volume ratio : Volume of added elements divided by # the total volume in the current design . # Example 1 ,2 ,3 and 4 use different parts and dimensions . if Example == 1: # Abaqus model paramters : NumberOfElems =14000 NumberOfNodes =14241 JobNamePrefix = Example_1__ PartName = ESize05 Shapes = [[ circle ,(25 ,0 ,0) ,15]] # Shapes [[ circle ,XC , R ]] is an array that hold the dimensions # of the circular shaped hole that needs to be present in the # deformed part . XC are the coordinates of the circle s center # and R is the radius in [ mm ]. InitialV0 = 50.0 * 70.0 # TotalV0 is the initial ( undeformed ) volume [ mm ^2]. elif Example == 2: # Abaqus model paramters : NumberOfElems =14000 NumberOfNodes =14241 JobNamePrefix = Example_2__ PartName = ESize05 # Shapes = [[ rectangle ,(25 ,0 ,0) ,(7.5 ,17.5 ,0) ,(42.5 , -17.5 ,0)]] Shapes = [[ rectangle ,(25 ,0 ,0) ,(15 ,10 ,0) ,(35 , -10 ,0)]] # Shapes [[ rectangle , XC , X1 , X2 ]] is an array that holds the # dimensions of the rectangular shaped hole that needs to be present # in the deformed part . XC are the coordinates of the rectangle s

52

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167

# center , X1 are the coordinates of the rectangle s top left corner # and X2 are the cooridnates of the rectangle s bottem right corner . InitialV0 = 50.0 * 70.0 # InitialV0 is the initial ( undeformed ) volume [ mm ^2]. elif Example == 3: # Abaqus model paramters : NumberOfElems =4000 NumberOfNodes =4141 JobNamePrefix = Example_3__ PartName = Huge_1 Shapes = [[ circle ,(40 ,0 ,0) ,20]] # Circular hole with radius of 20 mm . InitialV0 = 40.0 * 100.0 # TotalV0 is the initial ( undeformed ) volume [ mm ^2]. elif Example == 4: # Abaqus model paramters : NumberOfElems =4000 NumberOfNodes =4141 JobNamePrefix = Example_4__ PartName = Huge_1 Shapes = [[ rectangle ,(40 ,0 ,0) ,(20 ,20 ,0) ,(60 , -20 ,0)]] # Rectangular hole : 40 x 40 mm InitialV0 = 40.0 * 100.0 # TotalV0 is the total ( undeformed ) volume [ mm ^2]. InitialAlphaTH = 0 # Abaqus model parameters ModelName = ISO PartName = Huge_1 StepName = DisplacementStep # ############################################################ # -- SETTING UP INITIAL GEOMETRY -- # X = [1 for a in range ( NumberOfElems )] # ############################################################ # -- CREATE MATERIALS -- # # Material paramters : YM = 210 e3 ReducedYM = 0.01 * YM PR = 0.3 SY = 400 YMP = 0.2 * YM ReducedYMP = 0.2 * ReducedYM PlasticP roper ties = (( SY , 0.0) , ( SY + YMP * 5 , 5)) R e d u c e d Pl a s t i c P r o p e r t i es = (( SY , 0.0) , ( SY + ReducedYMP * 5 , 5))

53

168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225

EN = 1 if Continue == 1: # To Continue the script , the last iteration is taken as the current InitialIter = Iter # The abaqus model s materials are read to determine absent elements while EN <= NumberOfElems : MN = Material - E + str ( EN ) print Now reading Material number , EN Elastic Prope rties = mdb . models [ ModelName ]. materials [ MN ]. elastic # Elast icProperties refers to the properties of the EN - th element if Elastic Properties . table [0][0] == ReducedYM : X [ EN -1] = 0 EN = EN + 1 else : EN = EN +1 else : # If the script is not continued , it starts at iteration 1 InitialIter = 1 Iter = InitialIter V0 = InitialV0 TH = NumberOfElems # TH is ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? while EN <= NumberOfElems : # Every element has an identical material assigned to it . # Array X is read to determine the material properties . MN = Material - E + str ( EN ) print Now assigning Material number , EN mdb . models [ ModelName ]. Material ( name = MN ) if X [ EN -1] == 1: mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( YM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = PlasticProp erties ) else : mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( ReducedYM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = R e d u ce d P l a s t i c Pr o p e r t i e s ) EN = EN +1 # ############################################################ # -- ASSIGN SECTIONS -- # if AssignSections == 1: # The materials need to be assigned to sections ( elements ) in Abaqus EN = 1 while ( EN <= NumberOfElems ): SN = Section - E + str ( EN ) MN = Material - E + str ( EN ) print Now assigning Section number , EN mdb . models [ ModelName ]. H om o ge ne o us S o l i d S e c t i o n ( name = SN , material = MN , thickness =1) element = mdb . models [ ModelName ]. parts [ PartName ]. elements [ EN -1: EN ] region = regionToolset . Region ( elements = element ) mdb . models [ ModelName ]. parts [ PartName ]. Secti onAssi gnment ( region = region , sectionName = SN ) EN = EN + 1 else : print No need to assign any Sections !

54

226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

# ############################################################ # -- CALCULATING NODAL AND ELEMENTAL CONNECTIVITY -- # if C al c ul a t e C o n n e c t i vi ty == 1: Noda lConne ctivit y = [[] for b in range ( NumberOfNodes )] # NodalCon nectiv ity [ NN -1] is a matrix that shows which elements # ( EN ) are connected to a node ( NN ). El e men t a l C o n n e c t ivit y = [[] for b in range ( NumberOfElems )] # El em e n t a l C o n n e c tivi ty [ EN -1] is a matrix that shows which nodes # ( NN ) are connected to an element ( EN ). EN = 1 while EN <= NumberOfElems : Element = mdb . models [ ModelName ]. parts [ PartName ]. elements [ EN -1] connectivity = Element . connectivity i = 0 while i < 4: El e m e n t a lCo nnec tivit y [ EN -1]. append ( connectivity [ i ]+1) Nod alConnectivity [ connectivity [ i ]]. append ( EN ) i = i + 1 EN = EN + 1 else : print No need to calculate connectivity ! # ############################################################ # -- WRITE TO OUTPUT - FILE -- # MyO ut p utF i le I t e r D a t a = open ( OutputDirectory + IterData . txt , w ) # IterData . txt is updated after every iteration . MyOu t put S ym m a ry F i le = open ( OutputDirectory + Summary . txt , w ) MyOu t put S ym m a ry F i le . write ( NumberOfElems =%6 d NumberOfNodes =%6 d MaxIter =%6 d \ n %( NumberOfElems , NumberOfNodes , MaxIter )) MyOu t put S ym m a ry F i le . write ( InitialYM =%8 f ReducedYM =%8 f PR =%8 f \ n %( YM , ReducedYM , PR )) MyOu t put S ym m a ry F i le . write ( ARMax =%8 f \ n %( ARMax )) MyOu t put S ym m a ry F i le . close () # Symmary . txt contains information on the initial parameters . MyOutputFile = open ( OutputDirectory + Output . txt , w ) # MyOutputFile contains all lines that are printed in Abaqus V = [[] for a in range ( MaxIter )] # V is an array that contains the volume of the design # ############################################################ # -- START OF ITERATION LOOP -- # print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # print ###### Start of the iteration loop ###### print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # InitialIter = Iter while ( Iter <= MaxIter ): # and Convergence > ConvLimit : # ############################################################ # -- MAKING " SET " - LISTS OF ACTIVE AND INACTIVE ELEMENTS -- #

55

284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341

if EvaluateElements == 1: # X is evaluated and arrays with present and absent elements # are made . These arrays are then stored in sets in Abaqus . Activat edEle ments = [] De ac t i va t e dE lements = [] EN = 1 print Now Evaluating the state of the Elements while EN <= NumberOfElems : if X [ EN -1] == 1: ActivatedElements . append ( EN ) else : De ac tivatedElemen t s . append ( EN ) EN = EN + 1 mdb . models [ ModelName ]. parts [ PartName ]. S e t F r o m E l e m e n t L a b e l s ( name = A ctivatedElements _ + str ( Iter ) , elementLabels = Ac tivatedEleme nts ) mdb . models [ ModelName ]. parts [ PartName ]. S e t F r o m E l e m e n t L a b e l s ( name = D e activatedEl eme n ts_ + str ( Iter ) , elementLabels = Deac t ivat ed El em e n ts ) else : print Skipping the evaluation of elements . # ############################################################ # -- CREATING A JOB -- # JobName = JobNamePrefix + str ( Iter ) mdb . Job ( name = JobName , model = ModelName , type = ANALYSIS , explici tPrec ision = SINGLE , no d alO u t p u t P r e c i s i o n = SINGLE , description = , p a r a l l e l i z a t i o n M e t h o d E x p l i c i t = DOMAIN , mu lt i p ro c e ss ingMode = DEFAULT , numDomains =4 , userSubroutine = , numCpus =4 , st a n d a r d M e m o ryPolicy = MODERATE , scratch = , echoPrint = OFF , modelPrint = OFF , contactPrint = OFF , historyPrint = OFF ) # ############################################################ # -- SUBMITTING THE JOB -- # # print # ... Submitting the job ... mdb . jobs [ JobName ]. submit ( con s iste nc yC he c k in g = OFF ) mdb . jobs [ JobName ]. waitForCompletion () # ############################################################ # -- OPENING THE RESULTS -- # myOdb = openOdb ( path = JobName + . odb ) DisplacementStep = myOdb . steps [ StepName ] Increment = len ( DisplacementStep . frames ) CurrentFrame = DisplacementStep . frames [ Increment -1] # Only the last frame ( increment ) is analyzed . # ############################################################ # -- GETTING OUTPUT FROM ABAQUS -- # NodalCoordinates = CurrentFrame . fieldOutputs [ COORD ] MyNX1 = [] MyNX2 = [] for v in NodalCoordinates . values : MyNX1 . append ( v . data [0]) MyNX2 . append ( v . data [1])

56

342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399

# MyNX1 and MyNX2 contain nodal coordinates for all nodes . MyEV = [] # MyEV contains the elemental volumes . # ############################################################ # -- CALCULATING INDICATOR NUMBERS -- # Alpha = [] # Alpha [ EN -1] is an array containing the sensitivities per element # and the element number ( EN ). EN = 1 while EN <= NumberOfElems : k = 1 coor = [[] for b in range (4)] # coor [k -1] is an array that holds the coordinates for all # nodes connected to element EN while k <= 4: NN = E l e men talC onne c t i vi t y [ EN -1][ k -1] coor [k -1] = ( MyNX1 [ NN -1] , MyNX2 [ NN -1] ,0) k = k + 1 k = 1 xe = [0 ,0 ,0] # xe : Array with coordinates of the center of element EN . while k <= 4: i = 1 while i <= 3: xe [i -1] = xe [i -1] + (1/ ncn ) * coor [k -1][ i -1] i = i + 1 k = k + 1 # Next the 2 D volume of the element is calculated because # Abaqus s " EVOL " value doesnt give the deformed volume for # a 2 D problem . The 2 D elemental volumes are stored in the # array MyEV . AC = ( coor [2][0] - coor [0][0] , coor [2][1] - coor [0][1] , coor [2][2] - coor [0][2]) BD = ( coor [3][0] - coor [1][0] , coor [3][1] - coor [1][1] , coor [3][2] - coor [1][2]) VV = [[] for a in range (3)] VV [0] = AC [1]* BD [2] - AC [2]* BD [1] VV [1] = AC [2]* BD [0] - AC [0]* BD [2] VV [2] = AC [0]* BD [1] - AC [1]* BD [0] ev = 0.5 * sqrt (( VV [0])**2+( VV [1])**2+( VV [2])**2) MyEV . append ( ev )

alpha = [[] for a in range ( len ( Shapes ))] i = 1 while i <= len ( Shapes ): if Shapes [i -1][0] == rectangle : # If the i - th shape is a rectangle , the indicator number # is calculated by determining the shortest distance ( re ) # from the center of the desired hole ( XC ) to the point on # the border of the rectangle ( Xb ) that is closest to the # center of the EN - th element ( xe ). XC = Shapes [i -1][1] XR1 = Shapes [i -1][2] XR2 = Shapes [i -1][3]

57

400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457

XLimR XLimL YLimU YLimD

= = = =

XR2 [0] XR1 [0] XR1 [1] XR2 [1]

dL = abs ( xe [0] - XLimL ) dR = abs ( XLimR - xe [0]) dU = abs ( YLimU - xe [1]) dD = abs ( xe [1] - YLimD ) if min ( dL , dR , dU , dD ) == dL : if dU < dD : if xe [0] <= XLimL and xe [1] >= YLimU : Xb = ( XLimL , YLimU , 0 ) elif xe [0] > XLimL and xe [1] >= YLimU : Xb = ( xe [0] , YLimU , 0 ) else : Xb = ( XLimL , xe [1] , 0 ) else : if xe [0] <= XLimL and xe [1] <= YLimD : Xb = ( XLimL , YLimD , 0 ) elif xe [0] > XLimL and xe [1] <= YLimD : Xb = ( xe [0] , YLimD , 0 ) else : Xb = ( XLimL , xe [1] , 0 ) elif min ( dL , dR , dU , dD ) == dR : if dU < dD : if xe [0] >= XLimR and xe [1] >= YLimU : Xb = ( XLimR , YLimU , 0 ) elif xe [0] < XLimR and xe [1] >= YLimU : Xb = ( xe [0] , YLimU , 0 ) else : Xb = ( XLimR , xe [1] , 0 ) else : if xe [0] >= XLimR and xe [1] <= YLimD : Xb = ( XLimR , YLimD , 0 ) elif xe [0] < XLimR and xe [1] <= YLimD : Xb = ( xe [0] , YLimD , 0 ) else : Xb = ( XLimR , xe [1] , 0 ) elif min ( dL , dR , dU , dD ) == dU : if dL < dR : if xe [0] <= XLimL and xe [1] >= YLimU : Xb = ( XLimL , YLimU , 0 ) elif xe [0] <= XLimL and xe [1] < YLimU : Xb = ( XLimL , xe [1] , 0 ) else : Xb = ( xe [0] , YLimU , 0 ) else : if xe [0] >= XLimR and xe [1] >= YLimU : Xb = ( XLimR , YLimU , 0 ) elif xe [0] >= XLimR and xe [1] < YLimU : Xb = ( XLimR , xe [1] , 0 ) else :

58

458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515

Xb = ( xe [0] , YLimU , 0 ) elif min ( dL , dR , dU , dD ) == dD : if dL < dR : if xe [0] <= XLimL and xe [1] <= YLimD : Xb = ( XLimL , YLimD , 0 ) elif xe [0] <= XLimL and xe [1] > YLimD : Xb = ( XLimL , xe [1] , 0 ) else : Xb = ( xe [0] , YLimD , 0 ) else : if xe [0] >= XLimR and xe [1] <= YLimD : Xb = ( XLimR , YLimD , 0 ) elif xe [0] >= XLimR and xe [1] > YLimD : Xb = ( XLimR , xe [1] , 0 ) else : Xb = ( xe [0] , YLimD , 0 ) se = sqrt (( XC [0] - xe [0])**2+( XC [1] - xe [1])**2 +( XC [2] - xe [2])**2) re = sqrt (( Xb [0] - XC [0])**2+( Xb [1] - XC [1])**2 +( Xb [2] - XC [2])**2) elif Shapes [i -1][0] == circle : # If the i - th shape is a circle , the indicator number # is calculated by calculating the distance from the center # of the EN - th element ( xe ) to the center of the desired # circular hole . XC = Shapes [i -1][1] RC = Shapes [i -1][2] se = sqrt (( XC [0] - xe [0])**2+( XC [1] - xe [1])**2 +( XC [2] - xe [2])**2) re = RC alpha [i -1] = i = i + 1 ( re - se ) / re

alpha = max ( alpha ) # In order to combine multiple simple holes of different # shape and size , the maximum indicator value will be # selected as the indicator number . if AverageAlpha == 1 and Iter > 1: alpha = ( alpha + OldAlpha [ EN -1][0] ) / 2 Alpha . append ([ alpha , EN ]) # Alpha [ EN ] is an array with the EN - th element s indicator # number and its element number . EN = EN + 1 Volume = 0 # The total volume can now be calculated by summing the elements . EN =1 while EN <= NumberOfElems : if X [ EN -1] == 1: Volume = Volume + MyEV [ EN -1] else : Volume = Volume EN = EN + 1

59

516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573

V [ Iter -1] = Volume # In order to determine the volume ratio later on , it is important # to store the deformed volume of the initial design . if Iter ==1: InitialVolume = V [ Iter -1] SortedAlpha = sorted ( Alpha ) # The sensitivities are sorted from low to high . # ############################################################ # -- REMOVING AND ADDING ELEMENTS -- # if Iter == 1: # Initially a full design is used , so at iteration one # the previous indicator threshold value ( PreviousATH ) is one . PreviousATH = 1 SI = 1 DAlpha = [] # Next the indicator number closest to the desired initial # indicator number ( InitialAlphaTH ) is chosen as threshold # indicator number , and it s sorted index ( SI ) is chosen as # the threshold value ( TH ). while SI <= NumberOfElems : DAlpha . append ([ abs ( SortedAlpha [ SI -1][0] - InitialAlphaTH ) , SI ]) SI = SI + 1 TH = min ( DAlpha )[1] # Based on the threshold value ( TH ) , the next iteration s # volume ( V0k ) and the evolutionairy ratio ( ER ) is caluclated . V0k = ( float ( TH ) / NumberOfElems ) * InitialV0 ER = V0k / V0 - 1 else : # After the first iteration the next volume is determined by # evaluating the what is the threshold indicator number # of the current design ( PreviousATH ). If that value is below # zero , more elements need to be removed and the volume ( V0k ) # is reduced . And visa versa . PreviousATH = SortedAlpha [ TH -1][0] ER = abs ( PreviousATH ) * 0.05 if PreviousATH > 0: V0k = V0 *(1 - ER ) else : V0k = V0 *(1 + ER ) # The threshold ( TH ) value is then calculaed using the volume . TH = int (( V0k / InitialV0 ) * NumberOfElems ) + 1 AlphaTH = SortedAlpha [ TH -1][0] # The threshold indicator number is read from the sorted array . SI = 1 AR = 0 # AR is the admission volume ratio . while SI < TH : EN = SortedAlpha [ SI -1][1] if X [ EN -1] == 0: AR = AR + ( InitialV0 / NumberOfElems ) / V0 else : AR = AR

60

574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631

SI = SI + 1 print # ... At Iteration # , Iter , PreviousATH = , PreviousATH ,\ , TH = ,TH , , AR = ,AR , and Convergence = , Convergence , ... MyOutputFile . write ( # ... At Iteration # + str ( Iter ) + PreviousATH = + str ( PreviousATH )+ TH = + str ( TH )+ AR = + str ( AR )+ V0 = + str ( V0 )+ and Convergence = + str ( Convergence )+ ...\ n ) SI = 1 if AR <= ARMax : # If not too many elements are added in this iteration , elements # can be removed and added . The volume is immediately updated . while SortedAlpha [ SI -1][0] < AlphaTH : EN = SortedAlpha [ SI -1][1] if X [ EN -1] == 0: print # ... , at Iteration # , Iter ,\ - Adding Element Number : ,EN , with SI = ,SI ,\ V0 = ,V0 , and V0k = ,V0k , ... MyOutputFile . write ( # ... + at Iteration # + str ( Iter ) + - Adding Element Number : + str ( EN )+ with SI = + str ( SI )+ V0 = + str ( V0 )+ and V0k = + str ( V0k ) + ...\ n ) MN = Material - E + str ( EN ) mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( YM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = PlasticP roperties ) X [ EN -1] = 1 Volume = Volume + MyEV [ EN -1] V0 = V0 + InitialV0 / NumberOfElems SI = SI + 1 else : SI = SI + 1 SI = NumberOfElems while SortedAlpha [ SI -1][0] >= AlphaTH : EN = SortedAlpha [ SI -1][1] if X [ EN -1] == 1: print # ... , at Iteration # , Iter ,\ - Removing Element Number : ,EN , with SI = ,SI ,\ V0 = ,V0 , and V0k = ,V0k , ... MyOutputFile . write ( # ... + at Iteration # + str ( Iter )+ - Removing Element Number : + str ( EN ) + with SI = + str ( SI )+ V0 = + str ( V0 ) + and V0k = + str ( V0k )+ ...\ n ) MN = Material - E + str ( EN ) mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( ReducedYM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = R e du c e d Pl a s t i c P r o p e r t i e s ) X [ EN -1] = 0 Volume = Volume - MyEV [ EN -1] V0 = V0 - InitialV0 / NumberOfElems SI = SI - 1 else : SI = SI - 1 else : i = 1

61

632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689

k = 1 while i <= ( ARMax * NumberOfElems ): AddElem = SortedAlpha [k -1][1] if X [ AddElem -1] == 0: print # ... , at Iteration # , Iter ,\ - Adding Element Number : , AddElem ,\ V0 = ,V0 , and V0k = ,V0k , ... MyOutputFile . write ( # ... + at Iteration # + str ( Iter ) + - Adding Element Number : + str ( EN )+ V0 = + str ( V0 )+ and V0k = + str ( V0k )+ ...\ n ) MN = Material - E + str ( AddElem ) mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( YM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = PlasticP roperties ) X [ AddElem -1] = 1 Volume = Volume + MyEV [ AddElem -1] V0 = V0 + InitialV0 / NumberOfElems i = i + 1 k = k + 1 else : k = k + 1 i = 1 while V0 > V0k : DelElem = SortedAlpha [ - i ][1] if X [ DelElem -1] == 1: print # ... , at Iteration # , Iter ,\ - Removing Element Number : ,\ DelElem , V0 = ,V0 , and V0k = ,V0k , ... MyOutputFile . write ( # ... + at Iteration # + str ( Iter ) + - Removing Element Number : + str ( EN )+ V0 = + str ( V0 )+ and V0k = + str ( V0k )+ ...\ n ) MN = Material - E + str ( DelElem ) mdb . models [ ModelName ]. materials [ MN ]. Elastic ( table =(( ReducedYM , PR ) ,)) mdb . models [ ModelName ]. materials [ MN ]. Plastic ( table = R e du c e d Pl a s t i c P r o p e r t i e s ) X [ DelElem -1] = 0 i = i + 1 Volume = Volume - MyEV [ DelElem -1] V0 = V0 - InitialV0 / NumberOfElems else : i = i +1 # ############################################################ # -- WRITING SOME OUTPUT -- # My O utp u t F i l e I t e r Data . write ( str ( Iter )+ + str ( Volume )+ \ n ) MyOutputFileIter = open ( OutputDirectory + ITER_ + str ( Iter ) + . txt , w ) MyOutputFileIter . write ( Iter =%6 d V =%8 f Vf =%8 f V0 =%8 f V0f =%8 f + aTH =%8 f ER =%8 f \ n %( Iter , Volume , Volume / InitialVolume , V0 , V0 / InitialV0 , PreviousATH , ER )) MyOutputFileIter . close () # ITER_ #. txt is created every # - th iteration and contains volume # fractions and threshold values for the indicator number . MyOutputFileX = open ( OutputDirectory + X_ + str ( Iter )+ . txt , w )

62

690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742

EN =1 while EN <= NumberOfElems : MyOutputFileX . write (( str ( EN )+ + str ( X [ EN -1])+ \ n )) EN = EN +1 MyOutputFileX . close () # X_ #. txt is created every # - th iteration and contains the array # X which is the variable that needs to be optimized MyOu tputFi leAlph a = open ( OutputDirectory + Alpha_ + str ( Iter )+ . txt , w ) EN =1 while EN <= NumberOfElems : MyOutpu tFile Alpha . write (( str ( EN )+ + str ( Alpha [ EN -1][0])+ \ n )) EN = EN +1 MyOu tputFi leAlph a . close () # Alpha_ #. txt is created every # - th iteration and contains the # indicator number for all elements . # ############################################################ # -- CLOSING THE RESULTS IN ABAQUS -- # session . odbs [ WorkDirectory + JobName + . odb ]. close () # Convergence of the design variable V [ Iter -1] is calculated by # averaging over 10 past isterations . if Iter < InitialIter + 2* N : Convergence = 100 else : N = 5 i = 1 a = 0 b = 0 while i <= N : a = a + abs ( V [ Iter - i ] - V [ Iter -N - i ]) b = b + V [ Iter - i ] i = i + 1 Convergence = a / b OldAlpha = Alpha Iter = Iter + 1

# ############################################################ # -- CLOSING OUTPUT TXT - FILE -- # MyO ut p utF i le I t e r D a t a . close () MyOutputFile . write ( # ... Convergence = + str ( Convergence ) + after + str ( Iter -1)+ Iterations ...\ n ) MyOutputFile . close () print # ... Convergence = , Convergence , after , Iter , Iterations ... print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # print ###### Script has completed succesfully ! ###### print # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

63

You might also like