Abstract
Recently, topology optimization has drawn interest from both industry and academia as the ideal design method for additive manufacturing. Topology optimization, however, has a high entry barrier as it requires substantial expertise and development effort. The typical numerical methods for topology optimization are tightly coupled with the corresponding computational mechanics method such as a finite element method and the algorithms are intrusive, requiring an extensive understanding. This paper presents a modular paradigm for topology optimization using OpenMDAO, an open-source computational framework for multidisciplinary design optimization. This provides more accessible topology optimization algorithms that can be non-intrusively modified and easily understood, making them suitable as educational and research tools. This also opens up further opportunities to explore topology optimization for multidisciplinary design problems. Two widely used topology optimization methods—the density-based and level-set methods—are formulated in this modular paradigm. It is demonstrated that the modular paradigm enhances the flexibility of the architecture, which is essential for extensibility.
References
Aage N, Andreassen E, Lazarov BS (2015) Topology optimization using petsc: an easy-to-use, fully parallel, open source topology optimization framework. Struct Multidiscip Optim 51(3):565–572
Allaire G, Jouve F, Toader AM (2004) Structural optimization using sensitivity analysis and a level-set method. J Comput Phys 194(1):363–393
Andreassen E, Clausen A, Schevenels M, Lazarov BS, Sigmund O (2011) Efficient topology optimization in MATLAB using 88 lines of code. Struct Multidiscip Optim 43(1):1–16
Antoine L (2017) A level set-based structural optimization code using fenics. arXiv:1705.01442
Behnel S, Bradshaw R, Seljebotn DS, Ewing G et al (2008) Cython: C-extensions for python
Belytschko T, Xiao S, Parimi C (2003) Topology optimization with implicit functions and regularization. Int J Numer Methods Eng 57(8):1177–1196
Bendsøe MP, Sigmund O, Bendsøe MP, Sigmund O (2004) Topology optimization by distribution of isotropic material, Springer, Berlin
van Dijk NP, Maute K, Langelaar M, Keulen FV (2013) Level-set methods for structural topology optimization: a review. Struct Multidiscip Optim 48(3):437–472
Dunning P, Kim H (2013) A new method for creating holes in level-set function based topology optimisation. International Journal for Numerical Methods in Engineering
Dunning PD, Kim HA (2015) Introducing the sequential linear programming level-set method for topology optimization. Struct Multidiscip Optim 51(3):631–643
Dunning PD, Kim HA, Mullineux G (2011) Investigation and improvement of sensitivity computation using the area-fraction weighted fixed grid fem and structural optimization. Finite Elem Anal Des 47(8):933–941
Falck RD, Chin JC, Schnulo SL, Burt JM, Gray JS (2017) Trajectory optimization of electric aircraft subject to subsystem thermal constraints. In: 18th AIAA/ISSMO multidisciplinary analysis and optimization conference. Denver, CO
Gray JS, Hearn TA, Moore KT, Hwang J, Martins J, Ning A (2014) Automatic evaluation of multidisciplinary derivatives using a graph-based problem formulation in openMDAO In: 15th AIAA/ISSMO multidisciplinary analysis and optimization conference american institute of aeronautics and astronautics. https://doi.org/10.2514/62014-2042
Gray JS, Moore KT, Naylor BA (2010) Openmdao: An open-source framework for multidisciplinary analysis and optimization In: 13th AIAA/ISSMO multidisciplinary analysis and optimization conference, fort worth, TX, AIAA, AIAA-2010-9101 AIAA, Fort Worth, Texas. http://www.aricorkr/treatise/journal/contentasp?idx=134451
Hedges LO, Kim HA, Jack RL (2017) Stochastic level-set method for shape optimisation. J Comput Phys 348:82–107
Hwang JT, Lee DY, Cutler JW, Martins JRRA (2014) Large-scale multidisciplinary optimization of a small satellite’s design and operation. J Spacecr Rocket 51(5):1648–1663. https://doi.org/10.2514/1A32751
Hwang J T, Martins J R R A (2016) Allocation-mission-design optimization of next-generation aircraft using a parallel computational framework. In: 57th AIAA/ASCE/AHS/ASC structures, structural dynamics, and materials conference American institute of aeronautics and astronautics. https://doi.org/10.2514/62016-1662
Hwang JT, Martins JRRA (2018) A computational architecture for coupling heterogeneous numerical models and computing coupled derivatives. ACM Transactions on mathematical software. In press
Kambampati S, Jauregui C, Museth K, Kim H (2018) Fast level set topology optimization using a hierarchical data structure. In: AIAA aviation and aeronautics forum and exposition 2018
Lambe AB, Martins JR (2012) Extensions to the design structure matrix for the description of multidisciplinary design, analysis, and optimization processes. Struct Multidiscip Optim 46(2):273–284
Liu K, Tovar A (2014) An efficient 3D topology optimization code written in matlab. Struct Multidiscip Optim 50(6):1175–1196
Otomori M, Yamada T, Izui K, Nishiwaki S (2015) Matlab code for a level set-based topology optimization method using a reaction diffusion equation. Struct Multidiscip Optim 51(5):1159–1172
Pingen G, Waidmann M, Evgrafov A, Maute K (2010) A parametric level-set approach for topology optimization of flow domains. Struct Multidiscip Optim 41(1):117–131
Sigmund O (2001) A 99 line topology optimization code written in matlab. Struct Multidiscip Optim 21 (2):120–127
Sivapuram R, Dunning PD, Kim HA (2016) Simultaneous material and structural optimization by multiscale topology optimization. Struct Multidiscip Optim 54(5):1267–1281
Svanberg K, Svard H (2013) Density filters for topology optimization based on the geometric harmonic means. In: 10th world congress on structural and multidisciplinary optimization. Orlando
Wei P, Li Z, Li X, Wang MY (2018) An 88-line matlab code for the parameterized level set method based topology optimization using radial basis functions. Struct Multidiscip Optim 58(2):831–849
Funding
This paper received support from the NASA Transformational Tools and Technologies Project, contract number NNX15AU22A.
Author information
Authors and Affiliations
Corresponding author
Ethics declarations
Replication of results
To comply with Replication of Results and help the reader in using the present work in research and education, the codes of the present work is open to public e codes (https://github.com/chungh6y/openmdao_TopOpt). Instruction for installation and running the program can be found therein.
Conflict of interests
The authors declare that they have no conflict of interest.
Additional information
Responsible Editor: Jose Herskovits
Publisher’s note
Springer Nature remains neutral with regard to jurisdictional claims in published maps and institutional affiliations.
Appendix
Appendix
1.1 A.1 Numerical libraries
In this work, the existing finite element and level-set libraries written by C++ are interfaced to OpenMDAO by Cython (Behnel et al. 2008) for an efficient computation. OpenLSTO (open-sourced level-set topology optimization) is a recently published level-set topology optimization suite and in active development by researchers at the University of Cardiff and the University of California San Diego, which is freely available (https://github.com/M2DOLab/OpenLSTO-lite). The program is designed to provide users with easy access to the level-set method. To make a compilation process straightforward and demonstrate its usage within OpenMDAO, we provide the aforementioned OpenMDAO classes and OpenLSTO as a single suite (https://github.com/chungh6y/openmdao_TopOpt/tree/master/OpenLSTO-master). Detailed installation process is provided therein. After compilation, the user may find two libraries (the finite element and the level-set) as a shared library, which can be imported as the Python object. The concise examples of the given libraries along with the comments are found below.
1.1.1 A.1.1 Finite element method
As specified in the Fig. 6, dimensions (lx, ly), number of elements (nelx, nely), and force conditions are specified. Detailed descriptions of functions that specify boundary conditions can also be found in the GitHub repository. To be used within OpenMDAO, the calculation routines for the stiffness matrices and their derivatives give out the entities of sparse matrix, which is built by SciPy.sparse library.
from pyBind import py_FEA ᅟ # Meshing ============================= fem_solver = py_FEA(lx = 160, ly = 80, nelx=80, nely=40, element_order=2) [node, elem elem_dof]= fem_solver.get_mesh() ᅟ # Material ============================= fem_solver.set_material(E=1., nu=.3) ᅟ # Boundary condition ================== coord = np.array([0,0]) tol = np.array([1e-3,1e10]) fem_solver.set_boundary(coord=coord,tol=tol) BCid = fem_solver.get_boundary() ᅟ # External force as specified at Fig. 2 coord = np.array([length_x,length_y/2]) tol = np.array([1,1]) GF_ = fem_solver.set_force(coord = coord, tol = tol, direction = 1, f = -1.0) ᅟ # Stiffness matrix given as the entities of sparse matrix (CSC) nELEM = elem.shape[0] (rows, cols, vals)=fem_solver.compute_K_SIMP (np.ones(nELEM))
1.2 A.1.2 Level-set method
In the present section, a brief usage of the level-set library is illustrated. The method is classified into three categories: (1) geometric property extraction (2) boundary sensitivity evaluation, (3) and the update of ϕ after suboptimization. After the signed distance function is set (set_levelset), based on the current domain, Ersatz model area fraction as well as the geometric properties are evaluated using the discretise function. The boundary sensitivities bptSens are then obtained from the sensitivity module, where the compliance sensitivities are computed at the boundary points by various subroutines including least square method. Note that these values are the ingredients of suboptimization, wherein advection velocities at the boundary points (Bpt_Vel, timestep) are computed. The level-set function is then updated and reinitialized accordingly.
from py_lsmBind import py_LSM from from pyBind import py_Sensitivity ᅟ # LSM initialization (with initial holes) ================ lsm_solver = py_LSM(nelx = nelx, nely = nely, moveLimit = movelimit) hole = np.array([[16, 14, 5], ... , [144, 66, 5]]) lsm_solver.add_holes(locx = list(hole[:,0]), locy = list(hole[:,1]), radius = list (hole[:,2])) lsm_solver.set_levelset() ᅟ # Discretization ========================================= (bpts_xy, areafraction, seglength) = lsm_solver.discretise() (lb2,ub2) = lsm_solver.get_Lambda_Limits() ᅟ ... FEA that gives out structural response u ... ᅟ # Sensitivity module ==================================== pySens = py_Sensitivity(fem_solver, u) bptSens = pySens.compute_boundary_sens(bpts_xy) ᅟ ... suboptimization through the OpenMDAO ... ᅟ # Advection of the sign distance function ================ lsm_solver.advect(Bpt_Vel, timestep) lsm_solver.reinitialise()
1.3 A.1.3 Configuration of the connectivity
For an illustration of the connectivities established between variables of different Components, we present here the code snippet of the Group object of SIMP topology optimization method.
As the Group component initializes before components are called, a number of shared member variables in relation to the finite element meshes (e.g., nNODE, nELEM) as well as optimization parameters (e.g., penalization order p) are defined using metadata.
The numerous Component objects shown in Fig. 4 are added via add_subsystem, and their variables are connected by connect functions. Note that connections are made at the Group level; therefore, the connections can be modified easilywithout intrusive re-programming of the Components.
from openmdao.api import Group, IndepVarComp from pyBind import py_FEA ᅟ # SIMP Group initialization ============================================ class SimpGroup(Group): ᅟ def initialize(self): # Prescribing shared member variables within group self.metadata. declare('fem_solver', type_=py_FEA, required=True)self.metadata.declare('force', type_=np.ndarray, required=True) self.metadata.declare('num_elem_x', type_=int, required=True) self.metadata. declare('num_elem_y', type_=int, required= True) self.metadata.declare('penal', type_= (int, float), required=True) self.metadata. declare('volume_fraction', type_=(int,float), required=True) ᅟ def setup(self): # Where the Connectivity between components are set up fem_solver = self.metadata['fem_solver'] force = self. metadata['force'] num_elem_x = self.metadata ['num_elem_x'] num_elem_y = self.metadata['num_elem_y'] p = self.metadata['penal'] volume_fraction = self.metadata['volume_fraction'] (nodes, elem, elem_dof) = fem_solver.get_mesh() ᅟ (length_x, length_y) = (np.max(nodes[:, 0], 0), np.max(nodes[:, 1], 0)) (num_nodes_x, num_nodes_y) = (num_elem_x + 1, num_elem_y + 1) ᅟ nNODE = num_nodes_x * num_nodes_y nELEM = (num_nodes_x - 1) * (num_nodes_y - 1) nDOF = nNODE * 2 ᅟ # Input component ============================== # Independent variables are defined as outputs of IndepVarComp component comp = IndepVarComp() comp.add_output('force', val=force) comp.add_output('dvs', val=0.5, shape=nELEM) comp.add_design_var('dvs', lower=0.01, upper =1.0) ## Design variables self.add_subsystem ('cInputs', comp) ᅟ self.connect('cInputs.dvs', 'cFiltering.dvs') self.connect('cInputs.rhs', 'cState.rhs') self.connect('cInputs.rhs', 'cObjective.forces') ᅟ # density filter =============================== comp = DensityFilterComp(length_x=length_x, length_y=length_y, num_nodes_x=num_nodes_x, num_nodes_y=num_nodes_y, num_dvs=nELEM, radius=length_x / (float(num_nodes_x) - 1) * 2) self.add_subsystem('cFiltering', comp) self.connect('cFiltering.dvs_bar', 'cPenalty .x') self.connect('cFiltering.dvs_bar', 'cConstraint.x') ᅟ # penalization ================================= comp = PenalizationComp(num=nELEM, p=p) self.add_subsystem('cPenalty', comp) self.connect('cPenalty.y', 'cState.multipliers') ᅟ # states ======================================= comp = StatesComp(fem_solver=fem_solver, num_nodes_x=num_nodes_x, num_nodes_y= num_nodes_y, isSIMP = True) self.add_subsystem('cState', comp) self.connect('cState.states', 'cObjective.disp') ᅟ # compliance =================================== comp = ComplianceComp(num_nodes_x=num_nodes_x, num_nodes_y=num_nodes_y) comp.add_objective ('compliance') ## Objective self.add_subsystem('cObjective', comp) ᅟ # weight ======================================= comp = WeightComp(num=nELEM) comp.add_constraint ('weight', upper=volume_fraction) ## Constraint self.add_subsystem('cConstraint', comp)
Rights and permissions
About this article
Cite this article
Chung, H., Hwang, J.T., Gray, J.S. et al. Topology optimization in OpenMDAO. Struct Multidisc Optim 59, 1385–1400 (2019). https://doi.org/10.1007/s00158-019-02209-7
Received:
Revised:
Accepted:
Published:
Issue Date:
DOI: https://doi.org/10.1007/s00158-019-02209-7