Skip to content

Commit a8858e2

Browse files
committed
Merge branch 'master' of https://github.com/compas-dev/compas
2 parents 194b11b + fe8ccee commit a8858e2

File tree

4 files changed

+229
-130
lines changed

4 files changed

+229
-130
lines changed

src/compas/hpc/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
core.euler.kill_job
112112
core.euler.sync_folder_to_euler
113113
114+
114115
numba
115116
-----
116117

src/compas/hpc/algorithms/devo_numba.py

Lines changed: 0 additions & 129 deletions
This file was deleted.

src/compas/numerical/algorithms/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
from .fd_numpy import *
55
from .fd_cpp import *
66
from .pca_numpy import *
7+
from .topop_numpy import *
78

89
from .dr import __all__ as a
910
from .dr_numpy import __all__ as b
1011
from .drx_numpy import __all__ as c
1112
from .fd_numpy import __all__ as d
1213
from .fd_cpp import __all__ as e
1314
from .pca_numpy import __all__ as f
15+
from .topop_numpy import __all__ as g
1416

15-
__all__ = a + b + c + d + e + f
17+
__all__ = a + b + c + d + e + f + g
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
from __future__ import absolute_import
2+
from __future__ import division
3+
from __future__ import print_function
4+
5+
from numpy import abs
6+
from numpy import array
7+
from numpy import ceil
8+
from numpy import dot
9+
from numpy import hstack
10+
from numpy import kron
11+
from numpy import max
12+
from numpy import maximum
13+
from numpy import min
14+
from numpy import minimum
15+
from numpy import newaxis
16+
from numpy import ones
17+
from numpy import ravel
18+
from numpy import reshape
19+
from numpy import sqrt
20+
from numpy import squeeze
21+
from numpy import sum
22+
from numpy import tile
23+
from numpy import vstack
24+
from numpy import zeros
25+
26+
from scipy.sparse import coo_matrix
27+
from scipy.sparse.linalg import spsolve
28+
29+
from matplotlib import pyplot as plt
30+
31+
32+
__author__ = ['Andrew Liew <[email protected]>']
33+
__copyright__ = 'Copyright 2017, BLOCK Research Group - ETH Zurich'
34+
__license__ = 'MIT License'
35+
__email__ = '[email protected]'
36+
37+
38+
__all__ = [
39+
'topop2d_numpy'
40+
]
41+
42+
43+
def topop2d_numpy(nelx, nely, loads, supports, volfrac=0.5, penal=3, rmin=1.5):
44+
""" Topology optimisation in 2D using NumPy and SciPy.
45+
46+
Parameters
47+
----------
48+
nelx (int): Number of elements in x.
49+
nely (int): Number of elements in y.
50+
loads (dic): {'i-j': [Px, Py]}.
51+
supports (dic): {'i-j': [Bx, By]} 1=fixed, 0=free.
52+
volfrac (float): Volume fraction.
53+
penal (float): Penalisation power.
54+
rmin (float): Filter radius.
55+
56+
Returns
57+
-------
58+
array: Density array.
59+
60+
References
61+
----------
62+
Based on the MATLAB code from [andreassen2011]_.
63+
"""
64+
nx = nelx + 1
65+
ny = nely + 1
66+
nn = nx * ny
67+
ne = nelx * nely
68+
ndof = 2 * nn
69+
dv = ones((nely, nelx))
70+
71+
# Finite element analysis
72+
73+
v = 0.3
74+
E = 1.
75+
Emin = 10**(-10)
76+
77+
A11 = array([[12, +3, -6, -3], [+3, 12, +3, +0], [-6, +3, 12, -3], [-3, +0, -3, 12]])
78+
A12 = array([[-6, -3, +0, +3], [-3, -6, -3, -6], [+0, -3, -6, +3], [+3, -6, +3, -6]])
79+
B11 = array([[-4, +3, -2, +9], [+3, -4, -9, +4], [-2, -9, -4, -3], [+9, +4, -3, -4]])
80+
B12 = array([[+2, -3, +4, -9], [-3, +2, +9, -2], [+4, +9, +2, +3], [-9, -2, +3, +2]])
81+
A21 = A12.transpose()
82+
B21 = B12.transpose()
83+
A = vstack([hstack([A11, A12]), hstack([A21, A11])])
84+
B = vstack([hstack([B11, B12]), hstack([B21, B11])])
85+
86+
Ke = 1 / (1 - v**2) / 24 * (A + v * B)
87+
Ker = ravel(Ke, order='F')[:, newaxis]
88+
nodes = reshape(range(1, nn + 1), (ny, nx), order='F')
89+
eVec = tile(reshape(2 * nodes[:-1, :-1], (ne, 1), order='F'), (1, 8))
90+
edof = eVec + tile(hstack([array([0, 1]), 2 * nely + array([2, 3, 0, 1]), array([-2, -1])]), (ne, 1))
91+
iK = reshape(kron(edof, ones((8, 1))).transpose(), (64 * ne), order='F')
92+
jK = reshape(kron(edof, ones((1, 8))).transpose(), (64 * ne), order='F')
93+
94+
# Supports
95+
96+
U = zeros((ndof, 1))
97+
fixed = []
98+
for support, B in supports.items():
99+
ib, jb = [int(i) for i in support.split('-')]
100+
Bx, By = B
101+
node = int(jb * (nely + 1) + ib)
102+
if Bx:
103+
fixed.append(2 * node)
104+
if By:
105+
fixed.append(2 * node + 1)
106+
free = list(set(range(ndof)) - set(fixed))
107+
108+
# Loads
109+
110+
data = []
111+
rows = []
112+
cols = []
113+
for load, P in loads.items():
114+
ip, jp = [int(i) for i in load.split('-')]
115+
Px, Py = P
116+
node = int(jp * (nely + 1) + ip)
117+
data.extend([Px, Py])
118+
rows.extend([2 * node, 2 * node + 1])
119+
cols.extend([0, 0])
120+
F = coo_matrix((data, (rows, cols)), shape=(ndof, 1))
121+
Find = F.tocsr()[free]
122+
123+
# Filter
124+
125+
iH = zeros(ne * (2 * (int(ceil(rmin)) - 1) + 1)**2)
126+
jH = zeros(iH.shape)
127+
sH = zeros(iH.shape)
128+
129+
k = 0
130+
for i1 in range(nelx):
131+
for j1 in range(nely):
132+
133+
e1 = i1 * nely + j1
134+
max_i = int(max([i1 - (ceil(rmin) - 1), 0]))
135+
min_i = int(min([i1 + (ceil(rmin) - 1), nelx - 1]))
136+
137+
for i2 in range(max_i, min_i + 1):
138+
max_j = int(max([j1 - (ceil(rmin) - 1), 0]))
139+
min_j = int(min([j1 + (ceil(rmin) - 1), nely - 1]))
140+
141+
for j2 in range(max_j, min_j + 1):
142+
k += 1
143+
e2 = i2 * nely + j2
144+
iH[k] = e1
145+
jH[k] = e2
146+
sH[k] = max([0, rmin - sqrt((i1 - i2)**2 + (j1 - j2)**2)])
147+
148+
H = coo_matrix((sH, (iH, jH)))
149+
Hs = sum(H.toarray(), 1)
150+
151+
# Set-up plot
152+
153+
plt.axis([0, nelx, 0, nely])
154+
plt.ion()
155+
156+
# Main loop
157+
158+
iteration = 0
159+
change = 1
160+
move = 0.2
161+
x = tile(volfrac, (nely, nelx))
162+
xP = x * 1.
163+
nones = ones((ne)) * 0.001
164+
165+
while change > 0.1:
166+
167+
# FE
168+
169+
xrav = ravel(xP, order='F').transpose()
170+
sK = reshape(Ker * (Emin + xrav**penal * (E - Emin)), (64 * ne), order='F')
171+
K = coo_matrix((sK, (iK, jK))).tocsr()
172+
Kind = (K.tocsc()[:, free]).tocsr()[free, :]
173+
U[free] = spsolve(Kind, Find)[:, newaxis]
174+
175+
# Objective functions
176+
177+
ce = reshape(sum(dot(squeeze(U[edof]), Ke) * squeeze(U[edof]), 1), (nely, nelx), order='F')
178+
c = sum(sum((Emin + xP**penal * (E - Emin)) * ce))
179+
dc = -penal * (E - Emin) * xP**(penal - 1) * ce
180+
xdc = squeeze(H.dot(ravel(x * dc, order='F')[:, newaxis]))
181+
dc = reshape(xdc / Hs / maximum(nones, ravel(x, order='F')), (nely, nelx), order='F')
182+
183+
# Lagrange mulipliers
184+
185+
l1 = 0
186+
l2 = 10**9
187+
while (l2 - l1) / (l1 + l2) > 0.001:
188+
lmid = 0.5 * (l2 + l1)
189+
sdv = sqrt(-dc / dv / lmid)
190+
min1 = minimum(x + move, x * sdv)
191+
xn = maximum(0, maximum(x - move, minimum(1, min1)))
192+
xP = xn * 1.
193+
if sum(xP) > volfrac * ne:
194+
l1 = lmid
195+
else:
196+
l2 = lmid
197+
change = max(abs(xn - x))
198+
199+
# Update
200+
201+
x = xn * 1.
202+
plt.imshow(1 - x, cmap='gray', origin='lower')
203+
plt.pause(0.001)
204+
205+
iteration += 1
206+
207+
print('Iteration: {0} Compliance: {1:.4g}'.format(iteration, c))
208+
209+
return x
210+
211+
212+
# ==============================================================================
213+
# Main
214+
# ==============================================================================
215+
216+
if __name__ == "__main__":
217+
218+
loads = {
219+
'40-200': [0, -1]}
220+
221+
supports = {
222+
'0-0': [1, 1],
223+
'0-400': [0, 1]}
224+
225+
x = topop2d_numpy(nelx=400, nely=40, loads=loads, supports=supports, volfrac=0.5)

0 commit comments

Comments
 (0)