File Exchange

image thumbnail

Physical Units Toolbox

version 4.2.0.0 (71.2 KB) by Sky Sartorius
Enables operations using hundreds of supported physical units of measurement and physical constants.

8 Downloads

Updated 10 Dec 2020

View Version History

GitHub view license on GitHub

Editor's Note: This file was selected as MATLAB Central Pick of the Week

If the Physical Units Toolbox is on your MATLAB path, there is nothing to initialize, import, add to your workspace, or pass to functions - simply multiply/divide by u.(unitName) to attach physical units to a variable. For example, to define a speed using a supported unit: carSpeed = 100 * u.kph. Or, define a speed with an unsupported unit as a combination of supported units: snailSpeed = 20 * u.m/u.week.

Variables with physical units attached are of the class DimVar ("dimenensioned variable"). Math operations performed on dimensioned variables will automatically perform dimensional analysis and can create new units or cancel units and return a normal variable.

On a global or per-project basis, you can customize to use the base unit system of your choice (e.g. ft-lb-s instead of the SI m-kg-s), as well as customize preferred display units. Display units for any given variable can also be customized. Variables will display in the command window or plot, etc. in terms of those units.

Most common Matlab functions will work with physical units, including many types of plots (with added axis labels).

Cite As

Sky Sartorius (2021). Physical Units Toolbox (https://github.com/sky-s/physical-units-for-matlab), GitHub. Retrieved .

Comments and Ratings (26)

Sky Sartorius

The class to clear is actually u, not DimVar, so the command is 'clear u' (or 'clear classes'). I just updated the help blocks of some of the relevant files to try to clarify a bit.

And no, I have not yet tried using the toolbox with App Designer.

moali

Got it, I didn't realize 'clear classes' was a command. I thought that meant 'clear all' and/or 'clear DimVar'.
Very helpful tool. Was hoping to use it in App Designer. Anyone try that? Any tips?

Sky Sartorius

Hi Mohamedali,
Any time you want to change the base unit system, you have to clear classes, otherwise the previously used base unit system will remain in effect.

moali

A bit confused how to change the BaseUnitSystem. I tried copying into my project and changing default unitSystem = 'IPS'. With it in my project I also tried baseUnitSystem = baseUnitSystem('IPS').
But no matter what I do I always get back SI. What am I doing wrong?
>> a=1*u.in;
>> b=a*a
b =
6.451600000000001e-04

>> c=b/a
c =
0.025400000000000
m

Sky Sartorius

Thank you all for the feedback.

Frieder,
The single input for the plot function is now handled since the 2018-02-19 version.

RY3A1R,
Since the change a 4.0 is so pervasive, unfortunately I think the only solution for loading old-version data would be to put the old version on you path, load the data, extract double / string information, then save and later convert that using the new version. Sorry about that. Loading old-version data was not a use case I planned for.

Terry,
The only thing I might expect could be your issue is if char(178) (the superscript 2: ²) does not show up properly on your system. Try commenting out lines 73-76 (latest version) of @DimVar\displayparser.m so that it renders as ^2 instead.

Sky

Pham Trung

Frieder Wittmann

Nice. Thank you!

The behavior of plot() was a bit unexpected at first:
-------------------------
>> x = [1 2 3 4] * u.m

x =

1 2 3 4

m

>> plot(x)
Index exceeds matrix dimensions.

Error in DimVar/plotfunctionwrapper (line 138)
labelaxes(gca,plottableArgs{1:2},[])

Error in DimVar/plot (line 263)
[varargout{1:nargout}] = plotfunctionwrapper('plot',varargin{:});
---------------

> plot(x,x)

Works. Would be nice if plot(x) worked, too. I use it frequently to glance at my data.

RY3A1R

Thanks a lot for this great Units package!
I have used it extensively during my thesis and other project work =)
(plus the fuel fraction sizing and oswald factor estimation!)

But please don't break old measurement data files saved using earlier (pre 4.0) versions of the toolbox.

Idea for major updates in the future: Provide a script to update the DimVar definition in the *.mat files
(e.g. load file using old scheme, remove units, reapply units using new scheme)

Kind regards,
Julius

TERRY CHEN

I used
a=1*u.m;
b=1*u.m;
c=a*b
but c=1*u.m
I don't konw why?
d=a*b*a*b
d=1*m4

Sky Sartorius

Thanks for catching that, Henry. Fixed.

Henry

line 881 in u.m
h_bar = u.h/(2*pi); % Dirac constant
should be:
h_bar = u.h_c/(2*pi); % Dirac constant

u.h was hour

Michele Oro Nobili

Sky Sartorius

Fixed. Thanks, Michele.

Michele Oro Nobili

function: unitConversionFactor
line18
it should be: to = str2u(to);

Thomas Jager

Alberto Comin

Sky Sartorius

That sounds interesting. Contact me via my profile.

Thomas

Thank you again, I have just refactored my code to take advantage of your alterations! Would you be interested in code that translates the units() objects into formated strings for use in siunitx latex package?
It is able to generate prefixes for orders of magnitude (e.g. mega,micro), takes into account units that do not take prefixes (kelvin) and knows about significant digits.

Sky Sartorius

Thomas,
Download the latest version, which has unitsOf and u2num implemented for non-DimVars as well. It also has a documented way to expand the list of base units (e.g., add 'mol') either by editing your units.m file or programmatically by providing the units function with your own unit system.

Thomas

Thanks for the response. Number 3 perfectly fixes my issue!
How about realizing 1 and 3? Add a u2num and unitsOf function to the units folder that contains the units() function and the class definition folder. Such that you can simply add the units folder to the path and it simply works out of the box.

Another one: how about adding support for mole?
Are you developing using git?

Sky Sartorius

@Emanuele: I expanded size and the other oversimplified methods to support their full functionality. Thanks for inspiring me to go through and clean up and improve everything.

The "content" method you describe is the same as the existing "u2num" method.

Emanuele Ruffaldi

Great tool. Two minor changes for improving interoperability with existing code:

function outSize = size(v1,v2)
outSize = size(v1.value);
if nargin == 2
outSize = outSize(v2);
end

function y = content(x)
y = x.value
end

Sky Sartorius

In order to do what you describe, Thomas, u2num and unitsOf can't be normal methods of the class (at least not by themselves). I see three solutions to do what you want:

1) Make them static methods; add
isa(inVariable,'DimensionedVariable')
...
else
out = in;
end
This required writing "DimensionedVariable." before all function calls.
2) Move the unitsOf and u2num m files from the @DimensionedVariable folder to somewhere on your path (I suggest the same folder where units.m lives); add the same if/else as above.
3) Don't bother with "if isa(..." - just make a function on your path like
function [out] = u2num( varargin )
out = varargin{1};
end
MATLAB will use this for any input that isn't a DimensionedVariable.

I don't find any of the above solutions to be very elegant, which is why I haven't done any of them for the released submission. Perhaps someone here can suggest a more elegant solution.

P.S. I added the ability to switch base unit systems (e.g. use feet and lbs instead of meters and kg). Stay tuned for a new upload.

Thomas

Thanks for the great routine!
I have one suggestion: when the result of a computation is a dimensionless variable, it will be a double. But when using u2num() or unitsOf() on a double, the algorithm fails. Therefore I need to check the variables before batch processing them (for automatic printing in Latex using siunitx package and newcommands).
Could you include something like
if strcmp(class(val),'DimensionedVariable')
...
else if strcmp(class(val),'double')
...
in those functions?
Regards Thomas

Sky Sartorius

I uploaded a new version that, among other improvements, especially in documentation, has an entirely new subsasgn file that should take care of the removing elements problem and the preallocating problem. When doing subscripted assignment, you have to be assigning using input/output with the same units. The only exception is that NaN and [] are now allowed (either normal or with units). For preallocation, use a dimensioned NaN array. If you don't know the dimensions you'll need, the new subsasgn will allow changing the units of an all-NaN array to match the assigned variable (with a warning).

John Doe

Very cool, I use it extensively and it really helps.
One thing that I encountered is that assignements such as vect(index)=[] which remove elements in a vector don't work when using a DimensionedVariable vector.
Also preallocating arrays e.g. before a loop is not possible when we don't know the unit of the content at the moment of allocation. Maybe NaN and 0 should be treated specially, in a sense these have no unit and any unit at the same time.

MATLAB Release Compatibility
Created with R2015b
Compatible with any release
Platform Compatibility
Windows macOS Linux

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!