Array definition error

question
#1

When I wrote the following code, an error occurred in the definition of the array.
I think that the definition of array u is done, but I do not know why the error occurs.

Changing the definition of [array u] to [global u] did not work well.

using Plots
gr()
function calc_nrm(a::Matrix{Float64},b::Matrix{Float64})
    n=size(a,1)
    nrm=a-b
    sum=0
    for i in 1:n
        for j in 1:n
            sum+=abs(nrm[i,j]^2)
        end
    end
    ans=sum^0.5

    return ans
end

w=1.
h=1.
Nx=200
Ny=200

delta_x=w/Nx
delta_y=h/Ny

u=zeros(Nx+1,Ny+1)
u_new=zeros(Nx+1,Ny+1)

u[1,:].=0.
u[:,1].=0.
u[Nx+1,:].=40.
u[:,Ny+1].=80.

u_new[1,:].=0.
u_new[:,1].=0.
u_new[Nx+1,:].=40.
u_new[:,Ny+1].=80.

err=0

num=2/(delta_x)^2+2/(delta_y)^2

while err==0
    for j in 2:Nx
        for k in 2:Ny
            u_new[j,k]=(1/num)*((u[j-1,k]+u[j+1,k])/(delta_x^2)+(u[j,k-1]+u[j,k+1])/(delta_y^2))
        end
    end
    if calc_nrm(u,u_new)<2.1
        err=1
    end
    u=u_new
end

ERROR: LoadError: UndefVarError: u not defined
Stacktrace:
 [1] top-level scope at C:\Users\yuki-\Documents\juliapra\wave\laplace.jl:45 [inlined]
 [2] top-level scope at .\none:0
in expression starting at C:\Users\yuki-\Documents\juliapra\wave\laplace.jl:42
#2

You need to add a global to your u:

    ....
    global u
    u = u_new
end

But note that after above statement your u and u_new point to the same array, which is probably not what you want. Probably best to swap bindings:

    ....
    global u, u_new
    u, u_new = u_new, u
end

Next time, please post a minimal, working (or erroring) example to make it easy on your helpers: PSA: make it easier to help you

Also, note that running stuff in global scope, i.e. not in a function is not performant. Check the performance-tips of the docs.

#3

I wrapped the code around the function f1!(u), that modifies the input u. this code works:

using Plots
gr()
function calc_nrm(a::Matrix{Float64},b::Matrix{Float64})
    n=size(a,1)
    nrm=a-b
    sum=0
    for i in 1:n
        for j in 1:n
            sum+=abs(nrm[i,j]^2)
        end
    end
    ans=sum^0.5

    return ans
end

#wrapped function, with parameters passed as arguments

function f1!(u,params)
w,h,Nx,Ny = params  
delta_x=w/Nx
delta_y=h/Ny
u_new=zeros(Nx+1,Ny+1)

u[1,:].=0.
u[:,1].=0.
u[Nx+1,:].=40.
u[:,Ny+1].=80.

u_new[1,:].=0.
u_new[:,1].=0.
u_new[Nx+1,:].=40.
u_new[:,Ny+1].=80.

err=0

num=2/(delta_x)^2+2/(delta_y)^2

while err==0
    for j in 2:Nx
        for k in 2:Ny
            u_new[j,k]=(1/num)*((u[j-1,k]+u[j+1,k])/(delta_x^2)+(u[j,k-1]+u[j,k+1])/(delta_y^2))
        end
    end
    if calc_nrm(u,u_new)<2.1
        err=1
    end
    u=u_new
    
end
return u
end

#execution

w=1.
h=1.
Nx=200
Ny=200
u=zeros(Nx+1,Ny+1)


params = (w,h,Nx,Ny)
u = f1!(u,params)
1 Like
#4

Yes, in a function, the global is not needed (and would be wrong). But the comment about swapping bindings still applies, I think. If you’re from a matlab background, read this http://www.johnmyleswhite.com/notebook/2014/09/06/values-vs-bindings-the-map-is-not-the-territory/.

1 Like
#5

Thanks. It worked!!

I have one more question about swapping array.

u,u_new=u_new,u

I changed this code as follows.

u=deepcopy(u_new)

But, it didn’t work. (It seemed u and u_new pointed to the same array)

So, is there any ways to do deepcopy() like python??

#6

It seems that’s what you asked for.

If you are swapping arrays, what is the point of deepcopy? But if you insist,

u, u_new = deepcopy(u_new), deepcopy(u)