Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better error message if a ReactionMethod fails at runtime #140

Merged
merged 1 commit into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 79 additions & 24 deletions src/Model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ function create_model_from_config(
catch e
error("$(typeof(e)) while reading .yaml config file(s) $(abspath.(config_files)).\n"*
"If the error isn't obvious by looking at the file(s) (often this is a whitespace issue), "*
"try an online YAML validator eg http://www.yamllint.com")
"install the VS Code YAML plugin, or try an online YAML validator eg http://www.yamllint.com")
end

conf_model = data[configmodel]
Expand Down Expand Up @@ -778,12 +778,19 @@ function dispatch_methodlist(
dl::ReactionMethodDispatchListNoGen,
deltat::Float64=0.0
)
lasti = -1

for i in eachindex(dl.methods)
call_method(dl.methods[i], dl.vardatas[i], dl.cellranges[i], deltat)
end
try
for i in eachindex(dl.methods)
lasti = i
call_method(dl.methods[i], dl.vardatas[i], dl.cellranges[i], deltat)
end
catch
lasti != -1 && _dispatch_methodlist_methoderror(dl.methods[lasti][])
rethrow()
end

return nothing
return nothing
end

function dispatch_methodlist(
Expand All @@ -792,33 +799,62 @@ function dispatch_methodlist(
deltat::Float64=0.0
)

for j in eachindex(dl.methods)
methodref = dl.methods[j]
if has_modified_parameters(pa, methodref)
call_method(methodref, get_parameters(pa, methodref), dl.vardatas[j], dl.cellranges[j], deltat)
else
call_method(methodref, dl.vardatas[j], dl.cellranges[j], deltat)
lasti = -1

try
for i in eachindex(dl.methods)
lasti = i
methodref = dl.methods[i]
if has_modified_parameters(pa, methodref)
call_method(methodref, get_parameters(pa, methodref), dl.vardatas[i], dl.cellranges[i], deltat)
else
call_method(methodref, dl.vardatas[i], dl.cellranges[i], deltat)
end
end
end
catch
lasti != -1 && _dispatch_methodlist_methoderror(dl.methods[lasti][])
rethrow()
end

return nothing
return nothing
end

@generated function dispatch_methodlist(
dl::ReactionMethodDispatchList{M, V, C},
function _dispatch_methodlist_methoderror(reactionmethod)
io = IOBuffer()
println(io, "dispatch_methodlist: a ReactionMethod failed:")
show(io, MIME"text/plain"(), reactionmethod)
@warn String(take!(io))
return
end

function dispatch_methodlist(
@nospecialize(dl::ReactionMethodDispatchList),
deltat::Float64=0.0
)
try
_dispatch_methodlist(dl, deltat)
catch
_dispatch_methodlist_nomethoderroravailable()
rethrow()
end
return nothing
end

@generated function _dispatch_methodlist(
dl::ReactionMethodDispatchList{M, V, C},
deltat::Float64,
) where {M, V, C}

# See https://discourse.julialang.org/t/manually-unroll-operations-with-objects-of-tuple/11604

ex = quote ; end # empty expression
for j=1:fieldcount(M)
for i=1:fieldcount(M)
push!(ex.args,
quote
# let
# call_method(dl.methods[$j][], dl.vardatas[$j][], dl.cellranges[$j], deltat)
# call_method(dl.methods[$i][], dl.vardatas[$i][], dl.cellranges[$i], deltat)
# pass Ref to function to reduce compile time
call_method(dl.methods[$j], dl.vardatas[$j], dl.cellranges[$j], deltat)
call_method(dl.methods[$i], dl.vardatas[$i], dl.cellranges[$i], deltat)
# end
end
)
Expand All @@ -828,22 +864,36 @@ end
return ex
end

@generated function dispatch_methodlist(
function dispatch_methodlist(
@nospecialize(dl::ReactionMethodDispatchList),
@nospecialize(pa::ParameterAggregator),
deltat::Float64=0.0
)
try
_dispatch_methodlist(dl, pa, deltat)
catch
_dispatch_methodlist_nomethoderroravailable()
rethrow()
end
return nothing
end

@generated function _dispatch_methodlist(
dl::ReactionMethodDispatchList{M, V, C},
pa::ParameterAggregator,
deltat::Float64=0.0
deltat::Float64
) where {M, V, C}

# See https://discourse.julialang.org/t/manually-unroll-operations-with-objects-of-tuple/11604

ex = quote ; end # empty expression
for j=1:fieldcount(M)
for i=1:fieldcount(M)
push!(ex.args,
quote
if has_modified_parameters(pa, dl.methods[$j])
call_method(dl.methods[$j], get_parameters(pa, dl.methods[$j]), dl.vardatas[$j], dl.cellranges[$j], deltat)
if has_modified_parameters(pa, dl.methods[$i])
call_method(dl.methods[$i], get_parameters(pa, dl.methods[$i]), dl.vardatas[$i], dl.cellranges[$i], deltat)
else
call_method(dl.methods[$j], dl.vardatas[$j], dl.cellranges[$j], deltat)
call_method(dl.methods[$i], dl.vardatas[$i], dl.cellranges[$i], deltat)
end
end
)
Expand All @@ -853,6 +903,11 @@ end
return ex
end

function _dispatch_methodlist_nomethoderroravailable()
@warn "dispatch_methodlist: a ReactionMethod failed. To get a more detailed error report "*
"including the YAML name of the failed Reaction, rerun with 'generated_dispatch=false' argument added to PALEOmodel.initialize!"
end

#################################
# Pretty printing
################################
Expand Down
26 changes: 16 additions & 10 deletions src/Reaction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -324,11 +324,13 @@ end
add_method_do!(@nospecialize(reaction::AbstractReaction), @nospecialize(methodfn::Function), @nospecialize(vars::Tuple{Vararg{AbstractVarList}}); kwargs...) =
_add_method!(reaction, methodfn, vars, add_method_do!; kwargs...)

default_preparefn(m, vardata) = vardata

function _add_method!(
@nospecialize(reaction::AbstractReaction), @nospecialize(methodfn::Function), @nospecialize(vars::Tuple{Vararg{AbstractVarList}}), add_method_fn;
name=string(methodfn),
p=nothing,
preparefn=(m, vardata) -> vardata,
preparefn=default_preparefn,
operatorID=reaction.operatorID,
domain=reaction.domain
)
Expand Down Expand Up @@ -611,15 +613,19 @@ function Base.show(io::IO, react::AbstractReaction)
end

function Base.show(io::IO, ::MIME"text/plain", react::AbstractReaction)
println(io, typename(react))
println(io, " name='", react.name, "'")
println(io, " classname='", react.classname, "'")
println(io, " domain='", domainname(react), "'")
println(io, " operatorID=", react.operatorID)
println(io, " parameters=", get_parameters(react))
println(io, " methods_setup=", react.methods_setup)
println(io, " methods_initialize=", react.methods_initialize)
println(io, " methods_do=", react.methods_do)
dump_reaction(io, react)
end

function dump_reaction(io::IO, react::AbstractReaction; prefix="", show_parameters::Bool=true)
println(io, prefix, typename(react))
println(io, prefix, " name='", react.name, "'")
println(io, prefix, " classname='", react.classname, "'")
println(io, prefix, " domain='", domainname(react), "'")
println(io, prefix, " operatorID=", react.operatorID)
show_parameters && println(io, prefix, " parameters=", get_parameters(react))
println(io, prefix, " methods_setup=", react.methods_setup)
println(io, prefix, " methods_initialize=", react.methods_initialize)
println(io, prefix, " methods_do=", react.methods_do)
end

"""
Expand Down
17 changes: 15 additions & 2 deletions src/ReactionMethod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ call_method_codefn(io::IO, codefn, method::ReactionMethod{M, R, P, 5}, vardata,

"""
get_variables_tuple(method::AbstractReactionMethod) -> (Vector{VariableReaction}, ...)

println(io, typename(react))
Get all [`VariableReaction`](@ref)s from `method` as a Tuple of `Vector{VariableReaction}`
"""
get_variables_tuple(@nospecialize(method::ReactionMethod); flatten=true) = Tuple(get_variables(vl; flatten) for vl in method.varlists)
Expand Down Expand Up @@ -209,7 +209,7 @@ get_rate_stoichiometry(@nospecialize(m::ReactionMethod)) = []
# Pretty printing
############################################

"compact form"
# compact form
function Base.show(io::IO, @nospecialize(method::ReactionMethod))
print(
io,
Expand All @@ -220,3 +220,16 @@ function Base.show(io::IO, @nospecialize(method::ReactionMethod))
")",
)
end

# multiline form
function Base.show(io::IO, ::MIME"text/plain", @nospecialize(method::ReactionMethod))
println(io, "ReactionMethod")
println(io, " fullname='", fullname(method), "'")
println(io, " methodfn=", string(method.methodfn))
println(io, " preparefn=", string(method.preparefn))
println(io, " domain='", method.domain.name , "'")
println(io, " operatorID=", method.operatorID, "'")

print(io, " reaction=")
dump_reaction(io, method.reaction; prefix=" ", show_parameters=false)
end
Loading