Plotting vector fields

I wrote this down because it is weirdly hard to find anything on this topic.

To plot vector fields, use the undocumented (as of 2019 Dec 26) quiver function. Quiver is a strange name, coming from the military: a “quiver” is “a bundle of arrows”.

  quiver(x,y,quiver=(u,v))
  quiver!(x,y,quiver=(u,v))

  Make a quiver (vector field) plot. The ith vector extends from (x[i],y[i]) to (x[i] + u[i], y[i] + v[i]).

  Example
  ≡≡≡≡≡≡≡≡≡

  julia> quiver([1,2,3],[3,2,1],quiver=([1,1,1],[1,2,3]))

Here is my code that does this job, even if uglily,

using Plots

function vectorfield2d(field, points, arrowlength=0.1)
    # More input pattern parsing is solved by the Plots package, but I don't know how.
    errormessage = "Incorrect formatting of points. Please format them as [x1 y1; x2, y2;...]"
    
    if typeof(points) <: Array{<:Number, 2} && size(points)[1] === 2
        vectors = similar(points)
        for i in 1:size(points)[2]
            vectors[:, i] .= collect(field(points[:, i]...))
        end
    else
        error(errormessage)
    end
    vectors .*= arrowlength
    quiver(points[1, :],points[2, :],quiver=(vectors[1, :], vectors[2, :]))
    display(plot!())
end
        
vectorfield = vectorfield2d

A demonstration:

function meshgrid(n)
    xs = ones(n) .* (1:n)'
    ys = xs'
    xys = permutedims(cat(xs, ys; dims = 3), [3, 1, 2])
    return reshape(xys, 2, n^2)
end

vf(x, y) = (-y, x) # circular vectorfield

grid = meshgrid(20) ./ 2 .- [5; 5]
vectorfield2d(vf, grid)

5 Likes

Here’s a solution I found lying around my macine. It uses a function to calculate the vector at a given point.

There should definitely be better docs and a nicer way to do this:

xs = -2:0.2:2
ys = -2:0.2:2

using LinearAlgebra

df(x, y) = normalize([-y, x]) ./ 10

xxs = [x for x in xs for y in ys]
yys = [y for x in xs for y in ys]

quiver(xxs, yys, quiver=df)
6 Likes

If it’s undocumented, maybe you could add your write-up to the documentation?

1 Like

It’s undocumented in the sense that searching the docs gave me nothing. If I type ?quiver, it did print out how to use it.

If the docs failed you, no matter in what way, there is room for improvement. Maybe the plots docs needs a page that lists all docstrings so that they become searchable. This is easy to get using Documenter.jl

For future reference, you can try the function

julia> apropos("vector field")
Plots.quiver
Plots.quiver!
4 Likes

The has been other solutions, too, such as this, which scales the arrows correctly:
https://stackoverflow.com/questions/51466537/how-to-plot-a-vector-field-in-julia

There ought to be an official implementation in Plots, though.

1 Like