# How to improve accuracy of NIntegrate over ImplicitRegion

I'm trying to compute the area of a implicit region given as

R = ImplicitRegion[
0 < Sinh[u]/Cosh[v] < 1 && 0 < Sinh[v]/Cosh[u] < 1,
{{u, 0, Infinity}, {v, 0, Infinity}}
]


The region looks like this:

RegionPlot[
0 < Sinh[u]/Cosh[v] < 1 && 0 < Sinh[v]/Cosh[u] < 1,
{u, 0, 2}, {v, 0, 2}
]


I used NIntegrate (Mathematica 10.4) like this:

NIntegrate[1, Element[{u, v}, R]]
(* Out: 0.884886 *)


However I happen to know that the correct answer should be $\pi^2/8 = 1.2337$.

I'm reading the documentation for NIntegrate, but I'm quite overwhelmed by the amount of possible options. How can I improve the result of NIntegrate in this case?

You can first discretize the region as follows:

reg = DiscretizeRegion[
ImplicitRegion[0 < Sinh[u]/Cosh[v] < 1 && 0 < Sinh[v]/Cosh[u] < 1,
{{u, 0, 3}, {v, 0, 3}}]];


Now NIntegrate gives us better values:

NIntegrate[1, Element[{u, v}, reg]]


1.23371

I don't know why putting Infinity as the limits give terrible results.

• The result gets even better when I don't use MaxCellMeasure (1.23356). But strangely it get's worse again when I increase the bounds from 3 to 4 (1.24179) or even higher. Apr 17 '16 at 21:37
• @asmaier. That's interesting. Clearly a bug somewhere. I'll include that observation. Apr 17 '16 at 22:15

Some of what is going on is that the region is numericized to the extent that the precision of the numbers in R is set to 7.. Then NIintegrate discretizes the region with

dR = DiscretizeRegion[
ImplicitRegion[
0 < Sech[v] Sinh[u] < 1.000000 && 0 < Sech[u] Sinh[v] < 1.000000 &&
u >= 0 && v >= 0, {u, v}], PrecisionGoal -> 7.,
AccuracyGoal -> ∞]


The difficulty arises with computing the region bounds:

RegionBounds@
ImplicitRegion[
0 < Sech[v] Sinh[u] < 1.7. && 0 < Sech[u] Sinh[v] < 1.7. &&
u >= 0 && v >= 0, {u, v}]
(*  {{0, 0.9896590}, {0.00001562203, 0.9594784}}  *)


Well, there would be a problem in computing the bounds, since the region is infinite, but it's not clear why these numbers are found. In any case, it is the region that is integrated over:

NIntegrate[1, Element[{u, v}, dR]]
Area@dR
(*
0.884886
0.884886
*)


One can do better by truncating at explicit bounds, like @RunnyKine does:

dR2 = DiscretizeRegion[
ImplicitRegion[
0 < Sech[v] Sinh[u] < 1.7. && 0 < Sech[u] Sinh[v] < 1.7. &&
u >= 0 && v >= 0, {u, v}],
{{0, 6}, {0, 6}},
PrecisionGoal -> 7., AccuracyGoal -> ∞]
NIntegrate[1, Element[{u, v}, dR2]]
(*  1.23365  *)


In general, I would say that discretizing the region introduces errors at the boundary that can have a significant impact. (It's basically a trapezoidal-rule approximation.) One might consider a change of variables, if a suitable one can be found, to a region with finite bounds. One can also revert to the old-style way of dealing with integrating over a region, Boole:

NIntegrate[
Boole[0 < Sech[v] Sinh[u] < 1 && 0 < Sech[u] Sinh[v] < 1 && u >= 0 &&
v >= 0], {u, 0, Infinity}, {v, 0, Infinity}]
(*  1.2337  *)


Note that this does not work as well:

NIntegrate[Boole[RegionMember[R, {u, v}]], {u, 0, Infinity}, {v, 0, Infinity}]


NIntegrate::slwcon: Numerical integration converging too slowly...

NIntegrate::eincr: The global error of the strategy GlobalAdaptive has increased...

(*  1.07879  *)


It seems to have something to do with the (u | v) ∈ Reals added by RegionMember:

RegionMember[R, {u, v}]
(*
(u | v) ∈ Reals && 0 < Sech[v] Sinh[u] < 1 &&
0 < Sech[u] Sinh[v] < 1 && u >= 0 && v >= 0
*)


It must throw off NIntegrate`'s symbolic preprocessor.