C2.9 Refinement

(by Lotte)

Objectives

You will learn how to refine the design of the form active structure through a denser mesh and by tweaking the force densities to fit a structurally performative design target. Further, you will export your results to materialise the form-found geometry in the next step of D. Fabrication.

Procedure

The file is the same as in C2.8 Concrete Selfweight with the following modifications:

a. Mesh Subdivision

So far, the form finding was highly simplified because of its mesh's low resolution: the loads were only applied at the vertices along the crease cables and there was only one edge connecting the crease to the supporting arches, building a straight line. However, the knit is expected to sag under the weight of the concrete and build a curve. Thus, we must subdivide the mesh towards a higher resolution.

a1. First Subdivision

In order to subdivide the mesh, we subdivide the mesh right after the construction of the mesh and before assigning the attributes. We use the Mesh.subdivide method with the 'quad'-scheme to keep the quad structure.

# ==============================================================================
# Cablenet mesh datastructure
# ==============================================================================

# create the mesh from imported geometry
mesh = Mesh.from_json(FILE_I)

# ==============================================================================
# a1. Subdivison > NEW
# ==============================================================================
mesh = mesh.subdivide(scheme='quad', k=1)

# set default vertex attributes
...

Since we will now have twice the amount of longitudinal cables we must adjust the index of the continuous cables by multiplying it with a densification factor of 2.

...
# ==============================================================================
# Add centre vertices to anchors
# ==============================================================================
# a1. density factor > NEW
factor = 2

...
centre_vertices = list(set(flatten(cables[2 * factor])))  # a1. NEW!

...

mesh.edges_attribute('q', 10, keys=cables[1 * factor] + cables[ 3 * factor])  # a1. NEW! # noqa: E501

The resulting form found mesh has now also loads applied along the knit and the subdivided edges can form a curve:

a2. Second Subdivision

In order to subdivide the mesh further, we use the same function but set the subdivision factor k to 2:

...
# ==============================================================================
# a2. Subdivison > NEW
# ==============================================================================
mesh = mesh.subdivide(scheme='quad', k=2)
...

The longitudinal mesh edges will double again, thus we must double the factor of 2 resulting to 4:

...
# a2. density factor > NEW
factor = 4
...

Now the loads are applied very distributed and the knit shapes such a strong curve that the crease almost disappears:

The disappearance of the crease is also due to the fact that we input the force ratio of cables to knit through the force density. However, the force density is a measure per edge and not per knit width! This means that if we double the knit edges, we also double the force densities per length, resulting in a different ratio of force in the knit to the force in the cables as we had before. Basically, the mesh is pulled up as we densify. This can also be observed in the comparison of the sections of the meshes with three different resolutions: the denser the mesh, the higher.

So in the next step, let's adjust the force densities.

What you might have realised is that the computation time increased dramatically as the iterations under self-weight don't converge. This is because the sum of residuals stays above a certain threshold because now we have many more vertices. You can either increase the threshold, check the progression of residuals or just stop the kmax at 3. For now, we will choose the latter.

b. Refinement towards Target Geometry

In this step, we want to refine our design by form finding our cablemesh to fit a structurally performative design target. This target design respects two main constraints: the maximum needle bed width of the knitting machine, and a deep corrugation for high structural performance - though keeping them high enough so the arches along the creases don't become too flat.

We will do so by tweaking the force densities for the knit and cable in ratio and magnitude. Make sure to not exceed 5 kN tensile force in the crease cables!

b1. Force Check

Check the maximum forces and also verify if the units make sense by comparing the sum of concrete weight with a hand check.

# ==============================================================================
# Force Check
# ==============================================================================

f_max = []
for edge in mesh.edges():
    f = mesh.edge_attribute(edge, 'f')
    f_max.append(abs(f))
f_max = max(f_max)
print('f_max', f_max)

pz_sum = []
for key in mesh.vertices():
    pz = mesh.vertex_attribute(key, 'pz')
    pz_sum.append(pz)
pz_sum = sum(pz_sum)
print('pz_sum', pz_sum)

With the current q=1.0 and qcable=10, we receive a fmax=0.81kN, which is pretty low, but our form found geometry is also pretty far from the target design:

Our hand check of the selfweight: SW = area(rough, without tributary area of anchors) * thickness * density = ~5 m² . 0.035 m . 24 kN/m³ = ca 4.2 kN is close enough to the result of 4 kN.

Always add the force densities you used to your Rhino layer name so that you can compare later the effects.

Now we can either increase the q in the cables or decrease the q in the knit or both. Let's first explore them separately to see the effect:

b2. Increase q_cable

If we keep the q=1 and set the qcable=220 to pull it all the way down to the target crease curve, we result in a very high force in the cables of 16.4kN. This is not reasonable, as it would require over-dimensioning of the cables and the supporting structure.

The forces can't be even reasonably visualised:

b3. Decrease q_knit

If we lower the qknit=0.19 and keep the qcable=10, the mesh fits the crease cable and the cable force is low with fmax=0.75kN. However, if the magnitude is this low in the knit then the knit sag down under the concrete weight:

b4. Decrease qknit and Increase qcable

So instead we want to decrease qknit a bit and increase qcable as much as that we are below 5kN cable force. So we chose qknit=0.4 and qcable=65 resulting in fmax= 4.9kN. In order to get to these values, we can iterate manually. This is where a best-fit optimisation algorithm could help us to define the correct force densities (though outside of the scope of this workshop).

Unfortunately, there is still more sag in the knit than in our target geometry. To avoid the sag in reality and also because the exact stiffness of the knit cannot be fully predicted and modelled, there are three possibilities to avoid this sag:

  1. increase pretension forces > not reasonable, strength limit for the knit.

  2. insert transverse stiffeners > that is why we prepare pockets in the knit.

  3. harden knit e.g with resin or thin cement layer before concrete application.

b5. Thin Coating

In the knit hardening case 3, we would form find the structure without the concrete weight, but only with the weight of 1cm cement, so basically we would have to assign our force densities to fit the target shape under this lower load then. Try it out!

We can see, that now the sag of the knit has disappeared successfully:

c. Assign Cable Attribute

For the subsequent steps of fabrication, we want to store the information in our datastructure which edges are to be materialised as a cable:

# ==============================================================================
# c. Side Cables Attributes > NEW
# ==============================================================================

# increase force densities to crease creases
mesh.edges_attribute('cable', True, keys=cables[1*factor]+cables[3*factor])

This way you can always find these cable edges like this:

# increase force densities to crease creases
cables = mesh.edges_where({'cable': True})

d. Export

Now that we are satisfied with the form finding result of our form-active structure we can serialise the mesh datastructure to a JSON file to make it available for its materialisation in the next step D. Fabrication.

Set the output path also the data folder:

# ==============================================================================
# Initialise > NEW
# ==============================================================================

HERE = os.path.dirname(__file__)
DATA = os.path.abspath(os.path.join(HERE, '..', 'data'))
...
FILE_O = os.path.join(DATA, 'cablenmesh_fofin_refined.json')
# ==============================================================================
# c. Export > NEW
# ==============================================================================

mesh.to_json(FILE_O)

Last updated