Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to dispatch on molar mass? #662

Open
ejmeitz opened this issue Jul 9, 2023 · 4 comments
Open

How to dispatch on molar mass? #662

ejmeitz opened this issue Jul 9, 2023 · 4 comments

Comments

@ejmeitz
Copy link
Contributor

ejmeitz commented Jul 9, 2023

Hello,

I'd like to differentiate my functions based on if the user provided a Mass dimension or a molar mass dimension. Unitful already has the Unitful.Mass to make it easy to dispatch on mass but I've been majorly struggling to dispatch on molar mass. My attempt is below:

molar_mass_unit = Unitful.Dimensions{(Unitful.Dimension{:Mass}(1//1), Unitful.Dimension{:Amount}(-1//1))}
function f(a::Unitful.Quantity{T, molar_mass_unit, U}) where {T,U}
       println("molar mass function")
end

I also tried using

 molar_mass_unit = Unitful.Dimensions{(Unitful.𝐌,Unitful.𝐍^-1)}
@ejmeitz
Copy link
Contributor Author

ejmeitz commented Jul 9, 2023

Ok like 50th thing I tried worked but I still don't get why the above doesn't.

If I define @derived_dimension MolarMass 𝐌/𝐍 true I can just use MolarMass. I also created a PR to add this as one of the default derived units.

@sostock
Copy link
Collaborator

sostock commented Jul 12, 2023

My attempt is below:

molar_mass_unit = Unitful.Dimensions{(Unitful.Dimension{:Mass}(1//1), Unitful.Dimension{:Amount}(-1//1))}
function f(a::Unitful.Quantity{T, molar_mass_unit, U}) where {T,U}
       println("molar mass function")
end

This doesn’t work for two reasons:

  1. The second type parameter must be an instance of a Dimensions type, not a type itself (i.e., molar_mass_unit() instead of molar_mass_unit)
  2. Unitful uses a canonical ordering of the dimensions in the Dimensions type parameter. A value of 1u"kg/mol" (and any other quantity or unit of molar mass) has dimension
    julia> typeof(dimension(1u"kg/mol"))
    Unitful.Dimensions{(Unitful.Dimension{:Amount}(-1//1), Unitful.Dimension{:Mass}(1//1))}
    As you can see, the order of the dimensions is switched compared to your attempt. That’s why it doesn’t work.

I also tried using

molar_mass_unit = Unitful.Dimensions{(Unitful.𝐌,Unitful.𝐍^-1)}

This doesn’t work because Unitful.𝐌 and Unitful.𝐍 are already instances of the type Unitful.Dimensions, not Unitful.Dimension. The following works:

molar_mass_unit = Unitful.𝐌 * Unitful.𝐍^-1

@sostock
Copy link
Collaborator

sostock commented Jul 12, 2023

We should have better documentation for this. I think we should

  1. Feature @derived_dimension more prominently in the manual.
  2. Improve the part of the Quantity docstring which explains that D is an instance while U is a type:

    The type parameters D :: Unitful.Dimensions and U <: Unitful.Units.

@ejmeitz
Copy link
Contributor Author

ejmeitz commented Jul 12, 2023

Yeah definitely add another example to the dispatch part. Its a super useful and cool feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants