Energy dissipation in damped vibrations

In the previous post in this series (which was four months ago—time flies), we looked at the free vibrations of damped single-degree-of-freedom (SDOF) systems, systems that can be modeled as a spring-mass-dashpot like this:

Spring-mass-damper

The position of the mass, [u], can be expressed as a function of time, [t], through the formula

[u = A e^{-\zeta \omega_n t} \cos (\omega_d t - \phi)]

where [\omega_n] is the natural frequency of the undamped system, [\omega_d] is the frequency of the damped system, and [\zeta] is the damping ratio. They’re related to the physical properties of the system through these equations:

[\omega_n = \sqrt{\frac{k}{m}}] [\zeta = \frac{c}{2 m \omega_n}] [\omega_d = \sqrt{1 - \zeta^2} \omega_n]

The other two variables, [A] and [\phi], are determined through the initial position and velocity of the mass. As discussed before, we can start our clock at any time we like; we can, without any loss of generality, set [t = 0] at a point that will lead to [\phi = 0]. This simplifies the solution to

[u = A e^{-\zeta \omega_n t} \cos \omega_d t]

Taking the derivative of [u] gives us the velocity:

[\dot u = -A \omega_n e^{-\zeta \omega_n t} \left( \zeta \cos\omega_d t + \sqrt{1 - \zeta^2} \sin \omega_d t \right)]

where we’re using Newton’s dot notation for derivatives with respect to time.

In an earlier post, we calculated the total mechanical energy of an undamped system and showed how it remains constant over time. Let’s look at the mechanical energy of our damped system. The potential energy is

[U = \frac{1}{2} k u^2 = \frac{1}{2} k A^2 \left[ e^{-\zeta \omega_n t} \cos \omega_d t \right]^2]

and the kinetic energy is

[T = \frac{1}{2} m \dot u^2 = \frac{1}{2} m \omega_n^2 A^2 \left[ e^{-\zeta \omega_n t} \left( \zeta \cos\omega_d t + \sqrt{1 - \zeta^2} \sin \omega_d t \right) \right]^2]

Because [k = m \omega_n^2], the kinetic energy can also be written as

[T = \frac{1}{2} k A^2 \left[ e^{-\zeta \omega_n t} \left( \zeta \cos\omega_d t + \sqrt{1 - \zeta^2} \sin \omega_d t \right) \right]^2]

The total mechanical energy is the sum of these two, [U + T]. Instead of giving it as a long formula, let’s plot it. We’ll have to choose a particular damping ratio, so let’s go with [\zeta = 0.10].

Damped vibration energy balance

Note how the total mechanical energy decreases with time. Where is it going? It’s being dissipated as heat as the fluid in the dashpot gets pushed back and forth by the piston. The total energy curve is wavy because the activity of the dashpot changes with time. When the mass is near the extreme left and right ends of its travel (when [\omega_n t \approx 0, \pi, 2\pi, …]), its velocity is nearly zero and the dashpot isn’t doing much. The total energy is nearly constant during these times. On the other hand, when the mass is moving quickly (when [\omega_n t \approx \pi/2, 3\pi/2, 5\pi/2, …]), the dashpot is at its peak of activity and the total energy drops rapidly.


At the end of the previous post, I questioned the usefulness of analyzing a spring-mass-dashpot system:

Mechanical systems have springy parts and they have mass, but very few have actual dashpots. What good is all this math if it doesn’t represent actual equipment? We’ll talk about the kinds of real-world things we model as dashpots next time.

We model systems using dashpots because that leads to differential equations that we can solve. What we model as dashpots are things that dissipate mechanical energy from the system. For example:

Sliding friction is very common—almost unavoidable. It occurs at joints where parts are supposed to move relative to one another, like hinged joints; but it also occurs at joints where the part aren’t supposed to move relative to one another, like bolted joints. Surfaces held together by bolts are supposed to remain fixed, but they slide anyway—a little bit, back and forth—as the machine or structure vibrates. This slippage causes the parts to heat up, and it’s that transformation of mechanical energy into heat that causes the total mechanical energy of the system to decrease

Materials deformed beyond their elastic limit cannot spring back to their original state, leading to a loss of mechanical energy. Energy is also consumed when cracks form in a material because it takes energy to create the new surfaces on either side of a crack. This is a very common mechanism for energy dissipation in concrete structures.

Both plastic deformation and cracking are forms of hysteresis, but hysteresis also occurs anytime the loading and unloading curves of a material don’t match up.

Hysteresis

Image from Wikipedia.

The energy lost during a cycle of loading and unloading is represented by the area between the two curves. Hysteresis can occur in metals even when they’re loaded below the elastic limit, especially when the loading is rapid.

None of these dissipation mechanisms match the dashpot mathematically—that is, the energy loss wouldn’t follow perfectly the wavy curve shown in the energy plot. But we can choose a value of [\zeta] that makes the total energy loss the same, and that’s often good enough. Engineering is not science. The goal of engineering is not to understand our systems perfectly (which we could never achieve); the goal is to understand them well enough to build devices that work.


It’s just a silly phase I’m going through

I saw Guardians of the Galaxy this past weekend and really enjoyed it. There were a few clunky spots, and I have no idea why people are praising Vin Diesel’s voicing of Groot,1 but it was a fun movie. The movie was not, however, about my Guardians of the Galaxy.

Here are my Guardians, straight outta 1975:

Guardians of the Galaxy

Steve Gerber wrote the Guardians stories during my comics collecting days. I was a big Gerber fan back then, and read everything of his I could get my hands on. I have no idea what Marvel plans to do with Howard the Duck, but (Spoiler Alert!) I assume his appearance at the end of the movie was a nod to Gerber’s work on the old Guardians. Or maybe it was just a recognition that a racoon wasn’t the first anthropomorphic animal hero.

One of the old Guardians did make it into the movie. See the blue-skinned guy with the red fin coming out of his head? That’s Yondu, he of the whistle-controlled yaka arrows. Same blue skin but with a bar on top of his head instead of a fin. And the comic book Yondu didn’t have Michael Rooker’s menacing southern accent, probably because he was from Centauri IV.

The token Earthling, Vance Astro2 (in the blue and white outfit), like Peter Quill, left Earth in 1988, but he wasn’t abducted. Astro volunteered. He was put in suspended animation, bundled into a rocket, and shot to Alpha Centauri in a poorly thought-out attempt to save the human race. In the 1988 of 1975, we were all dying of cancer because we’d destroyed the ozone layer.3 How was one man alone supposed to start a colony on another world? Beats the hell out of me.

Marvel didn’t even think to give Astro an awesome mixtape, because predicting rockets to Alpha Centauri was easier than predicting the Walkman. You’d think they could’ve at least given him an 8-track player.


  1. Bradley Cooper’s Rocket Racoon, on the other hand, deserves every bit of acclaim it’s received. 

  2. Yes, Vance Astro. 

  3. As I recall, Marvel used ozone depletion to explain Killraven’s future Earth, too. 


Better work diary actions

In the update at the beginning of this post that shouldn’t have been written, I show how the Launch Center Pro work diary actions should have been built, but I’d like to have a freestanding post describing the actions that I can refer to later. This will be that (somewhat redundant) post.

The LCP actions I use for common entries in my work diary leverage the Drafts action I first described in this post.

Drafts work diary action

This action takes the current time and the contents of the active draft and appends it to a Dropbox file named for the current day. It differs slightly from the original version of the action in that I now use a 24-hour clock for the timestamps.

The diary file that results looks something like this:

07:22
Leaving home

08:05
At site

09:13
Leaving site

09:58
At office

Because it’s in Dropbox, I can refer to it from any device.

My most common entries have to do with travel, so I created a set of Launch Center Pro actions to make those entries with a single tap/swipe. They’re in an LCP group entitled Diary:

LCP work diary group

Each action is defined in pretty much the same way. Here’s the one for Leaving Home:

Launch Center Pro diary action

The URL is this:

drafts://x-callback-url/create?text=Leaving%20home&action=Work%20diary&x-success=launch%3A

The only difference between the various diary entry actions is the text= part. The x-success portion at the end causes my screen to return to LCP when the action is done.

I switched to these simple actions from my messy Pythonista scripts on the suggestion of David Cross. Had I waited a little longer, I could’ve just copied an action written by Greg Pierce instead of writing them from scratch. Still, it was heartening to see that what I came up with was basically the same as Greg’s example—that meant I’d finally done it right.

I do think, though, that I can improve the actions a bit. Not by editing the URLs, but by customizing the icons. Because they’re all currently using the default icon for Drafts actions, they all look the same except for their titles, which are too small for me if I’m not wearing my reading glasses. I’m going to look around for public domain icons that will make them more distinct.

Update 8/25/14
A few readers have asked about using geofencing to automatically make entries for leaving and arriving at home and work. I thought about doing that as I was making the actions but decided against it. My work diary isn’t meant to be a tool for tracking my life. As popular as that sort of thing is nowadays, I have no interest in it. I use the diary to account for time I can bill my clients and nothing else. You might say that automatically adding entries I can’t bill for doesn’t hurt, but I don’t agree. With my current system, every entry is relevant when I’m generating a bill after a trip; with an automatic system, the great majority of the entries would be irrelevant, and I would waste time sifting through them.


Work diary revisited

Update 8/21/14
You can pretty much ignore this post unless you want to explore the psychology of how someone can get caught in one way of thinking and miss something as plain as the nose on his face.

My first instinct is to write scripts, and I knew I could write Pythonista scripts to do what I wanted. But I didn’t want to have to launch Pythonista to run the scripts, because that would involve a lot of scrolling and would cost more time than they saved. I knew, though, that I could create home screen shortcuts that would run each script with a single tap. You’ll note that there’s no thought of using Launch Center Pro at this point. Although I bought LCP a while ago, I never got into using it.

After making the home screen shortcuts, I found that running a script that way would leave me in Pythonista. Because there’s no URL scheme for Springboard, I couldn’t script in a way to go back to the home screen where the icons lived. I really didn’t want to have to press the home button to get out of Pythonista.

That was when I hit upon using Launch Center Pro, and I was happy because everything worked. But I should’ve realized that LCP, combined with the Work diary action I’d already built in Drafts, could do what I wanted with very simple actions like this:

drafts://x-callback-url/create?text=Leaving%20home&action=Work%20diary&x-success=launch%3A

Not only is this far, far simpler than the Pythonista scripts described below, it runs faster and is more flexible. Later today, I’ll write a much shorter post about using LCP actions like this to create common diary entries.

In the meantime, read what’s below only if you want to look at a case study in complicated foolishness.

The work diary I outlined in this post last year continues to serve me well, but I’ve been looking for more efficient ways to make common entries. After a few attempts that weren’t as helpful as I’d hoped, I think I’ve hit on a solution using a combination of Pythonista and Launch Center Pro.

To review, my work diary is a set of text files stored in a Dropbox folder named “Diary.” Each file is named according to the date, like 2014-08-20.txt, and contains timestamped entries that look like this:

22:06
Started 200 degree test

22:45
Ended 200 degree test

22:54
Started 300 degree test

These entries are created in Drafts. I type or dictate the text of what I’m doing into a blank draft, invoke the Work diary action,

Drafts diary entry

and a new timestamped entry is added to the day file. The Drafts action that does the work is defined this way,

Drafts work diary action

where the file name is

[[date|%Y-%m-%d]]

and the template for the entry is

[[date|%H:%M]]
[[draft]]

This is a slight change from what I started with last year. Back then, the timestamp used a 12-hour clock with an AM/PM marker. I’ve since changed to a 24-hour clock to make it easier to figure out how much time I spent on each activity.

I don’t have the patience or the discipline to track all my time this way, but I have found this system especially useful on days when I travel. On these days, the entries tend to take on a few common forms:

07:22
Leaving home

08:05
At site

09:13
Leaving site

09:58
At office

Because I usually make these entries in my car with the Bluetooth connection on, the ambient noise and car speakerphone make Siri dictation less than perfect. To avoid dictation errors, I set up some shortcuts using the builtin iOS Settings. I soon learned that while shortcuts work fine when they’re part of a longer batch of text, they leave you hanging when the shortcut is the only thing you type.

Shortcut expansion

The little autocorrect bubble just sits there until you either type something else or tap somewhere in the text field.

TextExpander snippets are better for standalone entries because they expand immediately, with no need for additional typing or tapping. So I made a series of snippets for the entries I found myself making again and again.

lhz  -> Leaving home
lwz  -> Leaving work
lsz  -> Leaving site
lhoz -> Leaving hotel
ahz  -> At home
awz  -> At work
asz  -> At site
ahoz -> At hotel

I used these snippets for months, and they never gave me any trouble. Still, it seemed as though the sequence of

  1. Open Drafts
  2. Type abbreviation
  3. Tap action button
  4. Tap Work diary action

was too much for something as routinized as entering canned text like this, especially when my thumbs mistyped the abbreviation and I had to back up and retype. Autocorrect never wanted to turn “adz” into “asz” for me.

So I started thinking about ways to automate these entries further, and Pythonista seemed like my best bet.1 What I ended up with was a series of eight scripts—one for each of the common entries—that I run from Launch Center Pro.

Launch Center Pro shortcuts

A single tap on one of these icons switches me to Pythonista, runs the appropriate script to create a diary entry, and returns to Launch Center Pro. Counting the tap to start LCP itself, that’s two taps to make a diary entry, each on a large target with no chance for mistyping.

The scripts that do the work rely on the Dropbox module that comes with Pythonista. This module is not quite as easy to use as the one described in the Dropbox Python SDK documentation, and unfortunately the Pythonista documentation for the module contains some mistakes, but with a little trial and error I was able to get a set of scripts that worked.

The first step was to go to Dropbox’s App Console and “create an app.” This generated an app key and app secret that I could use to give my scripts access to my Dropbox files. I did that using this script, which is a slight modification of the authorization script in the Pythonista Dropbox documentation:

python:
 1:  from dropbox import client, rest, session
 2:  import clipboard
 3:  
 4:  # Get your app key and secret from the Dropbox developer website
 5:  APP_KEY = 'aaaaaaaaaaaaaaa'
 6:  APP_SECRET = 'bbbbbbbbbbbbbb'
 7:  
 8:  # ACCESS_TYPE should be 'dropbox' or 'app_folder' as configured for your app
 9:  ACCESS_TYPE = 'dropbox'
10:  
11:  sess = session.DropboxSession(APP_KEY, APP_SECRET, ACCESS_TYPE)
12:  
13:  request_token = sess.obtain_request_token()
14:  
15:  url = sess.build_authorize_url(request_token)
16:  
17:  # Make the user sign in and authorize this token
18:  clipboard.set(url)
19:  print "url:", url
20:  print "This URL is on the clipboard. Please visit the website and press the 'Allow' button, then hit 'Enter' here."
21:  raw_input()
22:  
23:  
24:  access_token = sess.obtain_access_token(request_token)
25:  
26:  print 'key:', access_token.key
27:  print 'secret:', access_token.secret
28:  print
29:  client = client.DropboxClient(sess)
30:  print "linked account:", client.account_info()

The APP_KEY and APP_SECRET in Lines 5 and 6 are the strings I got from the Dropbox App Console. Running this script within Pythonista puts a Dropbox authorization URL on the clipboard and then pauses at Line 21. At this point, I went to Safari, pasted the URL, and authorized my app in much the same way I authorized Tweetbot, Storify, Pinboard, and other apps. Returning to Pythonista and the paused script, I tapped the Return key to allow the script to finish. Lines 26 and 27 printed out the access key and secret that are needed in the next script. With that, this script has done its job and is no longer needed.

By the way, the description of obtain_access_token is one of the places where the Pythonista Dropbox module documentation is wrong. It says the return value is a tuple of the key and the secret when it’s actually a single object with key and secret attributes. That took some time to figure out.

To avoid repeating a big chunk of code eight times, I wrote a module, diary.py, with a function that can be called from all the other scripts:

python:
 1:  import dropbox
 2:  from datetime import datetime
 3:  
 4:  def add_entry(entry):
 5:    "Add a timestamped entry to today's diary file."
 6:  
 7:    # Initialize Dropbox.
 8:    app_key = 'aaaaaaaaaaaaaaa'
 9:    app_secret = 'bbbbbbbbbbbbbbb'
10:    access_key = 'ccccccccccccccc'
11:    access_secret = 'ddddddddddddddd'
12:    sess = dropbox.session.DropboxSession(app_key, app_secret, 'dropbox')
13:    sess.set_token(access_key, access_secret)
14:    client = dropbox.client.DropboxClient(sess)
15:  
16:    # Dates, times, and files.
17:    folder = '/Elements/Diary/'
18:    current = datetime.today()
19:    filename = current.strftime(folder +'%Y-%m-%d.txt')
20:    timestamp = current.strftime('%H:%M')
21:    dfiles = [ f['path'] for f in client.metadata(folder, list=True)['contents'] ]
22:  
23:    # Get the contents of today's diary file if it exists.
24:    if filename in dfiles:
25:      f = client.get_file(filename)
26:      log = f.read()
27:      f.close()
28:    else:
29:      log = ''
30:  
31:    # Add a new entry and save. Creates a new file if it doesn't exist.
32:    log += '%s\n%s\n\n' % (timestamp, entry)
33:    client.put_file(filename, log, overwrite=True)
34:  
35:  if __name__ == '__main__':
36:    add_entry('hello')

The function defined in this module, add_entry, does exactly what you’d expect from its name. Its single argument, entry, is what comes after the timestamp in a diary entry.

Lines 8–13 use the keys and secrets generated earlier to gain access to my Dropbox files. Line 14 initializes a Dropbox client process that handles the reading and writing of the files.

Lines 17–20 define the name and location of the diary file and define the timestamp. You’ll notice that my Diary folder is a subdirectory of a folder named “Elements.” Old-timers might remember that when the Elements app was the hot iOS text editor, it forced you to put all your files into a namesake Dropbox folder. I’ve linked every iOS text editor since then—none of which have been so restrictive—to that same folder.

Line 21 gets the names of all the files in the Diary folder. Line 24 then checks to see if there’s a file in there for today. If there is, it reads all the text from that file and puts it in a variable called log. If there’s no preexisting file for today, log is initialized to the empty string.

Line 31 adds the timestamp and entry to the end of log, and Line 32 writes log out to today’s file. This creates the file if it doesn’t already exist and overwrites the existing file if it does.

With diary.py doing all the hard work, the individual scripts for each common entry are easy. Here’s the one named Leave Home.py:

python:
1:  import diary
2:  import sound
3:  import webbrowser
4:  
5:  diary.add_entry('Leaving home')
6:  sound.play_effect('Coin_2')
7:  webbrowser.open('launch://')

Line 5 writes the entry, Line 6 plays a sound so I know when it’s done, and Line 7 takes me back to Launch Center Pro. The other seven scripts are exactly the same except for the argument to add_entry.

Which leaves just the definitions for the LCP actions. Here’s one:

Leave Home LCP action

The URL is

pythonista://Leave%20Home?action=run

I suppose I shouldn’t have left the space in the script name—that’s the reason for the %20. The .py extension isn’t needed in the URL because Pythonista knows to add it.

Apart from the quick, one-handed entry, the best thing about this solution is that it’ll be easy to extend if I start using other common entries in the future.


  1. I think Editorial would work, too, but I’m not as familiar with it.