FunicularFINDR š
Overview: Fun with Funiculars š
This program allows the user to apply point loads, line loads, and area loads to a UV grid and finds the resulting moment distributions using Python scripts nested in the dynamo file and custom nodes. The moment distributions from each load are superimposed and are used to create the funicular shell structure.
Video Demo
Workspace Screenshots
# Load the Python Standard and DesignScript Libraries
import sys
import clr
import importlib
clr.AddReference('ProtoGeometry')
sys.path.append(r'C:\Users\carri\Documents')
sys.path.append(r'C:\Users\carri\AppData\Local\python-3.8.10-embed-amd64\Lib\site-packages')
import numpy as np
from Autodesk.DesignScript.Geometry import *
import Moment_Calculations
importlib.reload(Moment_Calculations)
# The inputs to this node will be stored as a list in the IN variables.
uv_grid = IN[0]
xline_ld = IN[1]
sf = IN[2]
# Get information about x line load
f_xl = xline_ld[0]
locstart_xl = xline_ld[1]
locend_xl = xline_ld[2]
# Calculate moments from x line load
# Find start and end points of the load
appy_xlstart = locstart_xl.Y - sf
appy_xlend = locend_xl.Y - sf
appx_xl = locend_xl.X - sf
# Run point load moment finding function
mx_xl = Moment_Calculations.LineLoad(sf, len(uv_grid) * sf, appy_xlstart + sf, appy_xlend + sf, f_xl, sf)
mx_xl = np.array(mx_xl)
# initialize numpy zeros array for point load moments
m_xl = np.zeros((6, 6))
# assign moment values in array accordingly
m_xl[int(appx_xl / sf), :] = mx_xl
# for each y-coordinate
for i in range(1, len(uv_grid[0])):
# scale the moment distribution in the x direction by the factor from the m-dist in the y-dir
slope_a = 1 / int(appx_xl)
slope_b = 1 / (len(uv_grid) * sf - int(appx_xl) - sf)
if i*sf <= appx_xl:
m_xl[i, :] = mx_xl * i * slope_a * sf
else:
m_xl[i, :] = mx_xl - mx_xl * (i * sf - int(appx_xl)) * slope_b
# Assign your output to the OUT variable.
OUT = m_xl
def PointLoad(mmax, start, maxapp, end, sf):
length = int((end - start + sf) / sf)
m_p = [0] * length
slope_a = mmax / (maxapp - start) * sf
print(slope_a)
slope_b = mmax / (maxapp - end) * sf
print(slope_b)
for i in range(length):
if i*sf < maxapp - sf:
m_p[i] = slope_a * i
elif i*sf == maxapp - sf:
m_p[i] = mmax
else:
m_p[i] = mmax + slope_b * (i - maxapp/sf + 1)
return m_p
def LineLoad(start, end, app_start, app_end, force, sf):
length = int((end - start + sf) / sf)
m_xl = [0] * length
a = app_start - start
b = app_end - app_start
c = end - app_end
R1 = (force * b) / (2 * (length-1) * sf) * (2*c + b)
R2 = (force * b) / (2 * (length-1) * sf) * (2*a + b)
for i in range(length):
if i*sf < a:
m_xl[i] = R1 * i * sf
elif a <= i*sf < a+b:
m_xl[i] = R1 * i * sf - force / 2 * (i * sf - a) ** 2
else:
m_xl[i] = R2 * (length - i - 1) * sf
return m_xl
Sample Use: Structural Reactions with a Column & 2 Walls
Overview
As an example, a generative study was performed on a pavilion roof structure with a uniformly distributed self-weight supported by a column & 2 bearing walls. The self-weight provides a uniformly distributed area load downwards on the structure whereas the reaction from the column and the 2 bearing walls provide a point load & 2 line loads acting upwards, respectively.
Loading Assumptions & Application
It was assumed that there was a linear relationship in the force distribution between the column and the walls based on these two cases and on the total length of the 2 walls. Self-weight was applied as a typical area load using the coding group above. The approximate loading on the structures was calculated in the code group below.
Calculation of Total Panel Areas
Results of Generative Study
Overall, a generative study was performed using the end points of the wall line loads as input parameters and the area of the discretized shell structure as the evaluation variable. Ultimately, 16 options were explored with 4 different X-Value and Y-Value end points. The minimum area was found when the Y-Value end was 4 and the X-Value end was 2.
Next Steps
Here are the next steps in developing this tool:
- Parameterize the discretization of the moment distributions: this code should already be available within the dynamo script, but it needs to be debugged. The code currently runs successfully when the moment distribution is discretized into 6 points, but it should theoretically work with any number of points. The error should be somewhere in the Python scripts.
- Toggle for framing accommodation. If this structure were to be a framed structure (e.g. with wood or steel framing the panel edges) instead of a concrete shell, they would add line loads to the structure. Ideally, the code would have a button (or a Boolean True/False node) that would allow the user to select if they wanted to account for framing loads or not. This has not been implemented because Iām not sure how to account for the number framing elements yet.
- Loads on the boundary of the structure: the code currently only accounts for loads that are applied in the middle of the structure. Because of this, if a load is applied to a boundary, the moment distributions will be wrong. This was done for ease of coding for now, but can be updated.
- Design: the code currently focuses on the loading and finding a funicular structure purely based on the moment diagram. The next step would be to take that loading and to be able to design say a post-tensioned concrete shell or size framing to withstand the loads and moments in the configurations given.