PVector

All of the sub-types of Number and Quantity are supported. In general it works as we expected whereas there are too many possibilities to foresee. Mathematically vector operations, linear algebra, array conversions, neighbor searching, etc. are well documented in corresponding sections.

The vector types are immutable out of performance reason.

PVector and PVector2D

Constructor

It is assumed that 3D vectors are used more often, so we choose PVector to represent 3D vectors and provide user-friendly functions to avoid errors in case you missed suffix 2D:

julia> using PhysicalParticles
julia> PVector(1.0, 2.0)PVector2D{Float64}(1.0, 2.0)
julia> PVector(2.0, 3.0, u"m")PVector2D(2.0 m, 3.0 m)

The default constructors of PVector are still 3d-version:

julia> PVector()PVector{Float64}(0.0, 0.0, 0.0)
julia> PVector(u"m")PVector(0.0 m, 0.0 m, 0.0 m)

Basic Operators

Basic maths are well support by overriding Base: +, -, *, /, and array operations are supported by overriding Base: length, iterate

julia> a = pconvert(ones(3))PVector{Float64}(1.0, 1.0, 1.0)
julia> b = pconvert(ones(3)) * 2PVector{Float64}(2.0, 2.0, 2.0)
julia> a + bPVector{Float64}(3.0, 3.0, 3.0)
julia> a * b6.0
julia> norm(a)1.7320508075688772
julia> norm(a) == sqrt(3)true
julia> normalize(a)PVector{Float64}(0.5773502691896258, 0.5773502691896258, 0.5773502691896258)
julia> normalize(a) == a / sqrt(3)true
julia> cross(a, b)PVector{Float64}(0.0, 0.0, 0.0)
julia> dot(a,b) == *(a,b)true
julia> c = pconvert(ones(3)) * 1.0u"m"PVector(1.0 m, 1.0 m, 1.0 m)
julia> c * a3.0 m

More types, more possibilities

T<:Number gives us a whole world to try out new vector operations. As we mentioned above, the build-in type operation and promotion schemes have guaranteed most of operations would be correct:

julia> a = PVector(1.0, 1.0, 1.0) * imPVector{ComplexF64}(0.0 + 1.0im, 0.0 + 1.0im, 0.0 + 1.0im)
julia> a * PVector(1, 2, 3)0.0 + 6.0im
julia> norm(a)0.0 + 1.7320508075688772im
julia> b = PVector(1.0f0, 2.0f0)PVector2D{Float32}(1.0f0, 2.0f0)
julia> b * 2PVector2D{Float32}(2.0f0, 4.0f0)
julia> b * 2.0PVector2D{Float64}(2.0, 4.0)
julia> PVector(BigFloat)PVector{BigFloat}(0.0, 0.0, 0.0)
julia> PVector2D(BigInt, u"m")PVector2D(0 m, 0 m)

LinearAlgebra

norm, normalize, dot, cross from LinearAlgebra module are overloaded.

However, when it comes to Quantity, some wierd things would happen:

julia> using Unitful
julia> sqrt(1.0u"km" * 1000.0u"m")31.622776601683793 m^1/2 km^1/2
julia> sqrt(upreferred(1.0u"km" * 1000.0u"m"))1000.0 m
julia> 1.0u"km" / sqrt(upreferred(1.0u"km" * 1.0u"km"))0.001 km m^-1

To avoid this, we have to use upreferred in both norm and normalize:

@inline norm(p::PVector2D) = sqrt(upreferred(p * p))
@inline normalize(p::PVector2D) = (n = ustrip(norm(p)); return PVector2D(upreferred(p.x/n), upreferred(p.y/n)))

@inline norm(p::PVector) = sqrt(upreferred(p * p))
@inline normalize(p::PVector) = (n = ustrip(norm(p)); return PVector(upreferred(p.x/n), upreferred(p.y/n), upreferred(p.z/n)))

uconvert, ustrip, zero, one

These would be useful when you cannot predict the type of input.

julia> p = PVector(2.0, 2.0, 2.0, u"km")PVector(2.0 km, 2.0 km, 2.0 km)
julia> uconvert(u"m", p)PVector(2000.0 m, 2000.0 m, 2000.0 m)
julia> ustrip(u"m", p)PVector{Float64}(2000.0, 2000.0, 2000.0)
julia> ustrip(p)PVector{Float64}(2.0, 2.0, 2.0)
julia> one(u"m", p)PVector(1.0 m, 1.0 m, 1.0 m)
julia> one(p)PVector{Float64}(1.0, 1.0, 1.0)
julia> zero(u"m", p)PVector(0.0 m, 0.0 m, 0.0 m)
julia> zero(p)PVector(0.0 km, 0.0 km, 0.0 km)

parse from string

julia> parse(PVector2D, "PVector2D{Float64}(1.0, 2.0)")PVector2D{Float64}(1.0, 2.0)
julia> parse(PVector, "PVector{Float32}(1.0f0, 2.0f0, 3.0f0)")PVector{Float32}(1.0f0, 2.0f0, 3.0f0)
julia> parse(PVector, "PVector(1.0f0 m s^-1, 2.0f0 m s^-1, 3.0f0 m s^-1)")PVector(1.0f0 m s^-1, 2.0f0 m s^-1, 3.0f0 m s^-1)
julia> parse(PVector2D, "PVector2D{ComplexF64}(1.0im, 2.0im)")PVector2D{ComplexF64}(0.0 + 1.0im, 0.0 + 2.0im)

numeric type conversion

julia> convert(PVector{Float32}, PVector(1.1,2.2,3.3))PVector{Float32}(1.1f0, 2.2f0, 3.3f0)
julia> convert(PVector{Int32}, PVector(1.0,2.0,3.0))PVector{Int32}(1, 2, 3)