Hi everybody. i’m been working on this package for already some time, and it seems like is the time to make an announcement on discourse
What does it do?
if i oversymplify, is an equivalent of Tables.jl for Thermodynamic Models.
A problem when designing those models is that you want a lot of properties with different implementations, For example, if you want the the enthalpy of a liquid, maybe you want to calculate that using Pressure and Temperature, or Pressure and Entropy, or Molar Volume and Temperature, or specifify that is saturated… etc. at the start, if you have only one model, this is easy, you can just write the implementations directly:
pressure(v,t)
entropy(v,t)
...
if you have two or more models, maybe do something like this:
pressure(model::Model1,v,t)
entropy(model::Model1,v,t)
...
pressure(model::Model2,v,t)
entropy(model::Model2,v,t)
the problem arrises when now you want to add a different way to calculate said properties. one way is to add a function preffix or suffix:
#volume - temperature
pressure_vt(model::Model1,v,t)
entropy_vt(model::Model1,v,t)
...
pressure_vt(model::Model2,v,t)
entropy_vt(model::Model2,v,t)
#entropy - temperature
pressure_st(model::Model1,s,t)
entropy_st(model::Model1,s,t)
...
pressure_vt(model::Model2,s,t)
entropy_vt(model::Model2,s,t)
other option is to use a type system to signal on what function dispatch
#volume - temperature
pressure_vt(model::Model1,v,t)
entropy_vt(model::Model1,v,t)
...
pressure(model::Model2,::VT,v,t)
entropy(model::Model2,::VT,v,t)
#entropy - temperature
pressure(model::Model1,::ST,s,t)
entropy(model::Model1,::ST,s,t)
...
pressure_vt(model::Model2,::ST,s,t)
entropy_vt(model::Model2,::ST,s,t)
either way, the user interface has become cluttered. with multicomponent models, the problem is aggravated, as now the material parts can come in diferent forms, do i want a mol fraction, a mass fraction? total amounts? .
With all done, now there exists the Unitful.jl package, that, while excelent on what it does, now requires another dispatch.
This package was done to explore a possible solution of this problem.
Usage:
The package revolves around the ThermodynamicState
object, that can be created with the state
function:
st = state(t=1.0u"°C",p=1.0u"atm")
all property functions have the form : property(model,state,units,args..,kwargs...)
the “Simplest model” is the one that doesn’t calculate anything, and returns the values stored in thermodynamic state:
t0 = temperature(FromState(),st) #kelvin by default, no Unitful, returns 274.15
t0 = temperature(FromState(),st,u"°C") #no Unitful, returns 1.0
t0 = @to_units temperature(FromState(),st) #kelvin by default, with Unitful, returns 274.15 K
t0 = @to_units temperature(FromState(),st,u"°C") #with Unitful, returns 1.0 °C
there is a lot more to explain, in the Readme is a somewhat more detailed explanation of what it does.
I have been eating my own dog food and using this package to port some thermodynamic models to the interface proposed here. some resulting packages are:
(almost registered, properties of moist air)
(not registered, collection of models)
If this is useful for someone else besides myself, let me know if i can help.