Step 1 - Generative Design Framework
I opted to investigate 3 design decisions related to structural engineering as this is the field that my background is in.
- Design Decision 1: Steel vs. Concrete vs. Timber
- Design Variables
- Bay size
- Materials cost
- Can account for region in country - eg. mass timber might be cheaper in the PNW, areas closer to concrete plant might get cheaper concrete, etc.
- Evaluators
- Total building cost
- Total embodied carbon
- Structural performance (deflection)
- Most Important Tradeoffs to Consider
- Budget
- Architectural constraints (long spans, wide bays, etc)
- Sustainability or carbon goals
- Design Decision 2: Steel moment frame vs. Steel braced frame
- Design Variables
- Lateral system type
- Brace/frame location within building
- Bays used for lateral system
- Evaluators
- Drift performance
- Steel tonnage for lateral system
- Brace cost
- Fabrication and installation cost
- Most Important Tradeoffs to Consider
- Structural efficiency vs. architectural freedom
- Initial cost vs. operational flexibility
- Stiffness vs. ductility → period effects
- Design Decision 3: Ease of construction vs. Optimized member conditions
- Design Variables
- How many unique members are allowed
- Bay Size (both X and Y)
- # Floors
- Evaluators
- Total steel tonnage
- Number of unique pieces
- Total floor area
- Total embodied carbon
- Most Important Tradeoffs to Consider
- Material savings vs. fabrication premium
- Structural efficiency vs. constructibility risk
- Design effort vs. construction savings
Step 2 - Generative Design Study
I opted to study Design Decision 3: Ease of construction vs. Optimized member conditions. The reason I chose this decision is because this is a common issue that structural designers face; given an unlimited amount of time and unlimited budget, most designers could make a highly optimized building that could both potentially be cheaper (construction-wise) but also perform better. Unfortunately, this is usually not the case, and an emphasis is usually placed on speed, both from the design and construction side. As such, it is common to use a singular design condition for a range of conditions across a building, even though the cases may not apply perfectly.
As described above, my design variables were the number of unique members permitted in the design, bay size in x and y (both in feet), and the number of stories in the building. I chose these for a few reasons. Controlling the number of unique members permitted in the design allows a crucial decision to be made - a low number of unique members aids in construction and fabrication cost, but may result in oversized members, low efficiency, and higher structural steel cost by ton. Conversely, a high number of unique members allows for more optimized conditions and potential steel savings, but will raise construction time, increase potential for complications during fabrication and erection, and more. Adding bay size as a design variable allowed me to explore the effects across different lengths - short (10ft) bay lengths have different requirements than long (40ft) ones. And adding control in both directions of my idealized rectangular building allows me to explore the effect of different proportions. Finally, controlling the number of stories allowed me to utilize different load values to see the effect that this had on the response of each parameter.
My evaluators/objectives were pretty self explanatory. Total steel tonnage is something we want to minimize to minimize material cost. # of unique pieces is something likely want to minimize to reduce construction and fabrication cost. Total floor area is something we want to maximize in general, as developers and owners want the most bang for their buck. And total embodied carbon is something we want to minimize.
(I am only taking 3 units but I chose to do 4 design variables and 4 evaluators for extra credit).
I opted to use Grasshopper for this step as opposed to using Dynamo. I felt like I better understood the Grasshopper environment and felt like it would be better suited for the type of analysis I wanted to do. Plus, I found some YouTube tutorials that provided similar examples to those provided in class for Dynamo. As such, I used the WallaceI engine for Rhino to do my optimization. This engine takes in a series of design variables (”genes”) and optimizes a series of evaluators (”objectives”).
To start a defined sliders for the base size in both the X and Y directions and then used this to calculate the floor plate size in both the X and Y direction. I also defined sliders for the number of floors, the number of unique designs that are permitted as well as various sliders for the loading information. I first used the geometry information about the floor plate dimensions to create a base, rectangular footprint, then I divided it into beams based on the number of bases that I previously specified. I then used some Python logic to parse these into two separate lists that contained a list with all of the X beams in a list with all of the Y beams. I wanted to use Python to make this workflow easier so I watched some tutorials on how to use Py3 nodes. I then calculated the lengths of all of these beams, which are important for calculating loading and weight information. To calculate the loading, I used all of the earlier described sliders, as well as some simple formulation, namely, the formula wl^2/8, to get the moment demand on each beam based on the loading information specified earlier. Then, I use the formula for required section modulus, which is simply the moment demand divided by the allowable bending stress for a member. I specified this to be 33 KSI. This then got me a list of required section moduli, which I was then able to feed into another Python note to run some more simple logic to select an adequate member size for each member. And then essentially repeated this analysis across all of the floors.
Once this was done, I obtained all of my outputs for my objectives. Most are self explanatory based on the node logic, but I wanted to elaborate on the total CO2. If I simply used a multiplier times the total tonnage, the results would not be interesting as tonnage and CO2 would basically just be proxies for each other. So instead, I added a bay size factor, which penalizes larger bays. This is because larger bays require larger members which are more carbon intensive to produce and transport. This makes it so the CO2 calculation is not linear.
The end goal of all this was defeat all of these calculations into the WallaceI node, which handled all of the optimization, and the results of this can be seen below. I ran the analysis with a generation size of 50 and a generation count of 50 for a population size of 2500. The search space was 1.7e4 large.
Step 3 - Generative Design Study Results
Here are the results of my Parallel Coordinate Plot. The objectives are: F01 = Total Steel Tonnage, F02 = Total Tons CO2, F03 = Total # Unique Members, F04 = Total Floor Area (GSF). The blue lines are optimized solutions; the red are other alternatives. A few key observations can be made.
For one, F01 and F02 are very closely correlated. There is some variation as expected due to the bay sizing, but this effect is somewhat minimal. In future iterations, perhaps I could use a more complex formula for estimating embodied carbon to get more interesting results. But we can overall see that the blue lines tend to cluster at the bottom of FO1 and FO2, confirming the algorithm successfully found low tonnage, low carbon solutions.
We can see that FO3 crosses against FO1/FO2, because larger floor area correlates with higher tonnage, which is the central structural tradeoff. We see that solutions that minimize embodied carbon tend to have smaller floor areas, and solutions that maximize floor area tend to have higher embodied carbon (ie. Bigger building = more steel). This may seem obvious, but it is an important conclusion regardless.
We can also see that F04 usually arrives at a clustered set of solutions; solutions generally hover around a few values regardless of other variables. Again, this could be due to the artificial constraints I put on the range of how many sections are allowed, but this could be changed in the future. The main conclusion here is that standardization largely takes care of itself. Most solutions naturally converge toward a small number of unique sections regardless of bay size or floor count, so for a regular orthogonal grid building, aggressive section standardization doesn't cost much in tonnage.
Here is the objective space. It is interesting to look at to see the progression of the solutions that were explored.
The key takeaways that I (or a practicing engineer in general) can gather from these graphs are primarily to do with the approach to estimating tradeoffs. This shows that these decisions can be made in a quantifiable manner, and not just in a qualitative way. An engineer can look at this data and see that artificially constraining the number of unique conditions they have (potentially in the name of constructibility or fabrication simplicity) does not save a lot in terms of steel used (as I write this, I realize that it could be interesting to incorporate construction costs in some way in the future, but that could be an area for expansion). This can also help them evaluate the effect of different design decisions on things like total embodied carbon (ie. artificially shortening spans might not have as much of an effect on CO2 as they thought). Overall, the main goal here is to provide some objective basis on which to make decisions on how a building can be designed.
I also opted to display colors of the beams based on the weight (red = heavy, green = light). Here is an example of how it displayed for Floor 3, although this is not a particularly interesting example since the beams are all similar weight. Here is a video showing how it looks during the search. You can see that the building is changing dimensions, bay size, member weight, and more, quite rapidly.
My full Grasshopper workflow is below. The full image is a bit hard to read since my workflow was rather expansive (probably unnecessary).