Hi,
As part of my ODE problem, I create a mutable struct Event
to store data in a readable manner within the Callback framework of DifferentialEquations.jl. I have then implemented an instance Buffer
of type Event
to continuously track data for a fixed duration already before an event gets detected by a given Callback function. For some reason, I am not able to update the Buffer
instance properly within my framework. My code looks like:
#Create new type "Event" with 4 fields
mutable struct Event
t::Array{Float64,1}
u::Array{Float64,3}
v::Array{Float64,3}
θ::Array{Float64,3}
end
The 3-dimensional arrays u,v
and θ
each contain different properties for a series of [time, x position, y position] respectively.
I initialize the Buffer
as zeros
arrays and create a function to update the Buffer of fixed size with the latest values from the ode integrator:
#Update Buffer values with new integrator values
function buffer!(integrator,Buffer::Event)
update!(Buffer.t,integrator.t)
update!(Buffer.u,integrator.u[:,:,1])
update!(Buffer.v,integrator.u[:,:,2])
update!(Buffer.θ,integrator.u[:,:,3])
end
where the function update!
is given by:
#Functions to copy old values and add new ones at the end (updating buffer)
function update!(u::Array{Float64,3},v::Array{Float64,2})
u[1:end-1,:,:] = u[2:end,:,:] #move each value
u[end,:,:] = v #add new value at the end
end
function update!(u::Array{Float64,1},v::Float64)
u[1:end-1] = u[2:end] #move each value
u[end] = v #add new value at the end
end
Finally, I use the buffer!
function within a condition
and affect!
function that I pass as a DiscreteCallback
.
When I print the output of u,v
and θ
for the last five timesteps for a single position x=1, y=1 in order to check the buffer update at each iteration, I obtain:
#Iteration 1
"Buffer.u[end-5:end,1,1] = [0.0, 0.0, 0.0, -0.644079, -0.000371415, 0.0230215]"
"Buffer.v[...] = [0.0, 0.0, 0.0, -0.644079, -0.000371415, 0.0230215]"
"Buffer.θ[...] = [0.0, 0.0, 0.0, -0.644079, -0.000371415, 0.0230215]"
#Iteration 2
"Buffer.u[...] = [-0.644079, -0.000371415, 0.0230215, -0.644093, -0.000400668, 0.0242796]"
"Buffer.v[...] = [-0.644079, -0.000371415, 0.0230215, -0.644093, -0.000400668, 0.0242796]"
"Buffer.θ[...] = [-0.644079, -0.000371415, 0.0230215, -0.644093, -0.000400668, 0.0242796]"
...
What I would like to see is:
#Iteration 1
"Buffer.u[...] = [0.0, 0.0, 0.0, 0.0, 0.0, -0.644079]"
"Buffer.v[...] = [0.0, 0.0, 0.0, 0.0, 0.0, -0.000371415]"
"Buffer.θ[...] = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0230215]"
#Iteration 2
"Buffer.u[...] = [0.0, 0.0, 0.0, 0.0, -0.644079, -0.644093]"
"Buffer.v[...] = [0.0, 0.0, 0.0, 0.0, -0.000371415, -0.000400668]"
"Buffer.θ[...] = [0.0, 0.0, 0.0, 0.0, 0.0230215, 0.0242796]"
...
As you can see, update!
copies all three integrator.u
arrays [:, :, 1], [:, :, 2] and [:, :, 3] to each field u,v
and θ
instead of copying them individually to the respective field. The update of Buffer.t
works fine and if I just update a single field (u,v
or θ
) it also works fine. As additional information, my Buffer
variable is global
to be recognized in the callback function. I use Julia 1.1.1 and I have tried implementations with getfield
and setfield!
which do not change my issue.
Despite the limited information, I would be thankful for any advice on what I am doing wrong here and how I can address and update the individual fields correctly.
Luis