# How to use Parametric Structs with Unitful

**URL:** <https://discourse.julialang.org/t/how-to-use-parametric-structs-with-unitful/93049>\
**Category:** New to Julia\
**Tags:** question, parametric-types, unitful\
**Created:** [January 16, 2023, 9:03pm UTC](https://discourse.julialang.org/t/how-to-use-parametric-structs-with-unitful/93049 "2023-01-16T21:03:32Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![FelixHeox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/felixheox/32/44015_2.png) [@FelixHeox](https://discourse.julialang.org/u/FelixHeox)\
**Post date:** [January 16, 2023, 9:03pm UTC](https://discourse.julialang.org/t/how-to-use-parametric-structs-with-unitful/93049/1 "2023-01-16T21:03:32Z")

</div>

I am trying to create a package that solves the kinematics of a closed mechanism. The mechanism type consists of a list of link types that I have also defined parametricly:

```julia
abstract type Link end

struct BarLink{T} <: Link
	r::T # Vector Length
	θ::T # Position of link (variable) units of rad
	ω::T # Velocity of link, units of rad/s
	α::T # Acceleration of link, units of rad/s/s
end

struct Mechanism
	n::Integer 
	input::Integer #index of input link in link vector
	variables::Tuple{Integer, Integer} #index of variable links (2)
	links::Vector{Link}
end

```

Using Unitful I tried to create a 4-bar Mechanism:

```julia
bar1 = BarLink{Quantity}(10u"inch", Float64(π)u"rad", 0u"m/m", 0u"m/m") # line throws error
bar2 = BarLink{Quantity}(4u"inch", Float64(2*π/3)u"rad", 45u"rad/s", 0u"rad/s/s")
bar3 = BarLink{Quantity}(10u"inch", deg2rad(47.26)u"rad", 0u"m/m", 0u"m/m")
bar4 = BarLink{Quantity}(12u"inch", deg2rad(295.75)u"rad", 0u"m/m", 0u"m/m")

fourbar = Mechanism(4, 2, (3, 4), [bar1; bar2; bar3; bar4])

```

The error thrown from the initialization of `bar1`:

```julia
MethodError: no method matching Unitful.Quantity(::Int64)

```

For reference, I have similar code that works for other subtypes of Number:

```julia
bar1 = BarLink{Real}(10, π, 0, 0)
bar2 = BarLink{Real}(4, deg2rad(120), 45, 0)
bar3 = BarLink{Real}(10, deg2rad(227.26-180), 0, 0)
bar4 = BarLink{Real}(12, deg2rad(115.75+180), 0, 0)

fourbar = Mechanism(4, 2, (3, 4), [bar1; bar2; bar3; bar4])

```

and with SymPy:

```julia
@syms r1 r2 r3 r4 θ1 θ2 θ3 θ4 ω2 α2

bar1 = BarLink{Sym}(r1, θ1, 0, 0)
bar2 = BarLink{Sym}(r2, θ2, 0, 0)
bar3 = BarLink{Sym}(r3, θ3, 0, 0)
bar4 = BarLink{Sym}(r4, θ4, 0, 0)

fourbar = Mechanism(4, 2, (3,4), [bar1; bar2; bar3; bar4])

```

I have no idea why a method error is thrown, since Quantity is a subtype of Number, and also is abstract enough to contain different concrete subtypes of Quantity, shouldn’t the constructor create the datatype?

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [January 16, 2023, 10:42pm UTC](https://discourse.julialang.org/t/how-to-use-parametric-structs-with-unitful/93049/2 "2023-01-16T22:42:57Z")

</div>

There are some subtleties with Unitful. The unit `m/m` eagerly cancels the `m` to become dimensionless and actually a scalar Int. The following is something put together to avoid this:

```julia
# using Unitful and definition above

const mpm1 = Unitful.FreeUnits{(Unitful.Unit{:Meter, Unitful.𝐋}(0, 1),
  Unitful.Unit{:Meter, Unitful.𝐋}(0, -1)), NoDims, nothing}
const mpm = Quantity{Int64, NoDims, mpm1}(1)

bar1 = BarLink{Quantity}(10u"inch", Float64(π)u"rad", 0mpm, 0mpm) # line throws error
bar2 = BarLink{Quantity}(4u"inch", Float64(2*π/3)u"rad", 45u"rad/s", 0u"rad/s/s")
bar3 = BarLink{Quantity}(10u"inch", deg2rad(47.26)u"rad", 0mpm, 0mpm)
bar4 = BarLink{Quantity}(12u"inch", deg2rad(295.75)u"rad", 0mpm, 0mpm)

fourbar = Mechanism(4, 2, (3, 4), [bar1; bar2; bar3; bar4])

```

I’ll be happy to see more idiomatic ways of creating `m/m` unit.

---

<div class="post-metadata">

**Author:** ![tfiers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tfiers/32/32427_2.png) [@tfiers](https://discourse.julialang.org/u/tfiers)\
**Post date:** [January 17, 2023, 6:35am UTC](https://discourse.julialang.org/t/how-to-use-parametric-structs-with-unitful/93049/3 "2023-01-17T06:35:00Z")

</div>

If you are looking for performance, then “Avoid fields with abstract type”: [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-fields-with-abstract-type)  
(Quantity, Integer, and Link are all abstract types)\[1\]

I.e, if you want to keep the types parametric, it should be sth like

```julia
abstract type Link end

struct BarLink{R,Θ,Ω,Α} <: Link
	r::R # Vector Length
	θ::Θ # Position of link (variable) units of rad
	ω::Ω # Velocity of link, units of rad/s
	α::Α # Acceleration of link, units of rad/s/s
end

struct Mechanism{L<:Link}
	n::Int
	input::Int #index of input link in link vector
	variables::Tuple{Int,Int} #index of variable links (2)
	links::Vector{L}
end

```

(Note e.g. the `Int` (== `Int64`) instead of `Integer`: concrete vs abstract type. You could also annotate those fields `::I` and add `,I` or `,I<:Integer` in the parameter clause)

* * *

1. Note that this only applies to annotations of struct fields. Function argument annotations can still be happily abstract (or not given at all)

---

<div class="post-metadata">

**Author:** ![tfiers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tfiers/32/32427_2.png) [@tfiers](https://discourse.julialang.org/u/tfiers)\
**Post date:** [January 17, 2023, 6:55am UTC](https://discourse.julialang.org/t/how-to-use-parametric-structs-with-unitful/93049/4 "2023-01-17T06:55:36Z")

</div>

You don’t have to specify all those new type params on creation btw. They get filled in automatically. I.e:

```julia
bar1 = BarLink(10u"inch", Float64(π)u"rad", 0u"rad/s", 0u"rad/s/s")
bar1 = BarLink(10, π, 0, 0)
bar1 = BarLink(r1, θ1, 0, 0)

fourbar = Mechanism(4, 2, (3, 4), [bar1; bar2; bar3; bar4])

```
