Open keckler opened 3 years ago
I really like the idea of integrating Pint into the parameter definition system. The parameter definition objects in here have a string that represents the units and we could (perhaps optionally?) have the framework load up the equivalent unit type from the pint db (or a user-provided custom pint db). Then we can provide easy examples showing people how to do conversions, etc. with the framework.
That said, users at the moment can use pint if they want to using the param definitions as they are. This would involve basically doing something like the following given a block b
and trying to convert its power param from (whatever it's defined as) to megawatts. (it's defined in watts btw but the point here is that the person writing this code doesn't need to know or care what the actual internal parameter units are to get to MW here).
import pint
ureg = pint.UnitRegistry()
powerDef = b.pDefs['power']
power = b.p.power * ureg(powerDef.units)
power.to("MW")
We could perhaps imagine putting in a convenience api like a b.punits.power
which would automatically attach the pint units capabilities (returning a Pint Quantify rather than a float), like:
b.punits.power.to("MW")
I have one quick thought on this. It might be super obvious, but I just want to throw it out there.
In all the scientific models I've seen (Fermilab, climate change, MRIs, etc), the units INSIDE the model are formally set and never change. This makes the math easier (and faster). Different units can be used as INPUTS or OUTPUTS, but inside the model everything is kept simple.
So, users can provide whatever input data in whatever units. But once the program starts running, everything is converted to the preferred in-model units.
This is handy for people writing code inside ARMI. But it also has a big performance boost, since any array of data we have is just a NumPy array of floats, and not a NumPy array of Pint objects.
This may be totally obvious, I just wanted to make the goal clear.
I have finally started on this ticket.
First things first, a huge number of our Parameter
s are missing units. Or the units are spelled in an inconsistent manner. That is resolved with this PR: https://github.com/terrapower/armi/pull/1345
Of course, the next step would be to actually use pint
instead of the silly strings we have in Parameter
s now.
But I am leaving that off for a second still, as pint
won't be able to handle a lot of our units:
"n/s/cm$^2$"
"He/s/cm$^3$"
"dk/kk' * K^(n-1)"
"%FIMA/day spatial peak"
"fissions/cm^3/s"
Due to the nature of the plugins in ARMI and their different needs, the code does not enforce a specific set of units. This has led to a variety of units being used for the same physical quantities throughout the code in a way that is difficult to predict. And because the units of some quantities are not specified (see 351), sometimes it is unclear what units should be used for a given parameter.
It is desirable to implement a system which tracks and converts the units of physical quantities in ARMI as needed.
Not saying that this would definitely work, but a system such as Pint could potentially work well for this task.