Posts by retug (8)

Time Histories to Response Spectrums

I have inherited an awesome project through the most unfortunate circumstances, the loss of a great engineer moving onto bigger and brighter pastures.

The project is going to be an ASCE 41 non-linear dynamic analysis and has had geotech engineers involved in picking out ground motion that represent similar ground motions that the faults near this building may produce.

Converting from time history to response spectrum can be done in ETABs, but post processing the data is kinda difficult, I can't seem to find a way to programmatically access the response spectrum curves that ETABs produces.

It's also never a bad day when you have to break out the Chopra Book, so I decided to try to code the process.

The Results

 

You can find the code to make plots like these  on my github:
The required data format is a .txt file that is separated with returns and tabs. I have heard not all geotechs provide their time history data in this manner, so if you want to use this, you may have to edit.

Starting into this, I thought this process involved using fourier transforms to transition from the time domain to the frequency domain, I clearly had forgotten my structural dynamics. Reading chapter 5 of Chopra and getting some guidance from fellow engineer Bryant, I was able to recreate the Newmark method outlined in the Chopra book. Adding a whole bunch of for loops later, some awesome plots popped out.

Comparing the BSE-2E plots (the big, rare earthquakes in ASCE 41) to the code generated response spectrum yielded a ~1.3 increase in peak accelerations at the typical plateau of the response spectrum (time histories were produced high accelerations). 

The BSE-1E time history plots were much closer to the code generated BSE-1E response spectrum.

Diaphragm Slicer - ETABs API

The Tool

One feature that I like to use in ETABs is the section cut tool, but it is quite cumbersome to utilize in practice:

Notice how you have to enter (4) valid points to define a section cut... a time consuming process. I love to use this tool to analyze my diaphragm forces, but you are only left with snapshots of your total diaphragm moment and shear. Defining lots of these section cuts along the length of a diaphragm is tedious.

This tool allows structural engineers to select their diaphragm in ETABs, define the slicing direction and define the number of sections to generate, plotting shear and moment at each section cut. It yields awesome plots like the following that you can use to determine diaphragm shear force and moments. The example shown below is that of a (3) sided diaphragm, 40ft long, with a 1kip/ft load applied to edge of the diaphragm.

Diaphragm Shear - Total Shear at shear wall is 40 kips

Diaphragm Moment

The shear graph above makes sense 1 kip/ft * 40ft = 40 kips to be resisted by singular shear wall in the line of the applied force; while on the other hand, the moment in the diaphragm is a little counter intuitive. This graph will make me revisit my other three sided diaphragm post at a later date.

The Goods

You can find the code to make this happen on my github as well as the sample ETABs model utilized to generate all of the plots. The code is written in python and utilizes the ETABs API to do the leg work.

A big thanks to CSI for making this possible in ETABs v19 and above. The new API of ETABs allows engineers to programmatically access any of the available tables in the interactive database. This bit of code makes the section cuts for the diaphragm:


def make_quad_etabs(name_sect,point):
    name = str(name_sect)
    final = []
    for i in range(4):
        if i == 0:
            test = [name, 'Quads', 'All', 'Analysis', 'Default', '', '', '', '0','0','0','','Top or Right or Positive3','1', '1', '1', str(point[0][0]), str(point[0][1]), str(point[0][2]), '1']
            final.append(test)
        elif i == 1:
            test = [name, '', '','', '', '', '', '', '','','','','','', '1', '2', str(point[1][0]), str(point[1][1]), str(point[1][2]), '']
            final.append(test)
        elif i == 2:
            test = [name, '', '','', '', '', '', '', '','','','','','', '1', '3', str(point[2][0]), str(point[2][1]), str(point[2][2]), '']
            final.append(test)
        elif i == 3:
            test = [name, '', '','', '', '', '', '', '','','','','','', '1', '4', str(point[3][0]), str(point[3][1]), str(point[3][2]), '']
            final.append(test)
    return final

etabs_data_sect = []
for i,(etabs_quad,sec_name) in enumerate(zip(global_quad,name)):
    etabs_data_sect.append(make_quad_etabs(sec_name, etabs_quad))

flat_etabs_data = []
for point in etabs_data_sect:
    temp = []
    for data in point:
        for sing_data in data:
            temp.append(sing_data)
    flat_etabs_data.append(temp)
mega_data = []
for point in flat_etabs_data:
    for ind_pnt in point:
        mega_data.append(ind_pnt)

TableKey = 'Section Cut Definitions'
TableVersion = 1
FieldsKeysIncluded = ['Name', 'Defined By', 'Group','Result Type', 'Result Location', 'Location X', 'Location Y', 'Location Z', 'Rotation About Z','Rotation About Y', 'Rotation About X', 'Axis Angle', 'Element Side', 'Number of Quads', 'Quad Number', 'Point Number', 'Quad X', 'Quad Y', 'Quad Z', 'GUID']
NumberRecords = len(flat_etabs_data)
     

y = SapModel.DatabaseTables.SetTableForEditingArray(TableKey, TableVersion, FieldsKeysIncluded, NumberRecords,mega_data)              

FillImport = True
z= SapModel.DatabaseTables.ApplyEditedTables(FillImport)
model_has_run = SapModel.Analyze.RunAnalysis()

To use the code, select your floor and change any of the input that I have noted with the #UI note in the python code. 

Typical user input includes:

  • Selecting the diaphragm you want to slice up, this is done in the ETABs model
  • Select the vector direction you want to your diaphragm to be sliced up, (1,1,0) for example is going up and to the right at a 45 degree angle, in the example below, (1,0,0) tells the program to create vertical slices along the length of the diaphragm, moving from left to right.
    • #UI
      vector = [1,0,0]
  • Define the number of slices you want to make
    • # UI Number of slices to make along the diahragm
      n_cuts = 100
  • Set the hieght, in feet, that your diaphragm exists at in ETABs
    • #UI
      height = 10 
  • Set the starting location of you diaphragm
    • #UI
      ref_pnt=[0,0,0]
  • Hit the run button on your favorite IDE

After hitting run, the program will generate the number of section cuts you told it to create and matplotlib is utilized to plot the results.

In my example code, I had the program generate 100 cuts, the 100th cut corresponds to the section cut 0099 noted below.

A nice plot is generated at the beginning as well so you can see how you are slicing your diaphragm to make sure you made your user input correctly. The red dots below correspond to where your diaphragm exists, while the blue lines corresponds to your section cuts.

Overall the tool works well and I look forward to using it on more complicated diaphragms. Test it out and let me know what you think!

Website Quality of Life Updates

The website has three updates

  1. New (hopefully easier to view) layout
  2. Slugified URLs
  3. Images that enlarge on click

1 - New (hopefully easier to view) layout


This one was by far the hardest for me to achieve, but hopefully makes the site easier to read on mobile. I have very little frontend development skills at this point and this work was 99% in reworking the html code for the website... and it was a bear for me.

The old website appeared like the image below, lots of wasted space for the stupid image to take up, it looked exceptionally bad on mobile where screen space is at a premium:


 

The new site has the appearance you are looking at, hopefully much better, no more wasted space:

The code changes to make this happen are subtle and I struggled with them. I still do not fully understand the <div> tag and how and why it works.


    <article class="media content-section">
      <div class="container">
        <div class="media-body">
          <div class="article-metadata">
            <img class="rounded article-img" style = "float:right" src= "{{ object.author.profile.image.url }}">
            <a class="mr-2" href="{% url 'user-posts' object.author.username %}">{{ object.author }}</a>
            <small class="text-muted">{{ object.date_posted|date:"F d, Y" }}</small>
            <h2 class="article-title">{{ object.title }}</h2>
            {% if object.author == user %}
              <div>
                <a class = "btn btn-secondary btn-sm mt-1 mb-1" href = "{{post.get_absolute_url}}/update">Update</a>
                <a class = "btn btn-danger btn-sm mt-1 mb-1" href = "{{post.get_absolute_url}}/delete">Delete</a>
              </div>
            {% endif %}    
        </div>

This post has made me identify another upgrade I need to make, a way to format code to make it look readable... more work for a later time.

2 -Slugified URLs


I thought this one was going to be difficult but it turned out to be much easier than I had anticipated. I had to make a change to my models.py file (essentially the database which allows this blog site to work) which always scares me because the last time I did this, I lost the whole website. This time it worked and I did not have to restore the website, horray!

The term slugify is apparently a django term for turning urls into human readable urls. For example, the previous url for this post would have been re-tug.com/post/7, the slugified post now incorporates the post title, retug.com/post/website-quality-of-life-updates/7. Without slugifying the title, the url would have been retug.com/post/website%20quality%20of%20life%20updates/7.

This apparently helps with search engine optimization and will make the urls a little more meaningful.

The code to make this happen:

 Models.py


class Post(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField(null=True, blank=True, unique=True)

    def get_absolute_url(self):
        #return reverse('post-detail', kwargs = {'pk': self.pk})
        return reverse('post-detail', kwargs = {'pk': self.pk, 'slug': self.slug})

Urls.py

urlpatterns = [
    path('post/<slug:slug>/<int:pk>', PostDetailView.as_view(), name='post-detail'),


In addition to these updates, a lot of the html hyperlinks had to be updated... one example:


.html

<div>
                <a class = "btn btn-secondary btn-sm mt-1 mb-1" href = "{{post.get_absolute_url}}/update">Update</a>


 

3 - Images that enlarge on click


The simplest of the three to solve. I use CKEditor for my image uploading and viewing and they have nice option to embed a link in an image. Try clicking on the image below and it should enlarge.

This solves my problem of tiny images not being readable.

Sloping K Series Joist

Since my last post on bending rebar in revit, I have been attempting to make a sloping K Series joist in revit that will dynamically update in the most awesome way possible.

K Series Joist in Action

Why is this awesome?!? In the gif above, all of those joists are the same family, but they have differing seat heights based on the vulcraft catalogue. In addition to that, as you can see in the gif, if the supporting element, be it a beam or a wall changes, the joist seat height will dynamically update based on the Vulcraft catalogue parameters.

Attempt 1

I began by attempting this in a very math intensive way... lots of converting from a local coordinate system to a global coordinate system. I made this lovely diagram to layout all the math involved (pictured is actually the math for a LH series joist seat that slopes)

Programming this into revit was doable, but getting revit to work with this much math often led to instabilities within the family. Some of the equations were quite fun to look at, only place where " red = green + grey".

I would often get error messages that the modeled geometry is slightly off axis when moving and stretching the model. After a couple of more attempts and feeling defeated, I made a post to the revit structure forum

Toan to the Rescue - Attempt 30 at this Point

I have to give a big shout out to Toan Nguyen on the revit structural forum for helping me out. See my post here. He was the one that came to the rescue and suggested rotating the local axis of the reference points to match the global coordinate system and forgo all the math that seemed to make revit struggle. With his help and family he posted I was able to tweak the adaptive component family to work.

The Family

The family consists of (4) differing families:

  1. The main rig
  2. A two point adaptive family that forms the bottom chord, the top chord and the joist seat
  3. A two point adaptive family that forms repeating webs of the truss
  4. A two point adaptive family that is plugged into item 3 that is the repeated web element.
    This family used the repeater tool button to array family 3. This is an awesome button that I have not used before and is extremely slick to make arrays quickly and very stable.

I found that this family is much more stable in the project environment by having all of these nested families in the main rig family (family 1). Attempting to directly sketch the chord profiles in element 1, the main rig, led to extremely odd behavior and odd twisting of the members. You can see below the odd twisting:

 

All and all, I was quite happy with the end product, it is stable and can be moved and dragged dynamically without breaking. Be sure to pick the low point first and the high point second with this family.

But what about the Vulcraft BIM in Addin?

I heard this on the structural revit forum as well. The short of it is that this family is dynamic, the joist seat height will update automatically based on the slope of the joist. The vulcraft addin will not do that. In addition, the family is great in that a K series joist needs a typical joist seat length of 4", the adaptive family will always start joist seat bearing on the supporting member and will show that you are lacking the required bearing length. The vulcraft addin always sets the 4" of bearing centered on the CL of support. The adaptive family can do this as well, but gives you more flexibility.

WHAT DO I TELL MY ARCHITECT?

I can hear you BIM managers now "This isn't a structural framing member family, what do I tell my architect?" 

In response to this use this as an opportunity to have a conversation with them. 

We are using a newer family type to model our joist members. It allows our joists to dynamic adapt to the supporting members as well as dynamically adjust truss heel heights based on the slope of your roof. This will allow us to be better coordinated with your model.

This opens up an opportunity to show that you exploring new ideas and new ways of achieving a better coordinated model. I would bet you your architect would at least be intrigued by what you were doing.

File Size

I was concerned about the potential file size of this family.

The adaptive component family clocks in at a whopping 900 kb.

The typical K series joist from vulcraft has a file size of 1352 kb.

The typical K series joist out of the box from revit has a file size of 588 kb.

This places the adaptive component family nicely in the middle.

In addition to this, I made a test project with 100 joists in each project and compared file size.

  • Project with 100 joists, adaptive family - 17808 kb
  • Project with 100 joists, Vulcraft - 17160 kb
  • Project 100 joists, Revit K series - 17196 kb

The adaptive family project is the largest, although not a huge difference, ~ 700 kb.

One downside is the family does take a bit of time to render into the project as you are prompted to pick the (2) adaptive family point locations, but it is usually no more than 2 seconds or so. I wish autodesk gave an option to only create an adaptive components after the points are picked, it might make the adaptive component family a little nicer.

Future Work

You could add onto this family to allow for top chord extensions, adjusting to be LH series joists, and what ever else you might want. I will be calling it quits though.

I am very excited to be done with revit families on this site for a bit, they are fun to mull over in my brain and get started on, but making them work is a real pain in the butt. Onto bigger and better stuff... Please let me know if you would like the family, I will send it your way. Comment below.

Revit Rebar Bender

How awesome would it be to have an easy to use, rebar drafting drawing tool in revit, getting minimum bend radii for any type of rebar? For some reason Autodesk has never released one of these and you would think it would be easy low hanging fruit for them to tackle. They have awesome tools to model actual rebar in concrete, why not make detail component to help us structural engineers out.

The Revit Family - An Adaptive Component


Pros

I set out to tackle this problem and unfortunately had to settle on the adaptive component family in revit. Revit uses the term family for classification of elements in revit. They have structural framing families, stair families, etc, the list goes on. The nice thing about adaptive component family is that it prompts the user for points to place and then creates a generic model in the revit file that you working.

Cons

The major drawback to this family type is that it creates an actual element in your revit model. If you used a lot of these elements your revit file would be cluttered with these annoying elements. Ideally this piece of rebar would only exist in a draft view and nothing would be created in the 3d world.

With this con being a major con, this project turned into more of a fun, can I make a dynamic rebar bending tool in revit. Let's dig into the family creation.

Family Creation

The family functions by having (3) given points, see blue points below:

From these (3) adaptive points, you can setup dimensions to report length 1-2, length 2-3, and length 3-1.

For some unknown reason, autodesk has not given us the ability for angle values to used as reporting parameters in families. For awhile, this made me feel like this family was never going to work, I need to know the internal angle created by points 1,2 and 3. After doing some research though, the good old law of cosines came to me. I knew the (3) lengths of the triangle and with that, I could calculate all the internal angles of the triangle.

I now had access to the internal angle created by the points.

After doing some trig and touching up on ACI minimum bend radii, I was able to calculate the location of the point to begin the bend radius of the rebar.

Big thanks to my friend and fellow engineer Robert for helping me with this geometry. He ended up doing a nice geometric proof, while I ended up making a whole bunch of triangles with differing internal angles, reporting the values and plotting the results. From the results, I was able to curve fit to match the results and we ended up with the same answer, but different look (works out to be the same after some more trig identities). His result - b = r *cot(theta/2)

my result - b = r * tan((theta-pi)/2).

With this value and some more revit family rigging, the family was created. One hard lesson I learned in this process is to always enable 3d snapping in the adaptive component family environment. Merely placing points on a reference plane is not enough to constrain the family.

Below you can see the family in action, it dynamically updates and changes, all while keeping minimum bend radius for the type of rebar you have selected.

Comments

This family only works if the rebar is drawn in a way that the points are picked in a clockwise manner. If revit allowed for more robust reporting paramters such as angles, or negative lengths, I could have made this family work with clockwise or counter-clockwise point picks. Hey autodesk, throw us a bone in the family creation realm, give us negative length parameters!

If you would like to try out the family, let me know and I will send it your way! 

Future Work

I have wanted to access Revit's API for awhile now and I think this would be a fun project to try to formalize and make better. There maybe a way to make an addin for revit that will allow for dynamically created rebar that could forgo some of the shortcomings noted above. I must admit though, C# scares me a bit, but I think it is time I start to learn.

1 2 Next Last

Our Sidebar

You can put any information here you'd like.

  • Latest Posts
  • Announcements
  • Calendars
  • etc