1
+ abstract type DebugMode end
2
+ struct NoDebug <: DebugMode end
3
+ struct VerboseDebug <: DebugMode end
4
+
5
+ DETAILED_INFORMATION = """
6
+ Note that detailed debugging information adds a small amount of overhead to SciML solves
7
+ which can be disabled with the keyword argument `debug = NoDebug()`.
8
+
9
+ The detailed original error message information from Julia reproduced below:
10
+ """
11
+
12
+ DEFAULT_DEBUG_MSG = """
13
+ Error detected inside of the run of the solver. For more detailed information about the error
14
+ with SciML context and recommendations, try adding the keyword argument `debug = VerboseDebug()`
15
+
16
+ $DETAILED_INFORMATION
17
+ """
18
+
19
+ UNKNOWN_MSG = """
20
+ An unclassified error occured during the solver process and SciML's `VerboseDebug` mode cannot give
21
+ any more information. You can help improve the debug mode messages by reporting this error to
22
+ https://github.com/SciML/SciMLBase.jl/issues with a reproducer of the error from which a high
23
+ level description can be added.
24
+
25
+ $DETAILED_INFORMATION
26
+ """
27
+
28
+ DOMAINERROR_COMPLEX_MSG = """
29
+ DomainError detected in the user `f` function. This occurs when the domain of a function is violated.
30
+ For example, `log(-1.0)` is undefined because `log` of a real number is defined to only output real
31
+ numbers, but `log` of a negative number is complex valued and therefore Julia throws a DomainError
32
+ by default. Cases to be aware of include:
33
+
34
+ * `log(x)`, `sqrt(x)`, `cbrt(x)`, etc. where `x<0`
35
+ * `x^y` for `x<0` floating point `y` (example: `(-1.0)^(1/2) == im`)
36
+
37
+ Within the context of SciML, this error can occur within the solver process even if the domain constriant
38
+ would not be violated in the solution due to adaptivity. For example, an ODE solver or optimization
39
+ routine may check a step at `new_u` which violates the domain constraint, and if violated reject the
40
+ step and use a smaller `dt`. However, the throwing of this error will have haulted the solving process.
41
+
42
+ Thus the recommended fix is to replace this function with the equivalent ones from NaNMath.jl
43
+ (https://github.com/JuliaMath/NaNMath.jl) which returns a NaN instead of an error. The solver will then
44
+ effectively use the NaN within the error control routines to reject the out of bounds step. Additionally,
45
+ one could perform a domain transformation on the variables so that such an issue does not occur in the
46
+ definition of `f`.
47
+
48
+ For more information, check out the following FAQ page:
49
+ https://docs.sciml.ai/Optimization/stable/API/FAQ/#The-Solver-Seems-to-Violate-Constraints-During-the-Optimization,-Causing-DomainErrors,-What-Can-I-Do-About-That?
50
+
51
+ $DETAILED_INFORMATION
52
+ """
53
+
54
+ struct VerboseDebugFunction{F}
55
+ f:: F
56
+ end
57
+ function (f:: VerboseDebugFunction )(args... )
58
+ try
59
+ f. f (args... )
60
+ catch e
61
+ if e isa DomainError && occursin (" will only return a complex result if called with a complex argument. Try " ,e. msg)
62
+ println (DOMAINERROR_COMPLEX_MSG)
63
+ else
64
+ println (UNKNOWN_MSG)
65
+ end
66
+ throw (e)
67
+ end
68
+ end
69
+
70
+ debugwrapfun (f,debug:: VerboseDebug ) = VerboseDebugFunction (f)
71
+ debugwrapfun (f,debug:: NoDebug ) = f
0 commit comments