205205
206206@inline __build_interpolation (cache:: MIRKCache , u:: AbstractVector ) = MIRKInterpolation (cache. mesh, u, cache)
207207
208+ @inline __stage_values (k, prototype) = k
209+ @inline __stage_values (k:: PreallocationTools.DiffCache , prototype) = get_tmp (k, prototype)
210+
211+ @inline __copy_stage_values (k, prototype) = copy (k)
212+ @inline __copy_stage_values (k:: PreallocationTools.DiffCache , prototype) = copy (get_tmp (k, prototype))
213+
214+ @inline __stage_weight_eltype (k, weights) = typeof (zero (eltype (k)) * zero (eltype (weights)))
215+
216+ function __stage_weighted_zero (prototype, k, weights)
217+ T = __stage_weight_eltype (k, weights)
218+ return fill! (similar (prototype, T), zero (T))
219+ end
220+
221+ @inline __primal_value (x) = x
222+ @inline __primal_value (x:: ForwardDiff.Dual ) = __primal_value (ForwardDiff. value (x))
223+
208224"""
209225 EvalSol
210226
@@ -224,8 +240,7 @@ function (s::EvalSol{C})(tval::Number) where {C <: MIRKCache}
224240 dt = cache. mesh_dt[ii]
225241 τ = (tval - t[ii]) / dt
226242 w, _ = interp_weights (τ, alg)
227- K = __needs_diffcache (alg. jac_alg) ? @view (k_discrete[ii]. du[:, 1 : stage]) :
228- @view (k_discrete[ii][:, 1 : stage])
243+ K = @view (__stage_values (k_discrete[ii], z)[:, 1 : stage])
229244 KI = @view (k_interp. u[ii][1 : length_z, 1 : (cache. ITU. s_star - stage)])
230245 __maybe_matmul! (@view (z[1 : length_z]), K, @view (w[1 : stage]))
231246 __maybe_matmul! (@view (z[1 : length_z]), KI, @view (w[(stage + 1 ): cache. ITU. s_star]), true , true )
@@ -256,8 +271,7 @@ function (s::EvalSol{C})(tvals::AbstractArray{<:Number}) where {C <: MIRKCache}
256271 dt = mesh_dt[ii]
257272 τ = (tval - t[ii]) / dt
258273 w, _ = interp_weights (τ, alg)
259- K = __needs_diffcache (alg. jac_alg) ? @view (k_discrete[ii]. du[:, 1 : stage]) :
260- @view (k_discrete[ii][:, 1 : stage])
274+ K = @view (__stage_values (k_discrete[ii], zvals[i])[:, 1 : stage])
261275 KI = @view (k_interp. u[ii][1 : length_z, 1 : (cache. ITU. s_star - stage)])
262276 __maybe_matmul! (@view (zvals[i][1 : length_z]), K, @view (w[1 : stage]))
263277 __maybe_matmul! (
@@ -276,14 +290,15 @@ end
276290
277291# Intermediate derivative solution for evaluating derivative boundary conditions
278292function (s:: EvalSol{C} )(tval:: Number , :: Type{Val{1}} ) where {C <: MIRKCache }
279- (; t, cache) = s
293+ (; t, u, cache) = s
280294 (; alg, stage, k_discrete, k_interp, mesh_dt) = cache
281- z′ = zeros (typeof (tval), cache. M)
282295 ii = interval (t, tval)
283296 dt = mesh_dt[ii]
284297 τ = (tval - t[ii]) / dt
285298 _, w′ = interp_weights (τ, alg)
286- __maybe_matmul! (z′, @view (k_discrete[ii]. du[:, 1 : stage]), @view (w′[1 : stage]))
299+ K = __stage_values (k_discrete[ii], last (u))
300+ z′ = __stage_weighted_zero (last (u), K, w′)
301+ __maybe_matmul! (z′, @view (K[:, 1 : stage]), @view (w′[1 : stage]))
287302 __maybe_matmul! (
288303 z′, @view (k_interp. u[ii][:, 1 : (cache. ITU. s_star - stage)]), @view (w′[(stage + 1 ): cache. ITU. s_star]),
289304 true , true
@@ -372,19 +387,48 @@ end
372387end
373388
374389"""
375- update_eval_sol!(eval_sol::EvalSol, y_, cache::MIRKCache)
390+ update_eval_sol!(eval_sol::EvalSol, y_, cache::MIRKCache, u )
376391
377392Update the intermediate solution `eval_sol` with the new flattened solution `y_` and the cache.
378393When evaluating boundary conditions with new solution during nonlinear solving, we should
379394always update the intermediate solution with discrete solution + discrete stages + new stages
380395(Continuous MIRK: u(meshᵢ + τ*dt) = yᵢ + dt sum br(τ)*kr).
381396"""
382- @views function update_eval_sol! (eval_sol:: EvalSol , y_, cache:: MIRKCache )
383- eval_sol. u[1 : end ] .= __restructure_sol (y_, cache. in_size)
397+ @views function update_eval_sol! (eval_sol:: EvalSol , y_, cache:: MIRKCache , u)
398+ y = __restructure_sol (y_, cache. in_size)
399+ T_y = eltype (u)
400+ if eltype (first (eval_sol. u)) != = T_y || T_y != = eltype (cache)
401+ eval_cache = __mirk_eval_cache (cache, y, u)
402+ interp_setup! (eval_cache)
403+ return EvalSol (y, cache. mesh, eval_cache)
404+ end
405+ eval_sol. u[1 : end ] .= y
384406 eval_sol. cache. k_discrete[1 : end ] .= cache. k_discrete
385407 eval_sol. cache. k_interp. u[1 : end ] .= cache. k_interp. u
386408 interp_setup! (eval_sol. cache)
387- return nothing
409+ return eval_sol
410+ end
411+
412+ function __zeroed_similar_vector_of_array (x:: AbstractVectorOfArray , prototype)
413+ T = eltype (prototype)
414+ z = zero (first (prototype))
415+ return VectorOfArray ([fill! (similar (xᵢ, T), z) for xᵢ in x. u])
416+ end
417+
418+ function __mirk_eval_cache (
419+ cache:: MIRKCache{iip, T, use_both, DC, tune_parameters} , y, u
420+ ) where {iip, T, use_both, DC, tune_parameters}
421+ k_discrete = [__copy_stage_values (k, u) for k in cache. k_discrete]
422+ k_interp = __zeroed_similar_vector_of_array (cache. k_interp, u)
423+ new_stages = __zeroed_similar_vector_of_array (cache. new_stages, u)
424+ return MIRKCache {iip, T, use_both, NoDiffCacheNeeded, tune_parameters} (
425+ cache. order, cache. stage, cache. M, cache. in_size, cache. f, cache. bc, cache. prob,
426+ cache. problem_type, cache. p, cache. alg, cache. TU, cache. ITU, cache. f_prototype,
427+ cache. bcresid_prototype, cache. mesh, cache. mesh_dt, k_discrete, k_interp, y,
428+ cache. y₀, cache. y₀_flat, cache. residual, cache. fᵢ_cache, cache. fᵢ₂_cache,
429+ cache. errors, new_stages, cache. resid_size, cache. singular_term, cache. nlsolve_kwargs,
430+ cache. optimize_kwargs, cache. kwargs, cache. verbose
431+ )
388432end
389433
390434"""
@@ -399,7 +443,7 @@ function __construct_then_solve_root_problem(sol::EvalSol{C}, tspan::Tuple) wher
399443 nlsols = Vector {SciMLBase.NonlinearSolution} (undef, length (nlprobs))
400444 nlsolve_alg = __FastShortcutNonlinearPolyalg (eltype (sol. cache))
401445 for i in 1 : n
402- f = @closure (t, p) -> sol (t, Val{1 })[i]
446+ f = @closure (t, p) -> __primal_value ( sol (t, Val{1 })[i])
403447 nlprob = NonlinearProblem (f, sol. cache. prob. u0[i], tspan)
404448 nlsols[i] = solve (nlprob, nlsolve_alg)
405449 end
0 commit comments