Skip to main content
A MATLAB command window beside a labelled engineering plot, with a matrix grid motif in the background.
From the blog · by Ali Jabbary

MATLAB for engineering students: the 20% that does 80% of your coursework

Ali Jabbary
Ali Jabbary
M.Sc., P.Eng.
9 min read
#matlab#simulink#engineering#numerical-methods

Article Summary

A Mechanical P.Eng. on the small slice of MATLAB that gets you through engineering coursework — the matrix mindset, the .* trap, clean plots, and ode45.

A second-year mechanical student showed up to a session last term genuinely upset. Her vibrations assignment kept throwing the same red error — Matrix dimensions must agree — and she'd spent two hours convinced she had the physics wrong. She didn't. She'd written F = k*x where she meant F = k.*x, multiplied two column vectors the wrong way, and MATLAB did exactly what she told it to. We fixed it in about ninety seconds. Then we spent the rest of the hour on the thing that actually mattered: building a mental model so the error never came back.

I've used MATLAB professionally as a mechanical engineer — heat transfer models, signal processing, the occasional controls problem — and I've taught it to students for over a decade. Here's the honest truth nobody tells you in the first lecture: you do not need to learn MATLAB. You need to learn the 20% of it that does 80% of your coursework. The rest you can look up the day you need it. This post is that 20%.

Everything is a matrix (yes, even your single number)

The single biggest unlock for a new MATLAB user is this: MATLAB thinks in matrices first, scalars never. The name is literally short for Matrix Laboratory. When you type x = 5, MATLAB stores a 1×1 matrix. When you type t = 0:0.1:10, you get a 1×101 row vector. Almost every confusing error you'll hit in first and second year comes from a mismatch between the shape you think you have and the shape MATLAB actually has.

So before you write any line involving two variables, ask one question: what's the size of each thing? You can always check:

t = 0:0.1:10;
size(t)      % ans = [1 101]  -> a row vector
size(t')     % ans = [101 1]  -> a column vector (the ' transposes it)

That size() habit will save you more time than any other single thing in this article. When something breaks, your first move is not to stare at the formula — it's to print the sizes.

The * vs .* trap

This is the one that gets everybody, so let's kill it properly. MATLAB has two completely different multiplications:

  • * is matrix multiplication — the linear-algebra one, with the inner-dimensions-must-match rule.
  • .* is element-wise multiplication — multiply each element by the matching element, same shape in, same shape out.

The dot means "do this element by element." Here's a three-line demo that makes the difference impossible to forget:

a = [1 2 3];     % 1x3 row vector
b = [4 5 6];     % 1x3 row vector

a .* b           % element-wise -> [4 10 18]
a * b'           % matrix mult  -> 32  (a dot product: 1*4 + 2*5 + 3*6)
a * b            % ERROR: inner dimensions don't agree (1x3 times 1x3)

Read those three lines until they're boring. a .* b gives you a vector. a * b' gives you a single number because you turned b into a column first. a * b just errors, because you asked for matrix multiplication on two incompatible shapes.

The rule of thumb for coursework: if you're doing physics or engineering math on arrays of data — forces at each point, temperature at each node, a signal sampled over time — you almost always want .*, ./, and .^. You reach for plain * only when you genuinely mean a matrix operation (solving A\b, rotating a vector, that kind of thing). The same logic applies to division and powers: t.^2 squares every element, while t^2 tries to matrix-multiply t by itself and will yell at you unless t is square.

Takeaway: when in doubt, use the dot. Ninety percent of "dimensions must agree" errors in early coursework vanish the moment you put dots on your operators.

Indexing without the dimension-mismatch panic

Indexing in MATLAB has two quirks that trip up everyone coming from Python or C.

First, MATLAB indexes from 1, not 0. The first element of v is v(1). There is no v(0), and asking for it is an error, not a wraparound.

Second, you use round brackets () to index, not square brackets. Square brackets build arrays; round brackets pull elements out of them.

v = [10 20 30 40 50];

v(1)        % 10        -> first element
v(end)      % 50        -> 'end' is the last index, very handy
v(2:4)      % [20 30 40] -> a slice
v(v > 25)   % [30 40 50] -> logical indexing: keep elements matching a condition

That last one — logical indexing — is the move that separates people who fight MATLAB from people who enjoy it. Instead of writing a loop to find values above a threshold, you write the condition and MATLAB hands you the matching elements. Want to zero out every negative entry in a signal? s(s < 0) = 0. One line, no loop.

For matrices, indexing is (row, column):

A = [1 2 3; 4 5 6; 7 8 9];
A(2, 3)     % 6   -> row 2, column 3
A(2, :)     % [4 5 6]  -> the whole second row (the colon means 'all')
A(:, 1)     % [1; 4; 7] -> the whole first column

The colon : reads as "everything along this dimension." A(2,:) is "row 2, all columns." Once that clicks, slicing data out of a results matrix for plotting stops being a guessing game.

Plots that don't lose you marks

Here's a thing I wish someone had told me as a student: in most lab courses, your plots are graded as hard as your numbers. A correct result on an unlabelled, untitled, axis-less plot gets marked down, and rightly so — an engineer who hands a colleague an anonymous curve is handing them a puzzle. The good news is that a presentable plot is about five extra lines, and they're always the same five.

t = 0:0.01:2;
y = exp(-t) .* sin(2*pi*5*t);     % a damped oscillation (note the .*)

figure;
plot(t, y, 'LineWidth', 1.5);
xlabel('Time (s)');
ylabel('Amplitude (V)');
title('Damped 5 Hz Oscillation');
grid on;
legend('measured response');

Memorise that block. xlabel, ylabel, title, grid on, legend — with units in the axis labels, because a label that says "Time" without "(s)" is half a label. When you need to compare several curves on one figure, hold on lets you stack them:

figure; hold on;
plot(t, exp(-t),        'DisplayName', 'envelope');
plot(t, exp(-t).*sin(2*pi*5*t), 'DisplayName', 'signal');
legend show;          % picks up the DisplayName of each line
hold off;

And when a report wants several plots together, subplot(rows, cols, k) tiles them:

subplot(2,1,1); plot(t, y);       title('Response');
subplot(2,1,2); plot(t, abs(y));  title('Magnitude');

That's genuinely most of the plotting you'll do for two years of coursework. Labels, legend, grid, subplots. Everything fancier you can look up the afternoon you need it.

Scripts are fine — until they aren't

You'll start by writing scripts: top-to-bottom files that run every line in order. That's correct, and for a quick assignment it's all you need. The trouble starts when one script balloons to 200 lines, you copy-paste the same ten-line calculation three times, and you change a constant in two of the three copies. Now your bug isn't physics — it's bookkeeping.

The fix is to pull repeated logic into a function. A function takes inputs, returns outputs, and keeps its own variables to itself so it can't accidentally clobber something in your main script. Here's the same calculation as a script line and then as a function:

% --- script style: fine for one-off use ---
m = 2; k = 50;
omega_n = sqrt(k/m);

% --- function style: reusable, testable, named ---
function wn = natural_frequency(m, k)
    % NATURAL_FREQUENCY  Undamped natural frequency of a spring-mass system.
    %   wn = natural_frequency(m, k) returns sqrt(k/m) in rad/s.
    wn = sqrt(k / m);
end

The refactor rule I give students: the first time you copy-paste a calculation, stop and make it a function. Not the third time, the first. A function with a clear name (natural_frequency) also documents your intent — six weeks later, wn = natural_frequency(m, k) tells you what's happening; a bare sqrt(k/m) buried in line 140 does not. If you'd like the structured walk-through from scripts to functions to clean numerical methods, that's a core part of how I teach one-on-one MATLAB.

Solving an ODE with ode45 (the syntax everyone trips on)

If you're in mechanical, electrical, or any flavour of dynamics, you will solve ordinary differential equations numerically, and ode45 is the workhorse — a general-purpose solver for non-stiff problems. The concept is easy. The syntax is where people lose an evening, so let's be precise.

Per the MathWorks documentation, the basic call is:

[t, y] = ode45(odefun, tspan, y0)

Three ingredients: odefun is a function handle describing your derivatives, tspan is the time interval, and y0 is your initial condition(s). The piece that trips everyone is odefun. The docs are exact about its shape:

"The function dydt = odefun(t,y), for a scalar t and a column vector y, must return a column vector dydt... odefun must accept both input arguments t and y, even if one of the arguments is not used in the function."

Read that twice. Two inputs in — t and y — always, even if you don't use t. A column vector out. That's the contract. Break it and you get cryptic errors.

Let's solve a damped spring-mass system, m·x″ + c·x′ + k·x = 0. The trick (the other thing people trip on) is converting a second-order equation into a system of two first-order ones. Let y(1) = x (position) and y(2) = x' (velocity). Then:

% Parameters
m = 1; c = 0.5; k = 20;

% The derivative function: takes (t, y), returns a COLUMN vector
odefun = @(t, y) [ y(2);                                  % d/dt of position = velocity
                  (-c*y(2) - k*y(1)) / m ];               % d/dt of velocity from the ODE

tspan = [0 10];        % solve from t=0 to t=10 seconds
y0    = [1; 0];        % initial position 1, initial velocity 0  (a COLUMN)

[t, y] = ode45(odefun, tspan, y0);

plot(t, y(:,1), 'LineWidth', 1.5);
xlabel('Time (s)'); ylabel('Position (m)');
title('Damped Spring-Mass Response'); grid on;

The @(t, y) [...] is an anonymous function — it builds the function handle inline. Notice the output is a column vector [ ... ; ... ] with a semicolon between the rows: top entry is the rate of change of position, bottom is the rate of change of velocity. y0 = [1; 0] is a column too — keep that consistent and ode45 is happy. After the solve, y(:,1) is the position column and y(:,2) is the velocity column.

If your system needs extra parameters, the documented pattern is to wrap them in the handle: ode45(@(t,y) myode(t,y,c,k), tspan, y0). MATLAB only feeds t and y to the solver; the rest get baked in. That's the official advice, and it's the clean way to avoid global variables.

When Simulink actually enters the picture (an honest paragraph)

Students often ask whether they should be learning Simulink alongside MATLAB. Honest answer: usually not yet. Simulink is a block-diagram environment for modelling and simulating dynamic systems graphically — you wire up blocks instead of writing solver code, and it's genuinely excellent for control systems, signal flows, and multi-domain physical models where a diagram beats a wall of script. But it's a separate tool with its own learning curve, and most first- and second-year coursework lives entirely in the MATLAB scripting world. You'll typically meet Simulink in a dedicated controls or systems course, where the instructor introduces it on purpose. Until then, getting fluent with vectors, functions, and ode45 is a far better use of your hours. Learn the foundation; pick up Simulink when a course actually puts it in front of you.

The recap

The 20% that carries your coursework, in order of how often you'll lean on it:

What The thing to remember
Matrix mindset Everything's a matrix; check size() before you debug
* vs .* When in doubt, use the dot for element-wise math
Indexing Starts at 1, uses (), and v(v > 25) (logical indexing) is your friend
Plots xlabel/ylabel with units, title, grid on, legend, subplot — graded, so do them
Scripts → functions First copy-paste of a calculation, make it a function
ode45 Handle takes (t, y), returns a column vector; y0 is a column too

Master those six and you've covered the overwhelming majority of what undergraduate MATLAB throws at you. The fancy toolboxes and the thousand-page reference manual can wait for the specific day a specific assignment demands them — which, for most of your degree, is rarely.

If a Matrix dimensions must agree error has you convinced your physics is broken when it's really a missing dot, that's exactly the kind of thing that's faster to untangle with someone watching your screen than alone at midnight. I teach MATLAB one-on-one to engineering students, the first session is free, and we can start from wherever your coursework actually is — not from page one of a manual you don't have time to read.

Enjoyed this post? Get the next one in your inbox.

A short, useful email when there's a new tutorial, study guide, or career-prep post on the blog. No spam, unsubscribe anytime.

Ali Jabbary

Written by Ali Jabbary

M.Sc., P.Eng. • Expert Data Scientist & ML Engineer with 10+ years of experience. 500+ students helped worldwide. Specializing in Python, AI/ML, and turning complex problems into simple solutions.

Want 1-on-1 help on this? Here's where to go next:

More articles you might find useful.

Book a free callMessage Ali