How to change specific parameter in DifferentialEquations CallbackSet?

I am trying to run a simulation of a bacterial population with Julia. I set a function that takes one parameter (growth rate, mu) that should change at a specific time point (t_in). I set the CallbackSet for the DifferentialEquations package, but I don’t think the condition is implemented because nothing happens to the simulation – the growth does not show any difference. This might be due to the data themselves, but I think I got the syntax wrong.
The CallbackSet was designed to change the amounts of the bacteria, thus, the u parameter. Now I need to change p parameter and I am not sure if I got it right. I am pasting a snippet of the code for syntax checking. Is it correct?
Thank you

function dual_logist!(du, u, p, t)
    # parameters
    μ = p[:μ]   # bacterial growth rate
    # ODE
    du[1] = (μ[1]*u[1]*ł)  - (δ[1]*u[1]*u[5])  - (ω*u[1])
    du[2] = (μ[2]*u[2]*ł)  - (δ[2]*u[2]*u[6])  - (ω*u[2])

using DifferentialEquations
mu = [mu_0, nu_0]
u0 = ...
tspan = (0, 500)
t_in = 100
condition_1(u, t, integrator) = t_in     # time
affect_1!(integrator) = μ[1] = mu_1  # amount
cb1 = ContinuousCallback(condition_1, affect_1!)
condition_2(u, t, integrator) = t_in     # time
affect_2!(integrator) = μ[2] = nu_1  # amount
cb2 = ContinuousCallback(condition_2, affect_2!)
parms = (μ=mu...)
conditions = CallbackSet(cb1, cb2)
prob = ODEProblem(dual_logist!, u0, tspan, parms)
soln = solve(prob, Rosenbrock23(), callback=conditions, tstops=[t_in])

Try integrator.p

Thank you, I tried with:

condition_1(u, t, integrator) = t_in     
affect_1!(integrator.p) = μ[1] = mu_1  
cb1 = ContinuousCallback(condition_1, affect_1!)
soln = solve(prob, Rosenbrock23(), callback=conditions)

but I got the error:
syntax: "integrator.p" is not a valid function argument
So I tried with:

affect_1!(p) = μ[1] = mu_1  # amount

and it worked. But I still do not see any difference. To check if a modification is introduced, I set mu_1 to zero. Is the syntax correct?

Oops, sorry, I mean:

affect_1!(integrator) = integrator.p[:μ] = mu_1 (If the p is mutable)


affect_1!(integrator) = integrator.p = a_new_p_with_mu_1_updated (If the p is immutable)

I’m not sure about the structure of p. Could it be a NamedTuple or a LabelledArray?

Thank you, it is a named tuple:

julia> typeof(parms)
NamedTuple{(:μ, :κ, :ω, :δ, :η, :β, :λ), Tuple{Vector{Float64}, Float64, Int64, Vararg{Vector{Float64}, 4}}}

How to create a new NamedTuple based on the old one

nt = (a=1, b=2, c=3)

newnt = merge(nt, (; b=10))  #(a=1,b=10,c=3)

EDIT: I noticed p.μ is an array, so this might work

function affect_1!(integrator)
    integrator.p.μ[1] = mu_1

Or, if you don’t want side effects of mutating the array:

function affect_1!(integrator)
    # Copy the array and assign a new value at the 1st element
    newμ = replace(integrator.p.μ, 1 => mu_1) 
    # Replace the old params with the new ones
    integrator.p = merge(integrator.p, (; μ=newμ ))

Since your parameter set has two tiers, I would like to recommend the package ComponentArrays.jl, which handles nested named components better.

I tried with this approach, but again there was no difference in the data…

Thanks to a tip from Steffen P. it turned out the problem was in the time condition: it should be

condition_1(u, t, integrator) = t - t_in 

Now it works as you indicated.
Thank you for the support.