I just don’t understand why we need to provide u to nlsolve, which is just the array of variables for any particular ODE function
I think I misdirected you initially to provide u to nlsolve, because I misunderstood what the mathematical problem was. I think I understand correctly now that k is a set of implicit Runge-Kutta coefficients that have to be solved for at each time step, from a set of nonlinear equations involving f for fixed values of u and t So u and t are the parameters in the nonlinear solve and k is the unknown.
So the code snippet
function f!(fx, u)
fx .= f(u, t, dt, k)
end
c1 = nlsolve(f!, k)
should be changed to
function f!(fk, k)
fk .= f(u, t, dt, k)
end
solution = nlsolve(f!, k)
ksolution = solution.zero
And that code snippet should be inside the time-stepping loop, so that the u and t parameters can be set to their current values at any given time step.