Plotting Implicit Functions using ImplicitEquations.jl

I’m trying to plot an implicit function

using Plots, ImplicitEquations 
f(x,y)= sqrt((x^2+144)+(y^2+144))

and I get
ERROR: Cannot convert Num to series data for plotting
perhaps it’s because I have x and y as symbols

using ModelingToolkit, Plots, ImplicitEquations

@variables x y

f(x,y)= sqrt((x^2+144)+(y^2+144))

Yes.

Ok, how would I change the types, so that I have the right type for ploting?

You should use actual numbers rather than symbolic numbers.

julia> using Plots, ImplicitEquations

julia> f(x, y) = sqrt((x^2+144)+(y^2+144))
f (generic function with 1 method)

julia> plot(f ⩵ 20,  xlims = (-15, 15), ylims=(-15, 15))

produces

Screen Shot 2020-11-06 at 3.13.00 PM

2 Likes

I see thanks, I get that. the problem is that I’m doing derivatives, and need symbols for that, so I’d like to be able to change symbols back to numbers, so that I can plot with them.

You’d use build_function to get the Julia function and then do the ImplicitEquations plot with that.

1 Like

I thought I had it

build_function(f,[x,y])
plot(f(x,y)

but it’s still a symbol

julia> using ModelingToolkit; @variables x y;

julia> f(x,y)= sqrt((x^2+144)+(y^2+144))
f (generic function with 1 method)

julia> let ex = Differential(x)(f(x, y))
           func_ex = build_function(expand_derivatives(ex), x, y)
           @eval ∂xf(x, y) = ($func_ex)(x,y)
       end
∂xf (generic function with 1 method)

julia> using Plots, ImplicitEquations

julia> plot(∂xf ⩵ 0.1, xlims=(0, 10), ylims=(-100, 100))

produces

Screen Shot 2020-11-06 at 3.44.22 PM

In the future, people will have an easier time helping you if you actually show the code that produces the error. It’s a lot harder to help if we have to guess what you’re actually doing.

5 Likes

You’re not building the right function (or even using the right syntax for build_function). What Chris suggested was to use build_function to get a julia native function representation of the derivative, not the original function f.

Ok, I see, so I use Differential(x), to do a n implicit derivative as a f of x and y, then I use @eval to save the function as a Julia function.

There are a few issues:

  1. The predicate function in ImplicitEquations are too tightly typed
  2. build_function as called return an expression. You can get a function by passing expression=Val{false} but that is of type ggfunc and then see 1)
  3. You can call eval on an expression but that returns a function taking a single argument so needs some massaging, e.g.:

g(x,y) = eval(build_function(f(x,y), [x,y])((x,y)))

That’s a bit cumbersome, the fix should be addressing 1). (Though @Mason makes it look more elegant in his solution)

In the interim, there are some other possibilities. This page has an example with IntervalConstraintProgramming:

https://juliahub.com/docs/CalculusWithJulia/AZHbv/0.0.5/derivatives/implicit_differentiation.html

This page shows how Makie + MDBM could be used.

It would require a bit of adjusment to work with Plots, but not so much.

Just a little nitpick, this will run eval every time you call g, so it is different from what I wrote in more than aesthetics. My version doesn’t use eval at runtime.

Thanks for the clarification!

@variables μ x y u
@derivatives δx'~x δy'~y δu'~u δμ~μ 
expand_derivatives(δu(sqrt(u))*δx((x^2+144)) +δμ(sqrt(μ))*δy(y^2+144))

but I get 0 for some reason.
this is how I originally did the expand part

I don’t get zero when I run the code you showed. First, I got an error because you write δμ~μ instead of δμ'~μ , but after fixing that, I get

julia> using ModelingToolkit

julia> @variables μ x y u
(μ, x, y, u)

julia> @derivatives δx'~x δy'~y δu'~u δμ'~μ
((D'~x), (D'~y), (D'~u), (D'~μ))

julia> expand_derivatives(δu(sqrt(u))*δx((x^2+144)) +δμ(sqrt(μ))*δy(y^2+144)) |> simplify
(2 * inv(2 * sqrt(u)) * x) + (2 * y * inv(2 * sqrt(μ)))

Ok, I’m going to restart everything, I think that’s my problem.

Yes, that’s my problem. I need to know how to clean my regestries, I’m also not sure how to sub a function for u or μ

What did you use to simplify?

That simplify was not necessary, I just put it in there to check if expand_derivatives had any simplifications left over, but it didn’t. I forgot to remove it.

To answer your question though, simplify is exported by ModelingToolkit. The code I posted was self contained.

1 Like

Ok, I was having trouble with ModelingToolkit’s simplify, but it might be I wasn’t using it right.