@@ -372,36 +372,38 @@ end
372372
373373function simulateSegment! (m:: SimulationModel{FloatType,TimeType} , algorithm= missing ; kwargs... ) where {FloatType,TimeType}
374374 solution = nothing
375+ options = m. options
375376
376377 sizesOfLinearEquationSystems = Int[length (leq. b) for leq in m. linearEquations]
377378
378379 # Define problem and callbacks based on algorithm and model type
379- interval = m . options. interval
380- if abs (m . options. stopTime - m . options. startTime) <= 0
380+ interval = options. interval
381+ if abs (options. stopTime - options. startTime) <= 0
381382 interval = 1.0
382- tspan2 = [m . options. startTime]
383- elseif abs (m . options. interval) < abs (m . options. stopTime- m . options. startTime)
383+ tspan2 = [options. startTime]
384+ elseif abs (options. interval) < abs (options. stopTime- options. startTime)
384385 if m. nsegments == 1
385- tspan2 = m . options. startTime: interval: m . options. stopTime
386+ tspan2 = options. startTime: interval: options. stopTime
386387 else
387- i = ceil ( (m . options. startTime - m . options. startTimeFirstSegment)/ interval )
388- tnext = m . options. startTimeFirstSegment + i* interval
389- tspan2 = tnext: interval: m . options. stopTime
390- if tspan2[1 ] > m . options. startTime
391- tspan2 = [m . options. startTime, tspan2... ]
388+ i = ceil ( (options. startTime - options. startTimeFirstSegment)/ interval )
389+ tnext = options. startTimeFirstSegment + i* interval
390+ tspan2 = tnext: interval: options. stopTime
391+ if tspan2[1 ] > options. startTime
392+ tspan2 = [options. startTime, tspan2... ]
392393 end
393394 end
394- if tspan2[end ] < m . options. stopTime
395- tspan2 = [tspan2... , m . options. stopTime]
395+ if tspan2[end ] < options. stopTime
396+ tspan2 = [tspan2... , options. stopTime]
396397 end
397398 else
398- tspan2 = [m . options. startTime, m . options. stopTime]
399+ tspan2 = [options. startTime, options. stopTime]
399400 end
400- tspan = (m . options. startTime, m . options. stopTime)
401+ tspan = (options. startTime, options. stopTime)
401402
402403 eh = m. eventHandler
403- m. odeMode = true
404- m. solve_leq = true
404+ for leq in m. linearEquations
405+ leq. odeMode = true
406+ end
405407 if typeof (algorithm) <: DifferentialEquations.DiffEqBase.AbstractDAEAlgorithm
406408 # DAE integrator
407409 m. odeIntegrator = false
@@ -411,27 +413,65 @@ function simulateSegment!(m::SimulationModel{FloatType,TimeType}, algorithm=miss
411413 TimerOutputs. @timeit m. timer " DifferentialEquations.DAEProblem" problem = DifferentialEquations. DAEProblem {true} (DAEresidualsForODE!, m. der_x, m. x_init, tspan, m, differential_vars = differential_vars)
412414 empty! (m. daeCopyInfo)
413415 if length (sizesOfLinearEquationSystems) > 0 && maximum (sizesOfLinearEquationSystems) >= options. nlinearMinForDAE
414- # Prepare data structure to efficiently perform copy operations for DAE integrator
416+ # Prepare data structure to efficiently perform copy operations for DAE integrator
415417 x_info = m. equationInfo. x_info
416418 der_x_dict = m. equationInfo. der_x_dict
417419 der_x_names = keys (der_x_dict)
420+ daeMode = false
418421 for (ileq,leq) in enumerate (m. linearEquations)
419- if sizesOfLinearEquationSystems[ileq] >= options. nlinearMinForDAE &&
420- length (intersect (leq. x_names,der_x_names)) == length (leq. x_names)
421- # Linear equation shall be solved by DAE and all unknowns of the linear equation system are DAE derivatives
422- leq. odeMode = false
423- m. odeMode = false
424- leq_copy = LinearEquationsCopyInfoForDAEMode (ileq)
425- for ix in 1 : length (leq. x_names)
426- x_name = leq. x_names[ix]
427- x_length = leq. x_lengths[ix]
428- x_info_i = x_info[ der_x_dict[x_name] ]
429- @assert (x_length == x_info_i. length)
430- startIndex = x_info_i. startIndex
431- endIndex = startIndex + x_length - 1
432- append! (leq_copy. index, startIndex: endIndex)
422+ if sizesOfLinearEquationSystems[ileq] >= options. nlinearMinForDAE
423+ answer = leq. x_names .∈ Ref (der_x_names)
424+ daeMode = true
425+ for (index, val) in enumerate (answer)
426+ if ! val && leq. x_lengths[index] > 0
427+ daeMode = false
428+ break
429+ end
430+ end
431+
432+ if daeMode
433+ # Linear equation shall be solved by DAE and all unknowns of the linear equation system are DAE derivatives
434+ if eh. nz > 0
435+ leq. odeMode = true
436+ daeMode = false
437+ if options. log
438+ println (" No DAE mode for equation system $ileq because $(eh. nz) crossing function(s) defined (see issue #686 of DifferentialEquations.jl)" )
439+ end
440+
441+ else
442+ leq. odeMode = false
443+ leq_copy = LinearEquationsCopyInfoForDAEMode (ileq)
444+ for ix in 1 : length (leq. x_names)
445+ x_length = leq. x_lengths[ix]
446+ if x_length > 0
447+ x_name = leq. x_names[ix]
448+ x_info_i = x_info[ der_x_dict[x_name] ]
449+ @assert (x_length == x_info_i. length)
450+ startIndex = x_info_i. startIndex
451+ endIndex = startIndex + x_length - 1
452+ append! (leq_copy. index, startIndex: endIndex)
453+ end
454+ end
455+ push! (m. daeCopyInfo, leq_copy)
456+ end
457+ else
458+ if options. log
459+ unknownsThatAreNoStateDerivatives = " "
460+ first = true
461+ for (index, val) in enumerate (answer)
462+ if ! val && leq. x_lengths[index] > 0
463+ if first
464+ first = false
465+ unknownsThatAreNoStateDerivatives = " \" " * leq. x_names[index] * " \" "
466+ else
467+ unknownsThatAreNoStateDerivatives *= " ,\" " * leq. x_names[index] * " \" "
468+ end
469+ end
470+ end
471+ println (" No DAE mode for equation system $ileq because the unknowns $unknownsThatAreNoStateDerivatives are no state derivatives!" )
472+ end
473+ leq. odeMode = true
433474 end
434- push! (m. daeCopyInfo, leq_copy)
435475 else
436476 leq. odeMode = true
437477 end
@@ -442,6 +482,21 @@ function simulateSegment!(m::SimulationModel{FloatType,TimeType}, algorithm=miss
442482 m. odeIntegrator = true
443483 TimerOutputs. @timeit m. timer " DifferentialEquations.ODEProblem" problem = DifferentialEquations. ODEProblem {true} (derivatives!, m. x_init, tspan, m)
444484 end
485+
486+ if length (m. linearEquations) == 0
487+ m. odeMode = true
488+ m. solve_leq = true
489+ else
490+ m. odeMode = false
491+ m. solve_leq = false
492+ for leq in m. linearEquations
493+ if leq. odeMode
494+ m. odeMode = true
495+ m. solve_leq = true
496+ break
497+ end
498+ end
499+ end
445500
446501 callback2 = DifferentialEquations. DiscreteCallback (timeEventCondition!, affectTimeEvent!)
447502 if eh. nz > 0
@@ -450,9 +505,9 @@ function simulateSegment!(m::SimulationModel{FloatType,TimeType}, algorithm=miss
450505 # FunctionalCallingCallback(outputs!, ...) is not correctly called when zero crossings are present.
451506 # The fix is to call outputs!(..) from the previous to the current event, when an event occurs.
452507 # (alternativey: callback4 = DifferentialEquations.PresetTimeCallback(tspan2, affect_outputs!) )
453- callback1 = DifferentialEquations. FunctionCallingCallback (outputs!, funcat= [m . options. startTime]) # call outputs!(..) at startTime
508+ callback1 = DifferentialEquations. FunctionCallingCallback (outputs!, funcat= [options. startTime]) # call outputs!(..) at startTime
454509 callback3 = DifferentialEquations. VectorContinuousCallback (zeroCrossings!,
455- affectStateEvent!, eh. nz, interp_points= m . options. interp_points, rootfind= DifferentialEquations. SciMLBase. RightRootFind)
510+ affectStateEvent!, eh. nz, interp_points= options. interp_points, rootfind= DifferentialEquations. SciMLBase. RightRootFind)
456511 # callback4 = DifferentialEquations.PresetTimeCallback(tspan2, affect_outputs!)
457512 callbacks = DifferentialEquations. CallbackSet (callback1, callback2, callback3) # , callback4)
458513 else
@@ -463,24 +518,24 @@ function simulateSegment!(m::SimulationModel{FloatType,TimeType}, algorithm=miss
463518
464519 # Initial step size (the default of DifferentialEquations integrators is too large) + step-size of fixed-step algorithm
465520 if ! m. sundials
466- dt = m . options. adaptive ? m . options. interval/ 10 : m . options. interval # initial step-size
521+ dt = options. adaptive ? options. interval/ 10 : options. interval # initial step-size
467522 end
468523
469524 # Compute solution
470- abstol = 0.1 * m . options. tolerance
525+ abstol = 0.1 * options. tolerance
471526 tstops = (m. eventHandler. nextEventTime,)
472527 maxiters = Int (typemax (Int32)) # switch off maximum number of iterations (typemax(Int) gives an inexact error for Sundials)
473528 if ismissing (algorithm)
474- TimerOutputs. @timeit m. timer " DifferentialEquations.solve" solution = DifferentialEquations. solve (problem, reltol= m . options. tolerance, abstol= abstol, save_everystep= false ,
475- callback= callbacks, adaptive= m . options. adaptive, saveat= tspan2, dt= dt, dtmax= m . options. dtmax, maxiters= maxiters, tstops = tstops,
529+ TimerOutputs. @timeit m. timer " DifferentialEquations.solve" solution = DifferentialEquations. solve (problem, reltol= options. tolerance, abstol= abstol, save_everystep= false ,
530+ callback= callbacks, adaptive= options. adaptive, saveat= tspan2, dt= dt, dtmax= options. dtmax, maxiters= maxiters, tstops = tstops,
476531 initializealg = DifferentialEquations. NoInit ())
477532 elseif m. sundials
478- TimerOutputs. @timeit m. timer " DifferentialEquations.solve" solution = DifferentialEquations. solve (problem, algorithm, reltol= m . options. tolerance, abstol= abstol, save_everystep= false ,
479- callback= callbacks, adaptive= m . options. adaptive, saveat= tspan2, dtmax= m . options. dtmax, maxiters= maxiters, tstops = tstops,
533+ TimerOutputs. @timeit m. timer " DifferentialEquations.solve" solution = DifferentialEquations. solve (problem, algorithm, reltol= options. tolerance, abstol= abstol, save_everystep= false ,
534+ callback= callbacks, adaptive= options. adaptive, saveat= tspan2, dtmax= options. dtmax, maxiters= maxiters, tstops = tstops,
480535 initializealg = DifferentialEquations. NoInit ())
481536 else
482- TimerOutputs. @timeit m. timer " DifferentialEquations.solve" solution = DifferentialEquations. solve (problem, algorithm, reltol= m . options. tolerance, abstol= abstol, save_everystep= false ,
483- callback= callbacks, adaptive= m . options. adaptive, saveat= tspan2, dt= dt, dtmax= m . options. dtmax, maxiters= maxiters, tstops = tstops,
537+ TimerOutputs. @timeit m. timer " DifferentialEquations.solve" solution = DifferentialEquations. solve (problem, algorithm, reltol= options. tolerance, abstol= abstol, save_everystep= false ,
538+ callback= callbacks, adaptive= options. adaptive, saveat= tspan2, dt= dt, dtmax= options. dtmax, maxiters= maxiters, tstops = tstops,
484539 initializealg = DifferentialEquations. NoInit ())
485540 end
486541
0 commit comments