2.7.2: A Simplified ESO-Procedure on Shells
The example file “SimpleShellEso.gh” contains also a Python script which performs a simple evolutionary structural optimization (ESO) procedure on shell elements. As it applies no filters for calculating the fitness of individual shell triangles checkerboard patterns result (see fig. 2.7.2.1). Alas the script can be easily extended to include more elaborate fitness calculation schemes.
Fig. 2.7.2.1: SimpleShellEso.gh
The script shows how to work directly with the C++ model in order to avoid costly mappings to and from the C#-model:
1
import clr
2
3
clr.AddReferenceToFileAndPath("C:\Program Files\Rhino 6\Plug-ins\Karamba\Karamba.gha")
4
clr.AddReferenceToFileAndPath("C:\Program Files\Rhino 6\Plug-ins\Karamba\KarambaCommon.dll")
5
6
import Karamba.Models.Model as Model
7
import Karamba.Elements.ModelShell as Shell
8
import Karamba.Materials.FemMaterial_Isotrop as FemMaterial
9
import feb.ShellMesh as ShellMesh
10
import feb.TriShell3D as TriShell3D
11
import feb.VectSurface3DSigEps as TriStates
12
import feb.Deform as Deform
13
import feb.Response as Response
14
import feb.EnergyVisitor as EnergyVisitor
15
import Rhino.Geometry as Rh
16
17
from operator import attrgetter
18
19
# encapsulate ESO properties of shell elements
20
class EsoItem:
21
def __init__(self, shell_elem, elem_ind):
22
self.active = True
23
self.fitness = 0
24
self.shell_elem = shell_elem
25
self.area = shell_elem.area()
26
self.ind = elem_ind
27
28
def update(self, energy_visitor):
29
self.fitness = energy_visitor.elasticEnergy(self.ind) / self.area
30
31
32
# clone model to avoid side effects
33
model = Model_in.Clone()
34
model.deepCloneFEModel()
35
36
# generate ESO properties of each triangular shell element
37
eso_items = []
38
for elem in model.elems:
39
if type(elem) != Shell:
40
continue
41
tri_mesh = model.febmodel.triMesh(elem.fe_id)
42
for i in xrange(tri_mesh.numberOfElems()):
43
eso_items.append(EsoItem(tri_mesh.elem(i), i))
44
45
nremove_per_iter = int(NRemove/NIter+1)
46
n_removed = 0
47
48
# do the ESO iterations
49
for iter in xrange(NIter):
50
analysis = Deform(model.febmodel)
51
response = Response(analysis)
52
53
try:
54
response.updateNodalDisplacements()
55
response.updateMemberForces()
56
except:
57
raise Exception("singular stiffness")
58
59
energy_visitor = EnergyVisitor(model.febmodel, model.febmodel.state(0), 0);
60
energy_visitor.visit(model.febmodel);
61
62
for eso_item in eso_items:
63
eso_item.update(energy_visitor)
64
65
eso_items = sorted(eso_items, key = attrgetter("fitness"))
66
67
n_removed_per_iter = 0
68
has_changed = False
69
for eso_item in eso_items:
70
if (n_removed >= NRemove): break
71
if (n_removed_per_iter >= nremove_per_iter): break
72
if (eso_item.active == False):
73
continue
74
eso_item.shell_elem.softKilled(True)
75
eso_item.active = False
76
n_removed +=1
77
n_removed_per_iter +=1
78
79
has_changed = True
80
if (has_changed == False):
81
break
82
model.febmodel.touch()
83
84
# create active and inactive mesh for output
85
active_mesh = Rh.Mesh()
86
inactive_mesh = Rh.Mesh()
87
for i in xrange(model.febmodel.numberOfNodes()):
88
feb_pos = model.febmodel.node(i).pos()
89
active_mesh.Vertices.Add(Rh.Point3d(feb_pos.x(), feb_pos.y(), feb_pos.z()))
90
inactive_mesh.Vertices.Add(Rh.Point3d(feb_pos.x(), feb_pos.y(), feb_pos.z()))
91
92
for eso_item in eso_items:
93
ind0 = eso_item.shell_elem.node(0).ind()
94
ind1 = eso_item.shell_elem.node(1).ind()
95
ind2 = eso_item.shell_elem.node(2).ind()
96
if (eso_item.active):
97
active_mesh.Faces.AddFace(Rh.MeshFace(ind0, ind1, ind2))
98
else:
99
inactive_mesh.Faces.AddFace(Rh.MeshFace(ind0, ind1, ind2))
100
101
activeMesh = active_mesh
102
inactiveMesh = inactive_mesh
Copied!
In the above code the class “ESOItem” handles the book-keeping necessary in the optimization steps. it contains the activation-state, the fitness, the element’s area, a reference to the C++-element and the element’s index in the C#-model. The “update”-method calculates the specific elastic energy of the underlying shell-element.
Activation and deactivation of model elements works via setting the soft-kill status of C++-elements to “True” or “False” (see line 74). On model-assembly the stiffness of the corresponding element will be multiplied with the soft-kill-factor which is 1.0×10^−10. This factor can be set on the C++-model via “softKillFactor(new_factor)” if necessary.
The last part of the script categorizes the shell-faces into active or in-active adding their geometry to the corresponding output-meshes.
SimpleShellEso.gh
25KB
Binary
Last modified 16d ago
Copy link