MTK & units

In the past, I have more or less converted units manually, but have now started to use Unitful.jl – which also ties into Plots.jl and gives convenient typesetting of units along the axes.

To me, there are at least 3 reasons why units are useful:

  1. Correct handling of units and unit conversion.
  2. Checking a model for unit consistency.
  3. Simple inclusions of units in plots.

General allowance for units in quantities carries some (considerate) computational overhead in ModelingToolkit.jl. Because of that, units may be specified via the unit construct:

params = @parameters begin
        # Constant
        mb = 14,        [unit=u"u", description = "Nitrogen atom mass"]
        ... 
        #
    end

My understanding is that this support is limited to SI units (base SI units only?), and that units may be used for checking unit consistency - which is great (reason 12). Perhaps units are also included along Plots.jl axes via the recipes (reason 3)?

So the unit construct in MTK partially solves my problem by at least addressing reason 2. However, if only base SI units are allowed, this will probably make the model stiff? Say I am modeling atomic interaction where the natural time unit is ps. If I am forced to use unit s, that leads to clumsy numbers along the axes.


Next, consider the case that I am mainly (at the moment) interested in reasons 1 and 3 above.

Question 1:
To handle conversion of units, etc., I assume that I can do as follows:

params = @parameters begin
        # Constant
        mb = ustrip(uconvert(u"g", 14u"u")),        [description = "Nitrogen atom mass"]
        ... 
        #
    end

and that this will not have a detrimental effect on the solution time - even if I use Unitful.jl?

Question 2:
How can I handle automatic addition of units along the axes? Suppose I have instantiated an MTK model with name tp_h and solved this model, with solution sol_h where one of the unknowns is x_1

Doing

plot(sol_h, idxs=(tp_h.t, tp_h.x_1))

plots this result without units.

However, I don’t see how I can add units here. After all, tp_h.t is an index, so I can not write tp_h.t*u"ps" - as an example.

I can, of course, create a time vector manually, and add units:

tm_vec = collect(range(0,0.1,length=100))
x_1 = sol_h.(tm_vec, idxs=tp_h.x_1)

plot(tm_vec*u"ps", x_1*u"nm")

but this way I don’t utilize the elegant recipe of MTK.

Any way to combine MTK recipe with adding units?

We will be removing Unitful in the very near future. Unitful just gives so many compilation problems that it cannot be well-supported. We’ll keep a certain amount of DynamicQuantities.jl support, but for the most part the unit support is still very basic.

Yes, codegen cannot at this time add conversion factors.

At this time no.

1 Like