treillis 1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- treillis/__init__.py +26 -0
- treillis/_generation/__init__.py +20 -0
- treillis/_generation/cutting.py +401 -0
- treillis/_generation/io.py +337 -0
- treillis/_generation/lattices.py +1500 -0
- treillis/_generation/meshes.py +847 -0
- treillis/_generation/packings.py +1121 -0
- treillis/_generation/redraw.py +742 -0
- treillis/_generation/utils.py +43 -0
- treillis/display/__init__.py +1 -0
- treillis/display/clean.py +840 -0
- treillis/display/fast.py +856 -0
- treillis/display/plot_utilitaries.py +144 -0
- treillis/mechanics/__init__.py +14 -0
- treillis/mechanics/elements.py +2113 -0
- treillis/mechanics/fracture.py +285 -0
- treillis/mechanics/moduli.py +285 -0
- treillis/mechanics/stiffness.py +270 -0
- treillis/mechanics/utils.py +59 -0
- treillis-1.0.dist-info/METADATA +17 -0
- treillis-1.0.dist-info/RECORD +24 -0
- treillis-1.0.dist-info/WHEEL +5 -0
- treillis-1.0.dist-info/licenses/LICENSE +165 -0
- treillis-1.0.dist-info/top_level.txt +1 -0
treillis/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
""""
|
|
2
|
+
Treillis
|
|
3
|
+
========
|
|
4
|
+
"""
|
|
5
|
+
from ._generation import makepacking, frompacking, call, Mesh
|
|
6
|
+
from ._generation import Domain, Lattice, Density, Density2, shake
|
|
7
|
+
from ._generation import savebins, saveascii, saveh5, loadLattice, last_pack
|
|
8
|
+
from ._generation import cutbrick, cutsphere, cutout, cut_2Dshape, isolate
|
|
9
|
+
from ._generation import mapping, flat_bounds, add_elements
|
|
10
|
+
from ._generation import vec_dist
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
style = os.path.abspath(os.path.dirname(__file__)
|
|
14
|
+
+ r'/display/PYLAT.mplstyle')
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
__all__ = ["makepacking", "frompacking", "call", "Mesh",
|
|
20
|
+
'Domain', 'Lattice', 'Density', 'Density2', 'shake',
|
|
21
|
+
'saveascii', 'loadLattice', 'savebins', 'saveascii', 'saveh5',
|
|
22
|
+
'last_pack',
|
|
23
|
+
'cutbrick', 'cutsphere', 'cutout', 'cut_2Dshape', 'isolate',
|
|
24
|
+
'mapping', 'flat_bounds', 'add_elements',
|
|
25
|
+
'style',
|
|
26
|
+
'vec_dist',]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""treillis's base package, to generate and modify lattices."""
|
|
2
|
+
|
|
3
|
+
from .packings import makepacking, frompacking
|
|
4
|
+
from .meshes import call, Mesh
|
|
5
|
+
from .lattices import Domain, Lattice, Density, Density2, shake
|
|
6
|
+
from .io import savebins, saveascii, saveh5, loadLattice, last_pack
|
|
7
|
+
from .cutting import cutbrick, cutsphere, cutout, cut_2Dshape, isolate
|
|
8
|
+
from .redraw import mapping, flat_bounds, add_elements
|
|
9
|
+
from .utils import vec_dist
|
|
10
|
+
|
|
11
|
+
from . import cutting, io, lattices, meshes, packings, redraw, utils
|
|
12
|
+
|
|
13
|
+
__all__ = ["makepacking", "frompacking", "call", "Mesh",
|
|
14
|
+
'Domain', 'Lattice', 'Density', 'Density2', 'shake',
|
|
15
|
+
'savebins', 'saveascii', 'saveh5', 'loadLattice',
|
|
16
|
+
'last_pack',
|
|
17
|
+
'cutbrick', 'cutsphere', 'cutout', 'cut_2Dshape', 'isolate',
|
|
18
|
+
'mapping', 'flat_bounds', 'add_elements',
|
|
19
|
+
'vec_dist',
|
|
20
|
+
]
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Cutting
|
|
3
|
+
=======
|
|
4
|
+
|
|
5
|
+
The objective of this module is to facilitate slicing into lattices.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
#%% Package importation
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
from copy import deepcopy
|
|
12
|
+
import numpy as np
|
|
13
|
+
from tqdm import trange
|
|
14
|
+
import ipyparallel as ipp
|
|
15
|
+
|
|
16
|
+
from scipy.spatial import Delaunay
|
|
17
|
+
|
|
18
|
+
from .lattices import Lattice
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
__all__ = ['cutbrick', 'cutsphere', 'cutout', 'cut_2Dshape', 'isolate']
|
|
22
|
+
|
|
23
|
+
#%% Small functions to reuse
|
|
24
|
+
|
|
25
|
+
def keep_elem(elements: np.ndarray, I_kept: np.ndarray):
|
|
26
|
+
"""Keep only the elements linked to the nodes in I_kept, and renumber them to corrsepond to the indices of I_kept."""
|
|
27
|
+
elems = deepcopy(elements)
|
|
28
|
+
keep = np.array([np.prod(np.isin(e, I_kept)) for e in elems[:,:2]],
|
|
29
|
+
dtype=bool)
|
|
30
|
+
elems = elems[keep]
|
|
31
|
+
|
|
32
|
+
# Renumbering the elements
|
|
33
|
+
for i in range(len(I_kept)):
|
|
34
|
+
if np.isin(I_kept[i], elems[:,:2]).any():
|
|
35
|
+
elems[elems[:,0]==I_kept[i],0] = i
|
|
36
|
+
elems[elems[:,1]==I_kept[i],1] = i
|
|
37
|
+
return elems
|
|
38
|
+
|
|
39
|
+
def keep_elem_prop(elements: np.ndarray, param: np.ndarray, I_kept: np.ndarray):
|
|
40
|
+
"""Keep only the element property for the elements linked to the nodes in I_kept."""
|
|
41
|
+
param = deepcopy(param)
|
|
42
|
+
keep = np.array([np.prod(np.isin(e, I_kept)) for e in elements[:,:2]],
|
|
43
|
+
dtype=bool)
|
|
44
|
+
param = param[keep]
|
|
45
|
+
return param
|
|
46
|
+
|
|
47
|
+
def isin(point, shape, sx, sy):
|
|
48
|
+
"""Consider a node in the plot if it is surrounded by at least 2 white points."""
|
|
49
|
+
x = np.linspace(-sx/2,sx/2,shape.shape[1])
|
|
50
|
+
y = np.linspace(-sy/2,sy/2,shape.shape[0])
|
|
51
|
+
|
|
52
|
+
Ix = np.argmin(abs(point[0]-x))
|
|
53
|
+
Iy = np.argmin(abs(point[1]-y))
|
|
54
|
+
|
|
55
|
+
x0 = max(Ix-1, 0)
|
|
56
|
+
xf = min(Ix+1, shape.shape[1])
|
|
57
|
+
|
|
58
|
+
y0 = max(Iy-1, 0)
|
|
59
|
+
yf = min(Iy+1, shape.shape[0])
|
|
60
|
+
|
|
61
|
+
return np.sum(shape[y0:yf, x0:xf])>1
|
|
62
|
+
|
|
63
|
+
#%% Main functions
|
|
64
|
+
#%%% Basic shapes
|
|
65
|
+
|
|
66
|
+
def cutbrick(lattice: Lattice, xlims: list|None = None,
|
|
67
|
+
ylims: list|None = None, zlims: list|None = None):
|
|
68
|
+
"""Create a sliced lattice from within limits (=[[x_min,x_max], [y_min,y_max], [z_min,z_max]])."""
|
|
69
|
+
nodes = deepcopy(lattice.nodes)
|
|
70
|
+
elems = deepcopy(lattice.elems)
|
|
71
|
+
I = np.arange(len(nodes))
|
|
72
|
+
|
|
73
|
+
if xlims is None: xlims = [-np.inf, np.inf]
|
|
74
|
+
if ylims is None: ylims = [-np.inf, np.inf]
|
|
75
|
+
|
|
76
|
+
if xlims[0]<-lattice.sizedom[0]/2 and xlims[1]>lattice.sizedom[0]/2\
|
|
77
|
+
and ylims[0]<-lattice.sizedom[1]/2 and ylims[1]>lattice.sizedom[1]/2:
|
|
78
|
+
if zlims is None: return lattice
|
|
79
|
+
elif zlims[0]<-lattice.sizedom[2]/2\
|
|
80
|
+
and zlims[1]>lattice.sizedom[2]/2: return lattice
|
|
81
|
+
|
|
82
|
+
# For safety: we recalculate the limits to be within the lattice
|
|
83
|
+
xlims = [max(xlims[0], -lattice.sizedom[0]/2),
|
|
84
|
+
min(xlims[1], lattice.sizedom[0]/2)]
|
|
85
|
+
ylims = [max(ylims[0], -lattice.sizedom[1]/2),
|
|
86
|
+
min(ylims[1], lattice.sizedom[1]/2)]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
Ix = I[(nodes[:,0]>=xlims[0]) & (nodes[:,0]<=xlims[1])]
|
|
90
|
+
Iy = I[(nodes[:,1]>=ylims[0]) & (nodes[:,1]<=ylims[1])]
|
|
91
|
+
|
|
92
|
+
Ii = np.intersect1d(Ix, Iy)
|
|
93
|
+
|
|
94
|
+
if zlims is not None and lattice.dim==3:
|
|
95
|
+
zlims = [max(zlims[0], -lattice.sizedom[2]/2),
|
|
96
|
+
min(zlims[1], lattice.sizedom[2]/2)]
|
|
97
|
+
Iz = I[(nodes[:,2]>=zlims[0]) & (nodes[:,2]<=zlims[1])]
|
|
98
|
+
If = np.intersect1d(Ii, Iz)
|
|
99
|
+
else: If = Ii
|
|
100
|
+
|
|
101
|
+
# Redefining the parameters corresponding to the elems
|
|
102
|
+
ratio = keep_elem_prop(lattice.elems, lattice.aspect_ratio, If)
|
|
103
|
+
if isinstance(lattice.beam_section, np.ndarray):
|
|
104
|
+
section = keep_elem_prop(lattice.elems, lattice.beam_section, If)
|
|
105
|
+
else: section = lattice.beam_section
|
|
106
|
+
|
|
107
|
+
elems = keep_elem(elems, If)
|
|
108
|
+
return Lattice(lattice.nodes[If,:], elems, length=lattice.L,
|
|
109
|
+
inimesh=lattice.type, beam_section=section,
|
|
110
|
+
aspect_ratio=ratio)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def cutsphere(lattice: Lattice, pos: np.ndarray = None, rlim: float = None):
|
|
114
|
+
"""Cut the lattice in a spherical shape at the given position and radius."""
|
|
115
|
+
if pos is not None:
|
|
116
|
+
pos = np.array(pos).reshape((1, lattice.dim))
|
|
117
|
+
else: pos = np.zeros_like(lattice.nodes)
|
|
118
|
+
nodes = deepcopy(lattice.nodes)
|
|
119
|
+
nodes -= pos
|
|
120
|
+
elems = deepcopy(lattice.elems)
|
|
121
|
+
I = np.arange(len(nodes))
|
|
122
|
+
|
|
123
|
+
if rlim is not None:
|
|
124
|
+
lmax = np.max(np.sqrt(np.sum(nodes**2, axis=1)))
|
|
125
|
+
if rlim<=lmax:
|
|
126
|
+
cond = np.sqrt(np.sum(nodes**2, axis=1))<=rlim
|
|
127
|
+
If = I[cond]
|
|
128
|
+
|
|
129
|
+
# Selecting the ROI
|
|
130
|
+
nodes = nodes[If,:]
|
|
131
|
+
|
|
132
|
+
# Redefining the parameters corresponding to the elems
|
|
133
|
+
ratio = keep_elem_prop(elems, lattice.aspect_ratio, If)
|
|
134
|
+
if isinstance(lattice.beam_section, np.ndarray):
|
|
135
|
+
section = keep_elem_prop(elems, lattice.beam_section, If)
|
|
136
|
+
else: section = lattice.beam_section
|
|
137
|
+
|
|
138
|
+
elems = keep_elem(elems, If)
|
|
139
|
+
return Lattice(nodes, elems, length=lattice.L,
|
|
140
|
+
inimesh=lattice.type, beam_section=section,
|
|
141
|
+
aspect_ratio=ratio, size = np.array([rlim]))
|
|
142
|
+
|
|
143
|
+
print("There is no change in the lattice.")
|
|
144
|
+
return lattice
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def cutout(lattice: Lattice, position: np.ndarray, size: float|np.ndarray):
|
|
148
|
+
"""
|
|
149
|
+
Cut out a brick or a spherical shape in the lattice.
|
|
150
|
+
|
|
151
|
+
Parameters
|
|
152
|
+
----------
|
|
153
|
+
lattice : Lattice
|
|
154
|
+
Lattice to cut out.
|
|
155
|
+
position : np.ndarray
|
|
156
|
+
Position of the cut. Center of the sphere, or lower back left side of the brick.
|
|
157
|
+
size : float|np.ndarray
|
|
158
|
+
If only one value, radius of the sphere, if more values, respectively lengths along x, y, and z of the brick cutout.
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
-------
|
|
162
|
+
Lattice
|
|
163
|
+
Lattice with shape cut out.
|
|
164
|
+
|
|
165
|
+
Examples
|
|
166
|
+
--------
|
|
167
|
+
Cut out the center of a spherical lattice.
|
|
168
|
+
|
|
169
|
+
>>> import treillis
|
|
170
|
+
>>> lat = treillis.Lattice.initialize(10, 1, 'TriDT3D')
|
|
171
|
+
>>> cutlat = treillis.cutout(lat, [0,0,0], 8)
|
|
172
|
+
"""
|
|
173
|
+
nodes = deepcopy(lattice.nodes)
|
|
174
|
+
elems = deepcopy(lattice.elems)
|
|
175
|
+
elmpos = np.concatenate((
|
|
176
|
+
nodes[elems[:,0].astype(int)]\
|
|
177
|
+
.reshape(elems.shape[0],lattice.dim,1),
|
|
178
|
+
nodes[elems[:,1].astype(int)]\
|
|
179
|
+
.reshape(elems.shape[0],lattice.dim,1)), axis=2)
|
|
180
|
+
shape = 'brick'
|
|
181
|
+
|
|
182
|
+
try: len(position) == lattice.dim
|
|
183
|
+
except: raise ValueError("Initial position cannot be a float.")
|
|
184
|
+
position = np.array(position)
|
|
185
|
+
if len(position) != lattice.dim:
|
|
186
|
+
raise ValueError("Lattice is ", lattice.dim,
|
|
187
|
+
"D, but initial position is ", len(position),
|
|
188
|
+
"D.")
|
|
189
|
+
|
|
190
|
+
if not isinstance(size, (list, np.ndarray)): shape = 'sphere'
|
|
191
|
+
elif len(size) == 1: shape = 'sphere'
|
|
192
|
+
|
|
193
|
+
I = np.arange(elmpos.shape[0])
|
|
194
|
+
|
|
195
|
+
if shape=='sphere':
|
|
196
|
+
cond = (np.sqrt(np.sum((elmpos[:,:,0]-position)**2, axis=1)) <= size)\
|
|
197
|
+
+ (np.sqrt(np.sum((elmpos[:,:,1]-position)**2, axis=1)) <= size)
|
|
198
|
+
cond = cond.astype(bool)
|
|
199
|
+
else:
|
|
200
|
+
condx = (elmpos[:,0,:] >= position[0])\
|
|
201
|
+
* (elmpos[:,0,:]-position[0] < size[0])
|
|
202
|
+
condy = (elmpos[:,1,:] >= position[1])\
|
|
203
|
+
* (elmpos[:,1,:]-position[1] < size[1])
|
|
204
|
+
|
|
205
|
+
cond = condx * condy
|
|
206
|
+
|
|
207
|
+
if len(size) == 3:
|
|
208
|
+
if lattice.dim == 3:
|
|
209
|
+
condz = (elmpos[:,2,:] >= position[2])\
|
|
210
|
+
* (elmpos[:,2,:]-position[2] < size[2])
|
|
211
|
+
cond = cond * condz
|
|
212
|
+
else:
|
|
213
|
+
print("Warning: size is in 3D, but lattice is only 2D: third dimension will be ignored.")
|
|
214
|
+
|
|
215
|
+
cond = np.sum(cond, axis=1, dtype=bool)
|
|
216
|
+
|
|
217
|
+
if len(size) < len(position):
|
|
218
|
+
S = np.zeros(position.shape)
|
|
219
|
+
S[:len(size)] = size
|
|
220
|
+
size = S
|
|
221
|
+
else: size = np.array(size)
|
|
222
|
+
|
|
223
|
+
trans = (elmpos[:,:,0] < np.repeat(position.reshape(1, lattice.dim),
|
|
224
|
+
elmpos.shape[0], axis=0))\
|
|
225
|
+
* (elmpos[:,:,1] >= np.repeat(position.reshape(1, lattice.dim),
|
|
226
|
+
elmpos.shape[0], axis=0)\
|
|
227
|
+
+ np.repeat(size.reshape(1, lattice.dim),
|
|
228
|
+
elmpos.shape[0], axis=0))
|
|
229
|
+
trans = np.sum(trans, axis=1, dtype=bool)
|
|
230
|
+
|
|
231
|
+
cond = cond + trans
|
|
232
|
+
|
|
233
|
+
keep = np.delete(I, cond)
|
|
234
|
+
elmpos = elmpos[keep]
|
|
235
|
+
|
|
236
|
+
ratio = lattice.aspect_ratio[keep]
|
|
237
|
+
if isinstance(lattice.beam_section, np.ndarray):
|
|
238
|
+
section = lattice.beam_section[keep]
|
|
239
|
+
else: section = lattice.beam_section
|
|
240
|
+
|
|
241
|
+
nodes = np.concatenate((elmpos[:,:,0], elmpos[:,:,1]), axis=0)
|
|
242
|
+
nodes = np.unique(nodes, axis=0)
|
|
243
|
+
|
|
244
|
+
Inodes = np.arange(nodes.shape[0])
|
|
245
|
+
|
|
246
|
+
elems = np.concatenate((
|
|
247
|
+
np.array([[Inodes[np.prod(nodes == e, axis=1, dtype=bool)]]
|
|
248
|
+
for e in elmpos[:,:,0]]),
|
|
249
|
+
np.array([[Inodes[np.prod(nodes == e, axis=1, dtype=bool)]]
|
|
250
|
+
for e in elmpos[:,:,1]])), axis=1)
|
|
251
|
+
elems = elems.reshape(elems.shape[0], 2)
|
|
252
|
+
|
|
253
|
+
return Lattice(nodes, elems, length=lattice.L,
|
|
254
|
+
inimesh=lattice.type, beam_section=section,
|
|
255
|
+
aspect_ratio=ratio, size = lattice.sizedom)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def isolate(lattice: Lattice):
|
|
261
|
+
"""Clusterize a cut lattice in a list of sub-lattices."""
|
|
262
|
+
node_list = np.arange(lattice.nodes.shape[0])
|
|
263
|
+
Lattices = []
|
|
264
|
+
|
|
265
|
+
contacts = lattice.contacts_list
|
|
266
|
+
|
|
267
|
+
print("Getting the separate clusters")
|
|
268
|
+
while len(node_list) > 0:
|
|
269
|
+
c0 = node_list[0]
|
|
270
|
+
Lattices.append(np.array([c0]))
|
|
271
|
+
l = contacts[c0]
|
|
272
|
+
l = l[np.isin(l, Lattices[-1], invert=True)]
|
|
273
|
+
while len(l>0):
|
|
274
|
+
Lattices[-1] = np.concatenate((Lattices[-1], l))
|
|
275
|
+
Lattices[-1] = np.unique(Lattices[-1])
|
|
276
|
+
|
|
277
|
+
l = np.concatenate([contacts[i] for i in l])
|
|
278
|
+
l = np.unique(l)
|
|
279
|
+
l = l[np.isin(l, Lattices[-1], invert=True)]
|
|
280
|
+
|
|
281
|
+
print('Found', len(Lattices), 'clusters')
|
|
282
|
+
node_list = node_list[np.isin(node_list, Lattices[-1],
|
|
283
|
+
invert=True)]
|
|
284
|
+
|
|
285
|
+
if len(Lattices)==1:
|
|
286
|
+
print("No sub-lattice found")
|
|
287
|
+
return lattice
|
|
288
|
+
|
|
289
|
+
print("Creating the sub-lattices")
|
|
290
|
+
lat_list = []
|
|
291
|
+
for i in trange(len(Lattices)):
|
|
292
|
+
idx = Lattices[i]
|
|
293
|
+
mask_elm = np.prod(np.isin(
|
|
294
|
+
lattice.elems[:,:2], idx), axis=1, dtype=bool)
|
|
295
|
+
|
|
296
|
+
elm = keep_elem(lattice.elems, idx)
|
|
297
|
+
|
|
298
|
+
if type(lattice.beam_section)!=str:
|
|
299
|
+
beam = lattice.beam_section[mask_elm]
|
|
300
|
+
else: beam = lattice.beam_section
|
|
301
|
+
|
|
302
|
+
lat = Lattice(lattice.nodes[idx],
|
|
303
|
+
elm,
|
|
304
|
+
size=lattice.sizedom, length=lattice.L,
|
|
305
|
+
inimesh=lattice.type,
|
|
306
|
+
aspect_ratio=lattice.aspect_ratio[mask_elm],
|
|
307
|
+
beam_section=beam)
|
|
308
|
+
|
|
309
|
+
lat_list.append(lat)
|
|
310
|
+
|
|
311
|
+
return lat_list
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
#%%% Fun shapes
|
|
315
|
+
def cut_2Dshape(lattice: Lattice, shape: np.ndarray,
|
|
316
|
+
sx: float = None, sy: float = None):
|
|
317
|
+
"""
|
|
318
|
+
Cutout a 2D shape described by a black-and-white image in a lattice.
|
|
319
|
+
|
|
320
|
+
By convention, the shape will be cutout in the XY plane.
|
|
321
|
+
|
|
322
|
+
Parameters
|
|
323
|
+
----------
|
|
324
|
+
lattice : Lattice
|
|
325
|
+
The lattice you want to cut
|
|
326
|
+
shape : 2D np.ndarray
|
|
327
|
+
A black and white image encoded in 0s and 1s. By convention, the nodes
|
|
328
|
+
that are kept are in the
|
|
329
|
+
sx : float, optional
|
|
330
|
+
the size along the x-axis of the image. If not given, will be the
|
|
331
|
+
width of the lattice.
|
|
332
|
+
sy: float, optional
|
|
333
|
+
the size along the y-axis of the image. If not given, will be the height
|
|
334
|
+
of the lattice.
|
|
335
|
+
|
|
336
|
+
Returns
|
|
337
|
+
-------
|
|
338
|
+
Lattice
|
|
339
|
+
|
|
340
|
+
Examples
|
|
341
|
+
--------
|
|
342
|
+
Cutting a star-shape in a lattice.
|
|
343
|
+
|
|
344
|
+
>>> import numpy as np
|
|
345
|
+
>>> import treillis
|
|
346
|
+
>>> # create a lattice
|
|
347
|
+
>>> lat = treillis.Lattice.initialize([50, 50], 2, 'Vor', des=.1)
|
|
348
|
+
>>> # create the cutting template
|
|
349
|
+
>>> star = np.array([
|
|
350
|
+
>>> [0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],
|
|
351
|
+
>>> [0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0],
|
|
352
|
+
>>> [0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0],
|
|
353
|
+
>>> [0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0],
|
|
354
|
+
>>> [0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0],
|
|
355
|
+
>>> [0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0],
|
|
356
|
+
>>> [0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0],
|
|
357
|
+
>>> [0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0],
|
|
358
|
+
>>> [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
|
|
359
|
+
>>> [0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
|
|
360
|
+
>>> [0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0],
|
|
361
|
+
>>> [0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0],
|
|
362
|
+
>>> [0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
|
|
363
|
+
>>> [0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
|
|
364
|
+
>>> [0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
|
|
365
|
+
>>> [0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
|
|
366
|
+
>>> [0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
|
|
367
|
+
>>> [0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
|
|
368
|
+
>>> [0,0,0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0],
|
|
369
|
+
>>> [0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0],
|
|
370
|
+
>>> [0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0]])
|
|
371
|
+
>>> starlat = treillis.cut_2Dshape(lat, star)
|
|
372
|
+
|
|
373
|
+
Because of the way the node position is implemented, the star will be
|
|
374
|
+
upside-down in the lattice.
|
|
375
|
+
"""
|
|
376
|
+
nodes = deepcopy(lattice.nodes)
|
|
377
|
+
elems = deepcopy(lattice.elems)
|
|
378
|
+
if sx==0 or sy==0: raise ValueError("Cannot cut a 1D line in a lattice.")
|
|
379
|
+
if sx is None: sx = np.max(lattice.nodes[:,0])-np.min(lattice.nodes[:,0])
|
|
380
|
+
if sy is None: sy = np.max(lattice.nodes[:,1])-np.min(lattice.nodes[:,1])
|
|
381
|
+
|
|
382
|
+
I = np.arange(len(lattice.nodes))
|
|
383
|
+
|
|
384
|
+
I_ok = []
|
|
385
|
+
for i in range(len(lattice.nodes)):
|
|
386
|
+
if isin(lattice.nodes[i,:2], shape, sx, sy): I_ok.append(I[i])
|
|
387
|
+
|
|
388
|
+
nodes = nodes[I_ok,:]
|
|
389
|
+
# Redefining the parameters corresponding to the elems
|
|
390
|
+
ratio = keep_elem_prop(elems, lattice.aspect_ratio, I_ok)
|
|
391
|
+
if isinstance(lattice.beam_section, np.ndarray):
|
|
392
|
+
section = keep_elem_prop(elems, lattice.beam_section, I_ok)
|
|
393
|
+
else: section = lattice.beam_section
|
|
394
|
+
|
|
395
|
+
elems = keep_elem(elems, I_ok)
|
|
396
|
+
return Lattice(nodes, elems, length=lattice.L,
|
|
397
|
+
inimesh=lattice.type, beam_section=section,
|
|
398
|
+
aspect_ratio=ratio)
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
|