Problem with plotting and printing inside a loop

Hello, there! I’m studying a physical system with the following code:

θ = 0.01; dθ = 0.01
ϵ = 1.0
J = 1.0
μ = 1.0
h=0.0
i=1

while θ < 2
    m0 = 0.1
    while ϵ > 0.001
        m = μ*tanh(J/(μ*θ)*m0 + h)
        print(m)
        ϵ = abs(m-m0)
        m0 = m
    end
    plot!(θ,m)
    θ += dθ
end

but neither the prints called by print(m) and the plots called by plot!(θ,m) are being made. Is there something wrong with the way I’m writing them?

I’m slightly surprised your code doesn’t produce errors (it doesn’t run for me at all, Julia 1.5.3). What version of Julia and Plots.jl are you using? Some comments:

  1. I would expect m to be local to the while loop, and cause an error in the plot! unless you had previously defined it in an outer scope. Here’s info about local scopes. Did you already define m in REPL?
  2. What do you expect from plot!? Usually you need to feed it array-like collections, not scalars. Perhaps you mean to add a single point at a time, in which case you might have better success with plot!([θ],[m]). Also I am assuming you are using Plots?
  3. How did you initialize your plot? If your plot! works at all, it will just add to an existing plot. You may want to initialize a blank plot with plt = plot() before the loop.
  4. And if you have a plot that doesn’t display, and it’s been initialized as above, you can do display(plt) to make it appear as explained here. But I’m not sure if that’s your problem, since I half expect m not to exist in that scope.
  5. I have no idea why your print doesn’t work, but you may prefer to use println to get a newline between outputs.
  6. I followed the steps above and got something that ran. My println did work, but that inner while only iterated twice, so there was not much output. It appears you expect something to converge iteratively, but two iterations will not look very impressive.
  7. Would help if you could provide an MWE that runs, or at least errors like expected. And maybe some context about what you’re trying to do and what you expect to happen.
2 Likes

As such, print(m) works as long as before the loop you set each time:

θ = 0.01
ϵ = 1.0

but you probably want to use print("$m ") or println(m) to easily read it.

As said by @apo383 for the plot you need something more and different (and, being only 1 point each time, you should use scatter!). So:

plot()
while θ < 2
    m0 = 0.1
    while ϵ > 0.001
        m = μ*tanh(J/(μ*θ)*m0 + h)
        print("$m ")
        ϵ = abs(m-m0)
        m0 = m
    end
    display(scatter!([θ],[m]))
    θ += dθ
end
3 Likes

Hello @apo383 and @davide! Thank you very much! Your suggestions and corrections made it work.
I’m sorry I forgot to made it clear. Yes, I’m using Plots.jl.

@apo383:

  1. Corrected that (new code at the end of this reply).
  2. I expect to plot, at each cycle, a coordinate pair (θ,m) produced by the calculations.
  3. Corrected that.
  4. Corrected that as suggested by @davide.
  5. print("$m ") works.
  6. Yes, the inner loop calculate a iteration that initializes from m0=0.1. At the first iteration, for θ almost zero, two iterations are enough (I checked myself).

@davide:
That’s a little embarassing, ha! Obviosly the inner loop would only run once, since I was not reinitializing ϵ = 1.0 at each outter loop.

Now, I present the new code and the plot that I wanted to plot. Just need to figure how to fit a curve instead of a series of points. Once again, thank you very much!

using Plots
θ = 0.01; dθ = 0.01
J = 1.0
μ = 1.0
h=0.0
i=1


while θ < 2
    m0 = 0.1
    m=0
    ϵ = 1.0
    while ϵ > 0.001
        m = μ*tanh(J/(μ*θ)*m0 + h)
        ϵ = abs(m-m0)
        m0 = m
    end
    print("$m ")
    if i == 1
        display(scatter([θ],[m]))
    else
        display(scatter!([θ],[m]))
    end
    θ += dθ
    i +=1
end

mT

Might be worth pointing out that if you just want the last plot, there’s no need to call display inside the loop. You can display it once at the end:

plt = plot()
for ...
   ...
   scatter!(plt, ...)
end
display(plt)  # or just `plt` if in the REPL or running a Jupyter/Juno/VSCode/Pluto cell

If you do want to see an animation of intermediate plots, maybe you should also take a look at the Animations section of the Plots manual.

1 Like

Hi @leopdsf

if you do not need animation, you may collect the values (eg. in a matrix or in 2 vectors) inside the loop, and plot it at once when finished, so to have a unique line, using plot in this case (and not scatter).

2 Likes

Did that :smiley:

θ = 0.01; dθ = 0.00001
J = 1.0
h= 0.0
i= 1
μ = 1.0
lm = 2.0
N = ceil(Int,lm/dθ-1000)
S=zeros(N,2)

while θ < lm
    m0 = 0.1
    m=0
    ϵ = 1.0
    while ϵ > 0.0001
        m = μ*tanh(J/(μ*θ)*m0 + h)
        ϵ = abs(m-m0)
        m0 = m
    end
    #print("$m ")
    S[i,1]=θ
    #print("$m ")
    S[i,2]=m
    θ += dθ
    i +=1
end

Got a nicer graph:
mT(hdiff0)