This was not closed as being unreproducible, so I've decided to answer it, since I think this method may be useful to some. I can adapt something I wrote for other purposes to address the outcome desired by the OP. I had occasion to write an extended version of NIntegrateProfile
found in Needs["Integration`NIntegrateUtilities`"]
(see, for example, the tutorial NIntegrate Integration Strategies).
I adapted the Internal`AddHandler
solution of Szabolcs to
How to abort on any message generated? to capture the error estimate of NIntegrate
. I think it might be of general interest, so I will include it as well as adapt it to the OP's situation; it may also be helpful in the OP's case, depending on what exactly is desired.
It only catches the error estimate when NIntegrate::ncvb
is produced, so it is not a (complete) solution to Obtaining an NIntegrate error estimate.
Hooking the NIntegrate::ncvb
message. As shown by Szabolcs', we can use Internal`AddHandler
to capture the parameters passed to Message
. In the case of NIntegrate::ncvb
, some of the arguments are wrapped in HoldForm
. I do not recall the numeric parameters (e.g., the integral estimate) ever not being numeric, so I released the hold. The potential for an evaluation leak might be introduced by this.
ClearAll[sowMessageData];
sowMessageData[
Hold[Message[NIntegrate::ncvb, recur_, rvar_, vars_, vars0_, integral_, error_], _]] :=
Sow[{"ErrorEstimate" -> ReleaseHold@error,
"PossibleSingularity" -> Thread[Map[HoldPattern, vars, {2}] -> vars0 // ReleaseHold]},
sowNIntegrateData];
ClearAll[nintegrateProfile];
SetAttributes[nintegrateProfile, HoldAll];
nintegrateProfile[NIntegrate[args__]] :=
Module[{evaluations = 0},
Internal`WithLocalSettings[
Internal`AddHandler["Message", sowMessageData],
Flatten[{
Reap[Thread[{"Timing", "IntegralEstimate"} ->
AbsoluteTiming@ NIntegrate[args, EvaluationMonitor :> evaluations++]]],
"Evaluations" -> evaluations}],
Internal`RemoveHandler["Message", sowMessageData]
]]
nintegrateProfile[NIntegrate[1/x, {x, -0.5, 1}]]
nintegrateProfile[NIntegrate[1/x, {x, 0.5, 1}]]
NIntegrate::slwcon: Numerical integration converging too slowly; suspect one of the following: singularity, value of the integration is 0, highly oscillatory integrand, or WorkingPrecision too small. >>
NIntegrate::ncvb: NIntegrate failed to converge to prescribed accuracy after 9 recursive bisections in x near {x} = {0.00095325}. NIntegrate obtained -3.67657 and 5.363161650917478` for the integral and error estimates. >>
(*
{"Timing" -> 0.088606, "IntegralEstimate" -> -3.67657,
"ErrorEstimate" -> 5.36316, "PossibleSingularity" -> {HoldPattern[x] -> 0.00095325},
"Evaluations" -> 209}
{"Timing" -> 0.002897, "IntegralEstimate" -> 0.693147, "Evaluations" -> 11}
*)
The OP's goals. The first goal mentioned by the OP is to return 0
in case of NIntegrate::ncvb
. That's straightforward:
ClearAll[returnZeroOnNonconvergence];
returnZeroOnNonconvergence[
Hold[Message[NIntegrate::ncvb, recur_, rvar_, vars_, vars0_, integral_, error_], _]] :=
Return[0, NIntegrate];
Internal`WithLocalSettings[
Internal`AddHandler["Message", returnZeroOnNonconvergence],
NIntegrate[1/x, {x, -0.5, 1}],
Internal`RemoveHandler["Message", returnZeroOnNonconvergence]
]
NIntegrate::slwcon: Numerical integration converging too slowly; suspect one of the following: singularity, value of the integration is 0, highly oscillatory integrand, or WorkingPrecision too small. >>
NIntegrate::ncvb: NIntegrate failed to converge to prescribed accuracy after 9 recursive bisections in x near {x} = {0.00095325}. NIntegrate obtained -3.67657 and 5.363161650917478` for the integral and error estimates. >>
(* 0 *)
I'm a little confused by the OP's request to be able to "extract the last obtained value," because that is the value returned by NIntegrate
. In any case, the value is the argument integral
to sowMessageData
and maybe returned in whatever way desired (e.g. Return[{0, integral}, NIntegrate]
). And my first example nintegrateProfile
can be adapted to return all of the parameters, if desired.
Quiet[Check[ NIntegrate[Sin[x], {x, 0, 10000}, Method -> { Automatic, "SymbolicProcessing" -> False}] , "invalid"] ]
. Its pretty much what you say you tried though.. $\endgroup$$MessagePrePrint
for extracting the numbers.. they are often garbage though so I'm not sure thats a worthwhile thing to do. $\endgroup$K
is used the by system (see?K
). $\endgroup$