Hello, now that I (sort of) know how to calculate differential equations with nested functions I would like to learn how to use it with callbacks. Callbacks are used to run a differential equation to a certain point, changing the value of a parameter and then continue running. And that’s really handy when working with seasonal data.
I know how a callback looks like when using a differential equation that does not have nested functions, but my experiments with a callback and differential equation with nested functions have failed so far.
The outline of the code (I will post the whole code if you want, but I don’t know how to make a MWE because there are many parts)
function FF (parameters)
function CalcG (parameters)
function dNdT (parameters) #change in nutrient 'biomass'
something* CalcG (parameters)
end
function dPdT (parameters) #change in plant biomass
something/ FF (parameters)+ CalcG (parameters)
end
function dAdT (parameters) #change in animal biomass
function FF (parameters)
end
And then dNdT
, dPdT
, dAdT
are placed together into one array and calculated at the same time:
function dBdT_test(dB, bioS, p, t) #where dB is change in biomass
#extinction
@. bioS[bioS<0.000001] = 0.0 #here I don't know if this should be placed before or after the equations
@. dB[bioS<0.000001] = 0.0
dN = dB[1:num_nutrient]
dP = dB[num_nutrient+1:(arr_size-num_animal)]
dA = dB[(arr_size-num_animal+1):arr_size]
dB[1:num_nutrient] = dNdT(dN, D, S, N, K, v1, v2, r, bioS)
dB[num_nutrient+1:(arr_size-num_animal)] = dPdT(dP, K, N, r, bioS, X, num_plant, num_animal, num_nutrient)
dB[(arr_size-num_animal+1):arr_size] = dAdT(dA, foodWeb, e, bioS, X, num_plant, num_animal, num_nutrient, bm, b, h, ω, q)
#extinction
@. bioS[bioS<0.000001] = 0.0
@. dB[bioS<0.000001] = 0.0 #here I don't know if this should be placed before or after the equations
end
tspan = (0.0,500.0)
p = (foodWeb, num_plant, num_animal, num_nutrient, D, S, N, K, v1, v2, r, X, e, bm, b, h, ω, q)
prob = ODEProblem(dBdT,bioS,tspan,p)
sol=solve(prob)
Is it good to have dNdT
, dPdT
, dAdT
as separate functions and then call them into dBdT
?
I only want to put a callback for a specific species (lets say species 42) in dAdT
.
Should I place the callback into function dAdT
or function dBdT
?
I tried putting it into dBdT like so, but then f1 is not defined
dB[(arr_size-num_animal+1):arr_size] = dAdT_harvest(dA, foodWeb, e, bioS, X, num_plant, num_animal, num_nutrient, bm, b, h, ω, q) - (catch_co*bioS[42]*effort + f1)`
And the callback is
function condition(u,t,integrator)
t == 200.
end
function affect!(integrator)
for c in full_cache(integrator)
integrator.p[21] = 0.01
end
end
cb = DiscreteCallback(condition, affect!)
tspan = (0.0,500.0)
p = (foodWeb, num_plant, num_animal, num_nutrient, D, S, N, K, v1, v2, r, X, e, bm, b, h, ω, q, catch_co, effort, f1)
prob = ODEProblem(dBdT,bioS,tspan,p)
sol=solve(prob,callback=cb,tstops=[200.0])
Suggestions are greatly appreciated