Dynamics Notes

Jan 17Jan 18 Jan 19Jan 20 Jan 21
Jan 24Jan 25 Jan 26Jan 27 Jan 28
Jan 31Feb 1 Feb 2Feb 3 Feb 4
Feb 7Feb 8 Feb 9Feb 10 Feb 11
Feb 14Feb 15 Feb 16Feb 17 Feb 18
Feb 21Feb 22 Feb 23Feb 24 Feb 25
Feb 28Mar 1 Mar 2Mar 3 Mar 4
Mar 7Mar 8Mar 9 Mar 10 Mar 11
Mar 14Mar 15 Mar 16Mar 17 Mar 18
Mar 21Mar 22 Mar 23Mar 24 Mar 25
Mar 28Mar 29 Mar 30Mar 31 Apr 1
...... ...... ...
Apr 18Apr 19 Apr 20Apr 21 Apr 22
Apr 25Apr 26 Apr 27Apr 28 Apr 29
May 2May 3 May 4May 5 May 6
...... ...... ...
Aug 22Aug 23 Aug 24 Aug 25 Aug 26
Aug 29Aug 30 Aug 30 Sep 1 Sep 2
Sep 5Sep 6 Sep 7 Sep 8 Sep 9
Sep 12Sep 13 Sep 14 Sep 15 Sep 16
Sep 19Sep 20 Sep 21 Sep 22 Sep 23
...... ...... ...
December
...... ...... ...
January 2006
...... ...... ...
February 2006
...... ...... ...
March 2006
July 2006
August 2006
September 2006
November 2006
January 2007

Thu Jan 20work in progress

Initial Information - Dynamics (the source is in /usr/src/local/teach/cbt/dynamics, I think - C and F77) is old and uses a grasp-based GUI. It is vulnerable to OS-upgrades. It's used on the DPO. Staff member in charge is Prof Wallace. John Prendergast (jp356@eng.cam.ac.uk) demonstrated the experiment. By using code developed during the rankine conversion I've managed to do the system diagrams, display values relating to mass, damper, spring, initial displacement and velocity, and DIY forces. Users can change these values and change the number of masses (which redraws the diagram and some of the other tables). The window where users click to input points is also done. The code can be run by doing
     cd ~tpl/matlab
     matlab
then in matlab typing
     dynamics

Time taken so far 4 hrs.

I'm managing to crash the original program... perhaps no surprise now I've read some of the comments - "QWORK1 mysteriously zeroed by here sometimes", etc.

Fri Jan 21

Converting the routines in calcs.f. NAG routines are used (but the ones I've looked at so far can be replaced by matlab routines. It looks as if some of the matrix indexing may begin at 0 rather than 1. The routines are in ~tpl/matlab/dynamics/calcs.

2 hours today.

Tue Jan 25

NAG routines Today I spent 4 hours sorting out some of the calls in calc1 and calc2 replacing calls to NAG and fortran routines by matlab operations.

Fri Jan 28

I've not checked the calc conversion properly yet, but I'd like to work on another part of the program today to create a testbed for calc. Using the original program with the standard model, 1 DOF I did the following I then displayed Displacement, Acceleration and Velocity graphs. All had x axes where Time ran from 0 to 10. I'll aim to recreate this.

I've created a directory for the tcalcs routines and have started converting them.

In that situation I think the original program does

 CALL  TIMCAL(IANAL,INPTS,
     &                NF,NDRFL,
     $                RMASS,
     $                X1DOT,DX,
     o                RTOL,T)

Time today: 3 hours

Mon Jan 31

system.f exploded into a system folder. The routines here check validity of user input. I've moved much of that to the callbacks. Note that the mass values are stored both as reals (RMASS) and strings (CMASS). Ditto for spring (RSPR, CSPR) and damper (RDMP, CDMP) values. I'll use new names for the reals - MASS, SPRING, and DAMPER - and remove the strings to make the code more readable. 2 hours

Tue Feb 1

2 hours more conversion.

Wed Feb 9

Spent 3 hours trying to glue the front-end and back-end together, fixing things as I went along. Found another NAG routine to replace - D02BBF
D02BBF
Withdrawn at Mark 18
Replaced by D02PCF and associated D02P routines

Old: CALL D02BBF(X,XEND,N,Y,TOL,IRELAB,FCN,OUTPUT,W,IFAIL)
New: CALL D02PVF(N,X,Y,XEND,TOL,THRES,2,'usualtask',.FALSE.,
    +            0.0e0,W,14*N,IFAIL)
     ... set XWANT ...
  10 CONTINUE
     CALL D02PCF(FCN,XWANT,X,Y,YP,YMAX,W,IFAIL)
     IF (XWANT.LT.XEND) THEN
       ... reset XWANT ...
       GO TO 10 
     ENDIF
NAG's example code can be replicated like this using matlab.
function D02BBF
TSTART=0;
YSTART(1)=0;
YSTART(2)=1;
TEND=2*pi;
NPTS=8;
TINC=(TEND-TSTART)/NPTS;
T=TSTART:TINC:TEND
[t,y]=ode45(@F,T,YSTART)

function YP=F(T,Y)
YP(1)=Y(2);
YP(2)=-Y(1);
YP=YP';

Thu Feb 10

Another 2 hours. The equivalent of the original's calc now runs without syntax errors in the time domain, which is a start (a small one; I've not checked the output!). The output of the original is in the form of graphs All these use the 9000-element COORD array, but this COMMON array holds info on several features. The tcalcs:ISTART routine works out where to look.
      FUNCTION ISTART(NPARAM,NSELC,NPPCOR)
C     NPARAM     The number of the coordinate info required.
C                Numbers refer to coordinates as follows
C                for stage 1
C                                          1 - X1
C                                          2 - X2
C                                          3 - X3
C                                          4 - X1 velocity
C                                          5 - X2 velocity
C                                          6 - X3 velocity
C                                          7 - X1 acceleration
C                                          8 - X2 acceleration
C                                          9 - X3 acceleration
C     NSELC (I)  I=1,9 in stage 1
C                Contains information about whether info about
C                a given coordinate is required.
C                I=1,9 refers to coordinates as in NPARAM
C                NSELC(I) = 1 data reqd
C                NSELC(I) = 0 data not reqd
C    NUMPTS      Number of data points for each coordinate
For example, the acceleration values for the first mass will be in the 7th block where each block is NPPCOR=NUMPTS long. I'll check the COORD array in the matlab program.

This program will be harder to convert than previous ones because the fortran maps less cleanly onto matlab.

Tue Feb 15

More routines converted and function calls traced. 3 hours.

Thu Feb 17

More fixes. Integration parameter control added. 3 hours.

For the first time a non-null-interval calculation runs, giving this output for y in numint.

   10.0000   10.0000
   10.1225    9.5023
   10.2387    9.0141
   10.3489    8.5351
   10.4532    8.0654
   10.8890    5.8521
   11.1927    3.8567
   11.3777    2.0682
   11.4566    0.4754
   11.3683   -1.9354
   11.0379   -3.8139
   10.5226   -5.2265
    9.8711   -6.2336
    9.1236   -6.8939
    8.3182   -7.2619
    7.4852   -7.3892
    6.6494   -7.3211
    5.6304   -7.0220
    4.6663   -6.5516
    3.7768   -5.9697
    2.9751   -5.3232
    2.2093   -4.5890
    1.5566   -3.8620
    1.0125   -3.1698
    0.5715   -2.5318
    0.2637   -2.0275
    0.0204   -1.5778
   -0.1662   -1.1839
   -0.3032   -0.8455
   -0.3833   -0.6091
   -0.4390   -0.4062
   -0.4742   -0.2346
   -0.4920   -0.0918
   -0.4951    0.0372
   -0.4839    0.1368
   -0.4621    0.2109
   -0.4325    0.2630
   -0.4018    0.2934
   -0.3685    0.3114
   -0.3337    0.3191
   -0.2986    0.3184
   -0.2544    0.3078
   -0.2123    0.2892
   -0.1732    0.2653
   -0.1031    0.2062
   -0.0734    0.1742
   -0.0486    0.1436
   -0.0284    0.1151
   -0.0142    0.0926
   -0.0030    0.0724
    0.0056    0.0547
    0.0121    0.0394
    0.0159    0.0286
    0.0186    0.0194
    0.0203    0.0115
    0.0212    0.0050
    0.0214   -0.0009
    0.0210   -0.0054
    0.0201   -0.0088
    0.0189   -0.0111
    0.0176   -0.0125
    0.0162   -0.0134
    0.0147   -0.0138
    0.0132   -0.0138
    0.0113   -0.0134
    0.0095   -0.0127
    0.0078   -0.0117
    0.0062   -0.0105
    0.0047   -0.0091
    0.0033   -0.0077
    0.0022   -0.0064
    0.0013   -0.0051
    0.0007   -0.0041
    0.0002   -0.0032
   -0.0002   -0.0025
   -0.0005   -0.0018
   -0.0007   -0.0013
   -0.0008   -0.0009
   -0.0009   -0.0005
   -0.0009   -0.0002
   -0.0009   -0.0000
   -0.0009    0.0001
   -0.0009    0.0003
   -0.0009    0.0004
Plotted, these give
2graphs
which look a little the expected Displacement and Velocity graphs (though that may be a coincidence). The program currently looks like this
dynamics
The results should all end up in COORD but in this simple case only elements 100, 201, and 302 are non-zero (their values are 10.0000 , 10.1225, and -40.2449 which look like the first value for each of Displacement, Velocity and Acceleration). So the next thing to do is to look at the calls to out (3 of them?) to see if more values can be put into COORD. Total time spent so far: 28 hours.

Wed Feb 23

3 more hours done.

More values now put into COORD, though Acceleration has only 2 values associated with it. setfun changed so that more than 1 mass can be used without the program crashing. The following show the results for the 1st mass in the three situations
1 Mass2 Masses3 Masses
At least the graphs aren't all the same. There needs to be a way to show the behaviour of the other masses. The original program lets the user selectively display them on the one graph.

I've had a look at the Frequency options. The suboptions are

Mon Feb 28

2 more hours done. The number of output (y) values per graph was NPPCUR which was always 101 (T/DELATA + 1) but matlab's ODE function returns 85 or 169 values (I don't know why). When there are 169 values, some values in the COORD array for one graph are overwritten by the values for another graph. I've given each graph a space of 200 values in COORD and have changed the output routine so that 3, 6, or 9 graphs are printed, depending on the number of masses. Here's the output for 3 masses.
dynamics
Any resemblance to reality is coincidental. I'm not even sure that I've correctly entitled the graphs.

Thu Mar 3

Another 9 routines added to deal with Frequency-related parameters. 2 hours.

Wed Mar 9

I've decided to use matlab14 - its panels make the front-end prettier. The "Recalculate" button now outputs the system parameters in a figure (separate from the graphics for now). FFOR(1,1) is true if X0 is attached. FFOR(i,1) is true if force i (1:3) is attached. This is a matrix which started at 0 in the fortran version. I've now checked it. The code in time.f to change the attachments needs converting.

I'm unsure what the 1st 4 args to timcal do. I think they're something to do with setting one's own x,y points.

1 hour.

Thur Mar 10

For the single-mass situation I've now printed the system parameters in the same figure as the graphs. This is what the final version needs. The bad news is that the window can't be printed out in a recognizable fashion. I've posted to the matlab newsgroup for help.

Well, I've procrastinated all I can. Time to make the single-mass situation produce the correct graphs. Guess I now have to understand how the program's supposed to work so I can fix the Acceleration graph. It would be useful to be able to get some numbers out of the old version rather than just graphs. Alas, the old code fails with

/usr/ccs/bin/ld: Unsatisfied symbols:
   f01acf (code)
So I've changed the fortran code a little. /users0/cstaff/tpl/SRC/dynamics3 has a new working version of the fortran code. I'll change this so that it prints out the values used to produce the graphs in the single-mass situation.

2 hours.

Fri Mar 11

I'm having trouble making the fortran version print values out, so meanwhile I'll clarify what the Recalculate button does which as a call-tree looks like this
calltimcal -- timcal -- eom1
                     \_ vibby -- numint -- ode45 -- FCN -- setfun
                                        \_ out   ---------/ 
                                        \_ graphs
For the 2-mass and 3-mass situations I've printed into Figure 3 graphs produced by the data directly from ode45. They're much more believable than the data I'm currently plotting into figure 2. I've also generated the data for the acceleration graph directly from the velocity data (rather than call setfun). Here's the latest 3-mass output.

dynamics
3 hours.

Wed Mar 16

The original fortran code may have been in more of a mess than we thought. Compiling it with a modern compiler reveals several coding problems that may account for the crashes we get when we try to minimally modify the code to produce more output. The problem's being investigated. Meanwhile I'll check the user-input callbacks and tidy up the front-end. I've contacted Mathworks about the printing bug. They say it's fixed in the release that's been shipped (matlab 14 SP2).

I've tried changing masses, etc using the interface (e.g.

). The graphs match the original program so far, except when I set c2=1000 in the 2nd example - the original program said that the system is too stiff.

Time for a summary

  • The code can be run by doing
         cd ~tpl/matlab
         matlab14 -r dynamics
    
    Just click on the "Recalculate (time)" button to get some default graphs. The 3-mass graphs are displayed in 2 formats.
  • The time-domain stuff (mass, dampers, springs, initial displacements and velocities) can be modified, calculations run and graphs produced. The graphs look viable.
  • I'll next try to get the frequency-domain stuff in a similar state to the time-domain stuff
  • Total time including today: 43 hours.
2 hours

Thur Mar 17

The frequency calculation starts with a call to hrmcal which in turn calls eom2, dohcal and calc2 (the latter being where the real work is done - it uses several other routines). Results go into the HARMS array (which is used like the COORD array in the time-domain according to the doc). In the fortran code, HARMS is (0:500,3,2) and XARRAY begins at 0 too - I'll change the zero-based indexing. I've added a freq subdirectory for the routines that were in freq.f

In hrmcal I don't know what MENOP, MPTS or NPTS are for. Should be ints, so I'll guess MENOP=1; MPTS=0; NPTS=0;

In calc1 I need to determine which of the many calculated values are needed later.

2 hours

Wed Mar 23

Clicking on the "Recalculate (freq)" button now runs without error messages through the code. It doesn't produce worthwhile output but at least the densely mathematical code is legal now. I'd guess that the freqency code is in the same state as the time code was about a month ago.

If LFP is false then much of the code in calc2 isn't executed. Looking in the fortran code I can't see where LFP is ever set to true

Some matters arising from reading the Instructions for the program "DYNAMICS" documentation

4 hours.

Tue Mar 29

When "Recalculate (time)" is used with a single mass, there's a "Points" button so that users can click on a graph. The x coord of the point clicked on will be used to decide which displacement and velocity values to display.

My ILAB2 variable in calc2.m is an NxN whereas in the original it's a 1xN (where N in the original might be the number of masses). The contents are correct though - with 1 mass it contains 1 number (namely 1, which in STAGE 1 denotes X1). In calc2.m, WORK1 "contains the negative inverse mass matrix" according to comments. Currently, with a single mass of 10, it's

1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
which can't be right. Maybe this matrix should be of size num_of_masses-by-num_of_masses.

1 hour.

Wed Mar 30

Skeletal load/save session facility added. Currently "*.sess" filenames are used and only MASS, STRING and DAMPER are saved/loaded.

Forcing points can now be removed as well as added.

1 hour.

Fri Apr 1

Save/load facility for sets of forcing points added ("*.force" filenames). Typing "newdynamics" at the "traditional" teaching system's command line now starts my experimental version.

Here's an updated summary

  • The code can be run by typing
         newdynamics
    
    from the unix command line. Click on the "Recalculate (time)" button to get some default graphs. The "Forcing" button should also work ok.
  • The time-domain stuff (mass, dampers, springs, initial displacements and velocities) can be modified, calculations run and graphs produced. The graphs look viable. The 1-mass graphs are shown with a panel that displays settings, and a "Point" button so that you can find the coordinate of a particular point on the graphs. The 3-mass graphs are displayed in 2 formats.
  • I'll next try to get the frequency-domain stuff in a similar state to the time-domain stuff
  • Total time including today: 52 hours.
1 hour.

Thu Apr 21

I'm trying "Matlab Version 7.0.4.352 (R14) Service Pack 2" on tw700 (linux). This is the newest version of matlab, and the machine is the type we're mostly likely to use in future. "panels" still fail to print correctly, so I've mailed Mathworks again (later they confirmed that there's a bug). The dynamics code works no worse than before. Another bug or 2 fixed. The "Recalculate (freq)" button doesn't cause a crash if there's only 1 mass, but it does otherwise.

In calc2.m QWORK1 is (IDIM2*IDIM2*4) which is used as if it were QWORK1(IDIM2*2, IDIM2*2). I'm having trouble with the line

   qcopy2( QWORK1, I4, IDIM2, QWORK7, I4, I4, 1, 1, 1, IDIM3 + 1, IDIM2, I4 );
because given the dimensions of QWORK1 and QWORK7, the values that IDIM3, IDIM2, and I4 have mean that the indices will go off the end of the array.

1 hour.

Tue Apr 26

3 hours of tracking bugs down. I had some of the qcopy2 lines wrong, and I tend to use zeros(n) (which produces an n-by-n matrix) when I mean zeros(n,1). The problem remains that QWORK1(IDIM2*2, IDIM2*2) and QWORK(IDIM2, IDIM2) are multiplied together as if QWORK1 was (IDIM2*2, IDIM2). So I've added a HACK to calc2 which chops QWORK1 down to the expected size, multiplies, then restores the chopped off part.

Tue Apr 27

2 hours of tracking bugs down. I'd wrongly set MPTS to 0 (it should be the 'Num of points' on the Frequency panel). Fixing this has led to some code being run for the first time. calc2's call to qmult4 assumes that QWORK1 is a vector! I think there must be QWORK1-related bugs in the original code (which has comments about QWORK1's contents "mysteriously" changing).

Tue Apr 28

Here's how QWORK1 is used in the original Fortran's calcs.f. (where IDIM2=NDOFS (i.e. 1,2 or 3), IDIM3=IDIM2, and I4=IDIM3 + IDIM2)
QWORK1(IDIM2 *IDIM2* 4 ) ("QWORK1( IDIM2 * 4 )" is commented out)
CALL QCOPY2(QWORK1, I4, IDIM2, ...) implying QWORK1(I4, IDIM2)
CALL QMULT2(QWORK3, QWORK1, WORK1, I4, IDIM3, IDIM3) implying QWORK1(I4, IDIM3)
CALL QMULT(QWORK1, QWORK3, QFORC1, I4, IDIM3, 1) implying QWORK1(I4,1)
CALL QMULT4(QHARMS, QWORK4, QWORK1, I5, I4, I, MPTS) implying QWORK1(I4)
CALL QMULT(QWORK1, QWORK3, QFORC1, I4, IDIM3, 1) implying QWORK1(I4,1)
CALL QMULT2(QWORK3, QWORK1, WORK3, I4, IDIM3, NF) implying QWORK1(I4, IDIM3)
CALL QMULT(QWORK1, QWORK3, QFORCE, I4, NF, 1) implying QWORK1(I4,1)
CALL QMULT5(QWORK3, QWORK1, I5, I4) implying QWORK1(I4)
Perhaps this is legal in Fortran, as long as QWORK1 has enough bytes. Perhaps only parts of QWORK1 are involved in some calculations. Maybe this is what's meant by
C     M Hardy uses variable dimensioning of multi- dimensional arrays
C     These must be dimensioned at max and passed in empty through a
C     'buffer layer' where no use is made of them
I've been assuming that the array dimensions being passed down as parameters always refered to the whole array (and so in matlab weren't needed, because matlab "knows" the size of each array).

I've changed qmult4 and qmult5 so that they're closer (to the letter rather than the spirit) to the original fortran code.

2 hours

Tue May 3

Well, the code doesn't crash when running frequency-based calculations however many masses there are now, but I'm sure I'm not doing the right thing - the program draws graphs full of null values. Maybe this is a part of the program where I need to go back to basics and forget the Fortran code, but I'll need a teaching person's help.

I think I'll try to get the fortran program running by removing the graphics. It would help a lot to be able to compare, stage by stage, the fortran and matlab calculations. So in /users0/cstaff/tpl/SRC/dynamics3nographics now are reduced versions of 7 of the fortran files, which I hope will suffice to run the frequency-domain stuff. It compiles with f90 and (unlike the original code) copes with added PRINT statements. I haven't yet worked out how to set all the required values without a user-interface, but I'm progressing.

I've just tried the animation option in the original program. Either it's moving too fast or it's not working. I wonder whether it's still being used? And I'd better try a little animation experiment in matlab to see how jerky/flickery it is. Judge for yourself by running this, which uses (I think) the fastest way to animate

axis([0 10 0 10])
xcoords=[1 2 2 1];
ycoords=[1 1 2 2];
p=patch(xcoords, ycoords,'r')
increment=.02
for i=1:300
  xcoords=xcoords+increment;
  ycoords=ycoords+increment;
  set(p,'XData',xcoords,'YData',ycoords);
  drawnow
end
for i=1:300
  xcoords=xcoords-increment;
  set(p,'XData',xcoords)
  drawnow
end
4 hours

Wed May 4

My non-graphics version runs (I used the "+check=all" compile flag, which helped). However, all the values in HARMS are 0, -1000.0 or 1.00000E+09. I presume I've failed to set all the variable correctly

3 hours

Fri Aug 26

Discussions suggest that there's not enough time to bring the new version into use for the forthcoming term (John's going to be away for a week or so). Frequency domain analysis is needed, and that's the least-completed part of the new version. Guess I should start looking at that part of the code again, but even if I fix it this week there won't be time to test, rewrite the handout etc. Maybe next year...

Thu Sep 1

There's renewed interest in getting this new version to work for next term. The handout's been rewritten with this in mind, and a design for the screen has been suggested. I assume that the options on this design are all the ones needed - it's going to be a cut-down version. Yesterday and today I've produced a new screen (for 1DOF).

The white panels are easier to program than the loose boxes of the "model parameters", but math characters can't be used in them, so they're not used for the model parameters. The screen needs a little tidying up, but I need to concentrate on functionality for a while.

The model parameter callbacks, "Run Time Analysis" and "Save session" buttons now work much as their analogues did before, so do the frequency analysis input boxes. The "Load session" button needs a little more work.

Fri Sep 2

Flipping between 1DOF and 2DOFs works - diagrams and input fields change.

A final decision on whether to use this new version needs to be made around the end of September - the IB Lab runs for the first time on Monday 10 October 2005. We do have the fallback of the existing version ...

Mon Sep 5

The load/save session buttons work for the mass/spring/damper variables. I spent the rest of the time debugging the frequency-domain code.

Thu Sep 15

I've found one bug - I'd wrongly translated calc1's NAG F01ACF call into matlab. However, the resulting graphs are no better.

Tue Sep 20

I've been pursuing various options

December

I now have the equations governing the motion for the 2-body situation. I simplified these so that I could try them out in a single-body example, but I haven't managed to get results that match those of the original program even for the time-domain option.

January 2006

By reading the dynamics handout and some online notes about spring-dashpots, matlab and ODEs I've managed to get a little further. Some of the time-domain curves are the right kind of shape now. I think I have a problem understanding the notation - the CUED and non-CUED formulae differ regarding use of constants, it seems to me. My single-body code is in /users0/cstaff/tpl/matlab/singleode.m and the 2-body code is in /users0/cstaff/tpl/matlab/doubleode.m

February 2006

I've made some progress on using matlab in 1-DOF situations, and can reproduce some results from the Dynamics databook. See Matlab and 1B dynamics for CUED students

March 2006

Mar 23: contact with knowledge domain specialist re-established. Here's a progress report
                         Dynamics

First some background ... Dynamics is an old fortran program. I started 
converting it to matlab line by line but could never get the freq domain 
stuff working. So I started rewriting the code from first principles. 
This approach will produce a much smaller, faster program that's much 
easier to maintain, but it means that need to understand the code.
I'm aiming to produce a matlab script that given the inputs 
that the old program uses, produces graphs and numerical output. I could
then plug the code into the already-written front-end.

I need help with getting the matlab scripts to produce the output that the 
fortran code does. Ideally of course I'd like the computation code written
for me, but any help on improving/extending would I've done so far would
be useful. Some of the code I've written may confuse more than it helps ...


Now a progress report, with code ... I started first by trying to reproduce 
the graphs that the old program produces.

singleode - this tries to reproduce the 1DOF time/displacement of the
            old program. The shape of the graph is roughly right, but 
            there's less damping than there should be, I think

doubleode - this tries to reproduce some graphs (time and freq) in the 
            2DOF situation. The time ones are more believable than the 
            freq ones.

I then tried to reproduce graph that are in the databook. I had more success
there, but I don't know how to extend these to deal with >1 DOF.

springs  - "Step Response of a linear second-order system
            initially at rest" (p.6 of the data book)

springs2 - "Harmonic response of a linear second-order system -
            Magnitude" (top of p.9 of the data book)

springs3 - "Harmonic response of a linear second-order system -
            Phase" (bottom of p.9 of the data book)

springstest - an attempt to produce the diagram at the top of p.9 of the 
            data book "empirically" (without using the formala on p.8 for 
            the max response
            
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function singleode
% m1u'' + c1u' + (k1)u = F0sin(wt)

% Using
% u ->u1; u'-> u2

% we get

% u2' = - c1*u2 - ((k1)/m1)*u1  + (F0/m1)*sin(w*t)
% u2(0)=0;
% u2'(0)=1; % a=F/m

m1=10;
c1=10; % damping
k1=10; % stiffness
w=5;   % ???
F0=10; % ???



initial = [10; 10];

[T,Y] = ode23(@yprime2, [0, 10], initial);
figure
plot(T,Y);
%yy=fft(Y)
%size(real(yy))
%figure
%plot(real(yy))

function dy = yprime2(t,y)
w=10; % omega (natural frequency?)

%wn=k/n
wn = sqrt(10/10);
lambda=10;
lambdacrit=2*10*wn;
damping=lambda/lambdacrit;
wd=wn/sqrt(1-2*damping^2);

% This is from WWW notes
% dy= [y(2); -10*y(2)-(wd^2)*y(1)+sin(t)];

% This is from CUED
%  dy= [y(2); -10*y(2)- y(1)+sin(wd*t)];
 dy= [y(2); -y(2)- y(1)+sin(wd*t)];


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function doubleode


% m1u1'' + c1u1' + (k1+k2)u1 = F0sin(wt)
% m2u2'' + c2u2' - k1u1 = 0


% Using
% u1 ->u1plain; u1'-> u1dash
% u2 ->u2plain; u2'-> u2dash

% we get

% u2' = - c1*u2 - ((k1)/m1)*u1  + (F0/m1)*sin(w*t)
% u2(0)=0;
% u2'(0)=1; % a=F/m

% u2dash' = -c2*u2dash/m2 + u1plain*k1/m2

m1=10;
c1=10; % damping
k1=10; % stiffness
w=5;   % ???
F0=10; % ???



initial = [10; 10; 10; 10];

[T,Y] = ode23(@yprime2, [0, 10], initial);
figure
plot(T,Y);
yy=fft(Y)
size(real(yy))
figure
plot(real(yy))

function dy = yprime2(t,y)
w=10; % omega (natural frequency?)

%wn=k/n
wn = sqrt(10/10);
lambda=10;
lambdacrit=2*10*wn;
damping=lambda/lambdacrit;
wd=wn/sqrt(1-2*damping^2);

dy= [y(2); -10*y(2)-(wd^2)*y(1)+sin(t); y(4) ; -10*y(4)/10 + y(1)*10/10];



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function springs
m1=10;
c1=10; % damping
k1=10; % stiffness
f=10; % initial force
x=f/k1;
dampingratio=c1/(2*sqrt(k1*m1));
% Without damping, the natural frequency is w
w=sqrt(k1/m1);

% Y=x/(2*dampingratio*sqrt(1-dampingratio*dampingratio))
natfreq=sqrt(k1/m1)
wdamped=natfreq * sqrt(1-dampingratio*dampingratio)

initial = [0; 0];

for para=[0, 0.1, 0.25, 0.5, 1, 1.5]
     [T,Y] = ode23(@yprime2, [0, 20], initial,[],x,w,para);
     plot(T,Y(:,1)/x);
     hold on
end

function dy = yprime2(t,y,x,w,dampingratio)
dy= [y(2); - 2*dampingratio*y(2)*w - y(1)*w*w + x*w*w];


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function springs2
m1=10;
k1=10; % stiffness
natfreq=sqrt(k1/m1);
clf

freqrange=0.01:0.1:2;

for dampingratio=[0.1 0.2 0.3 0.5 1 1.5]
     if dampingratio < 1/sqrt(2) ;
       wmax= natfreq*sqrt(1-2*dampingratio^2);
       responsemax=1/(2*dampingratio*sqrt(1-dampingratio^2));
       disp(sprintf('max response for dampingratio=%.3f',dampingratio))
       disp(sprintf(' is %.3f at freq=%.3f', responsemax, wmax))
       plot(wmax,responsemax,'or');
     end
    element=1;
     for freq=freqrange
          y(element)=realform(natfreq, dampingratio, freq);
          element=element+1;
     end
     plot(freqrange,y)
     hold on
end

function y=realform(omegan, dampingratio, omega) 
omegaratio=omega/omegan;
y= 1/sqrt((1-omegaratio^2)^2 + (2*dampingratio*omegaratio)^2);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function springs3
m1=10;
k1=10; % stiffness
natfreq=sqrt(k1/m1);
clf

freqrange=0.01:0.1:2;

for dampingratio=[0.1 0.2 0.3 0.5 1 1.5] 
element=1;
for freq=freqrange
     y2(element)=tanphi(natfreq, dampingratio, freq);
     element=element+1;
end
y3=atan(y2)*180/pi;

y3(y3>0) = y3(y3>0)-180;
plot(freqrange/natfreq,y3)
hold on
end

function y=tanphi(omegan, dampingratio, omega) 
     omegaratio=omega/omegan;
     y= (-2*dampingratio*omegaratio)/(1-omegaratio^2);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function springstest

m1=10;
c1=10; % damping
k1=10; % stiffness
f=10;

dampingratio=c1/(2*sqrt(k1*m1)); % not used
x=f/k1;
w=sqrt(k1/m1);


Y=x/(2*dampingratio*sqrt(1-dampingratio*dampingratio));
natfreq=sqrt(k1/m1);
wdamped=natfreq * sqrt(1-dampingratio*dampingratio);

% sprintf('critical damping rate = %d',2*m1*natfreq)
% sprintf('corresponding dampingratio = %d', 2*m1*natfreq/(2*sqrt(k1*m1)))

trange=0:0.1:18;
freqrange=0.01:0.1:2;
initial = [0; 0];

figure(1)
clf
for dampingratio=[0.1 0.2 0.3 0.5 1 1.5]
  if dampingratio < 1/sqrt(2) ;
     wmax= w*sqrt(1-2*dampingratio^2);
     responsemax=1/(2*dampingratio*sqrt(1-dampingratio^2));

     disp(sprintf('max response for dampingratio=%.3f is %.3f at freq=%.3f',dampingratio, responsemax, wmax))
  end
  
  element=1;
  for freq=freqrange
     [T,Y] = ode23(@yprime2, trange, initial,[],x,w,dampingratio, freq);
     MAXY(element)=max(Y(:,1));
     element=element+1;
  end
  plot(freqrange, MAXY)
  hold on
end


figure(2)
clf
for dampingratio=[0.1 0.2 0.3 0.5 1 1.5]
element=1;
for freq=freqrange
      y(element)=realform(natfreq, dampingratio, freq)
      element=element+1;
end
 plot(freqrange,y)
 hold on
end

  

function dy = yprime2(t,y,x,w,dampingratio, freq)
 dy= [y(2);  - 2*dampingratio*y(2)*w - y(1)*w*w + x*cos(freq*t)];
 
 
 function y=realform(omegan, dampingratio, omega) 
 omegaratio=omega/omegan;
 y= 1/sqrt((1-omegaratio^2)^2 + (2*dampingratio*omegaratio)^2);

July 2006

I've just found some code which could be very useful. It was on matlab's site - contributed software - at http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=3797&objectType=file. I don't know how viable the calculations are, but if they're ok, we might consider not only using the maths part but using the whole program. If you do
  cd ~tpl/mechmodelling/canonical
  matlab -r mdof
you can try the front end. The maths stuff can be used without the front-end by doing something like
mass = 0.3*[1,0,0;0,1,0;0,0,1];
damp = 0.1*[2,-1,0;-1,2,-1;0,-1,2];
stiff = 10000*[2,-1,0;-1,2,-1;0,-1,2]; Wmax = 500; % (rad/sec)
N_Sample = 512;
Noise_Factor = 0;
out = 1; %response point
inp = 1; %input point

[H,w,par] = Hcanonical(mass,damp,stiff,Wmax,N_Sample,Noise_Factor,out,inp)

August 2006


Updated January 2007
Tim Love