MATLAB: Intro and infrastructure

Outline

  • Infrastructure

    • Tips about the MATLAB program

    • Tips about MATLAB code

    • Some is relevant to later lectures, some is just nice to know

  • Time ODEs

    • Mechanical systems as a base

    • Hand-rolled Euler, ode45, linear state-space implementations

    • Simulink basics & block diagram equivalents

  • Systems modeling

    • More mechanical system examples

    • Simscape libraries: Mechanical, Electrical, Thermal

    • Fluids and Pneumatic (if I can figure them out)

  • Composing system models

Basic tips

Function documentation

  • Quick help from help <function>

    • Arguments, inputs, outputs

  • Detailed help from doc <function>

    • Same as the webpage by default

    • Offline access by going to Home/Preferences/Help/Documentation Location

Up arrow

  • Use the up arrow in the MATLAB command window to execute the thing you did
    last

  • Start typing, and that behavior will be filtered

PATH and startup.m

  • %userprofile%/Documents/MATLAB is on your "MATLAB PATH"

    • A "PATH", in any context, is just "where your program globally looks for functions"

    • MATLAB's built-in functions and libraries are on MATLAB's PATH

    • Any function you put to this kind of directory is call-able no matter where you are

  • %userprofile%/Documents/MATLAB/startup.m runs whenever MATLAB starts

    • Configure parts of MATLAB not visibile in Preferences

    • Example: Dock figure window by default

    set(groot, "DefaultFigureWindowStyle", "docked");
    • Example: Default figure font size of 14

    set(groot, "DefaultAxesFontSize", 14);

Value output

  • Probably you use disp to print values

    • Fine if you're just printing a number

    • disp(['The value of pi is ', num2str(pi, 2), 'to two decimal places'])

  • Instead we can use fprintf(fmt, ...)

    • fprintf("The value of pi is %.2f to two decimal places\\n", pi)

  • Most common to use

    • %d for integers

    • %f for decimals

    • %e for exponental

    • %s for strings

Vectorization

Operating on entire arrays "at once" is better than using a for loop.

  • Many functions in MATLAB are vectorized

    • Implicitly applying to entire arrays (sin, sum, exp, etc.)

    • Mathematically equivalent to doing a for-loop in MATLAB and doing elements
      one-at-a-time

    • There's still a for-loop under the hood, but it's in a lower-level
      (faster) language

    • Can be stupidly faster in some cases ~ orders of magnitude is a reasonable
      expectation

  • When each element of the array doesn't depend on the others, vectorization is
    possible

  • You can't vectorize numerical simulation (except by explicitly solving the
    system)

1D indexing

  • Let vector v be a row or column vector (doesn't matter)

  • v(n) takes the n-th element of v

  • v(end) gets the last element of v

v = randi(20, 1, 7) v(n) v(end) v(4:7) v([1, 4:7])

2D indexing

  • Ordered (row, col)

  • row and col are as flexible as they were before

    • end to mean the end

    • a:b to create a continuous slice

    • [a b c d] to create a non-continuous slice

Linear & logical indexing

  • To be perfectly consistent, the 1D examples should have used 1, n or n, 1
    to specify "the first column"

    • Lack of this is not a special case of indexing

  • What if you just use one index anyway?

    • A(4) seems to work

    • Can you go off the end? Sure! A(15) gives a result

    • The single index treats the matrix as a big stack of columns

  • find returns linear indices

    • fives = find(A == 5) is all of the linear inidces where A is 5

    • A(fives) = 0 makes all of those zero (gets rid of all of the fives)

  • Equivalently, make an array of the same dimensions of logical (true/false)
    values

    • fives = (A == 5)

    • A(fives) = 0

    • Even more briefly A(A == 5) = 0

  • Don't try to write up a list of linear indices or ones and zeros yourself; you should get from find, sub2ind, or a logical operation

  • A(:) turns anything into a column (useful if you want to garauntee
    orientation)

Broadcast dimensions

  • Two kinds of math: Matrix operations and element-wise

    • * is matrix multiplication, .* is element-by-element

    • Same for /, ^ and their element-wise counterparts ./, .^

  • When you try to use element-wise math on mismatched arrays, what happens?

    • If one of the dimensions is 1, it gets copied

    • (N, 1) .* (1, M) -> (N, M)

    • Scalar multiplication is a special case---think of the scalar as getting
      copied

Operating along a dimension

  • sum and similar functions say that their second argument makes the funciton
    operate "along" a dimension

    • Good mnemonic is that this "along" variable is the dimension removed by
      the operation

    • Example: sum(A, 2) removes 2, which is the column, "squashing" the array
      down.

Performance claims

  • As far as you know, when you write code, MATLAB just runs it

  • Actually, MATLAB's interpreter attempts to do optimization (JIT compilation)

  • Actually actually, the operating system is scheduling thousands of threads

  • Actually (last time for now), the CPU is trying to branch predict

  • Don't say it's faster without good benchmarking!

    • Significant difference

    • Long-enough runtime

    • Persistant across attempts

Debugging

  • Type "keyboard" or click the red dot next to the line

  • Inspect variables to make sure they turn out how you expect

  • Test calculations

Example: Fourier Series

  • The sine series for a square wave has given coefficients $b_{n}$.
    Compute the sine series $f(t)$ to 100 terms between -2 and 2 seconds using a

    • double for-loop (solve to f_t_a)

    • single for-loop---sine evaluated for all time (solve to f_t_b)

    • single vectorized operation (solve to f_t_c)

$$ b_{n} = \frac{4}{\pi n}\quad \text{for} \quad n = 1,3,5,\cdots $$
$$ f(t) = \sum_{n} b_{n} \sin(n \pi t) $$

Solution: Double for-loop

Solution: Single for-loop

Solution: No for-loop

Timing

  • tic before and toc after displays the time

  • profile on before profile viewer after breaks down the time in detail

Example: Curve stitching

  • A machine error introduces jumps into a dataset

  • All element-to-element jumps greater than 0.5 are erroneous

  • Remove these jumps

    • Need to remove their effect on all subsequent elements

Hint
diff returns the difference between consecutive elements,
cumsum takes the cumulative sum of its argument

Solution: Curve stitching

Data structures

Structures

  • You can create a variable that has variables inside it

  • struct.a creates a variable struct that has a field a

Why timeseries?

  • When you output Simulink data, you'll have the option to use an array or
    structure

  • In interpreting physical signals, you want two things to be true

    • Data never makes sense in isolation from time

    • Data and time cannot have the same operations done to them

  • The Simulink array output has data and time in one matrix

    • If adding signals, hope and pray they have the same time vector

    • Hope you don't accidentally add one time vector to another

What timeseries?

  • A Timeseries is a structure with fields Data and Time

    • ts.Data to get the data, ts.Time to get time

    • The MECE department says you should use arrays for simulink output but
      they are wrong

    • Array output treats time and data the same, and hides the time-dependence

    • You can plot a timeseries and MATLAB figures out the axes

    • synchronize to make the times for two timeseries the same, allowing math
      on the elements, or resample for just one

Timetables

  • A timeseries but with serveral fields synchronized to a time column

  • This time column has to have units

    • If it doesn't already come from Simulink, you have to use seconds, hours,
      milliseconds, etc.

Conclusion

  • More proficiency with basics

  • Know how to instrument code (benchmark, profile, debug)

  • Know that vectorizing is a thing

  • Can use structures, timeseries, and timetables

  • Notes will go on the wiki sometime this week

Remarks

  • In a 3-D array, the third index is the "page"

  • There are more options to speed up code

    • Column and row-major ordering differ

    • Contiguous and non-contiguous slicing differ

    • Not likely to be worth it (unless you're doing a lot of operations)

  • The first argument of fpritnf may be a file descriptor, which is a number
    representing an open file

    • fprintf(fid, ...)

    • Use fid = fopen("path_to_file") to print to a file you open

    • Use fid = 1 to print to the console

  • compose works like fprintf but on arrays of strings

References/Further reading