The area of a unit disk is $2\pi$? (NIntegrate over a numerical region)
According to the documentation of ToNumericalRegion
:
The region r should be a constant region for which ConstantRegionQ gives True.
However,
Needs["NDSolve`FEM`"]
inDisk[x_?NumericQ, y_?NumericQ] := x^2 + y^2 <= 1
r = ToNumericalRegion[ImplicitRegion[inDisk[x, y] == True, {{x, -1, 1}, {y, -1, 1}}]];
ConstantRegionQ @ r
False
so your region definition doesn't meet the requirements of ToNumericalRegion
.
The following works.
r = ImplicitRegion[x^2 + y^2 <= 1, {{x, -1, 1}, {y, -1, 1}}];
ConstantRegionQ @ r
True
Area @ r
π
NIntegrate[1, {x, y} ∈ r]
3.14159
I noticed that ContourPlot
does an awesome job discretizing the region. I don't know how this scales and how complicated your real problem is, but for the disk it works quite well:
ContourPlot
excludes complex numbers from the region by default, so a convenient way to plot the region is to set the function value to the imaginary unit if the point is outside the region. Then we can get the mesh by using DiscretizeGraphics
.
inDisk[x_?NumericQ, y_?NumericQ] := x^2 + y^2 <= 1;
mr = DiscretizeGraphics@
ContourPlot[
Piecewise[{{0, inDisk[x, y]}}, I], {x, -1, 1}, {y, -1, 1},
Mesh -> All, PlotPoints -> 15]
If we want we can simplify the mesh:
simplemr =
TriangulateMesh[mr, MaxCellMeasure -> Infinity,
PerformanceGoal -> "Speed"]
And then integrate over this region:
NIntegrate[1, {x, y} ∈ simplemr]
3.14027
Not perfect, but close.
Edit: A cleaner solution might be to use RegionFunction
instead of the imaginary unit, for example:
inDisk[x_?NumericQ, y_?NumericQ, f_] := x^2 + y^2 <= 1;
mr = BoundaryDiscretizeGraphics@
ContourPlot[0, {x, -1, 1}, {y, -1, 1}, PlotPoints -> 5,
MaxRecursion -> 6, RegionFunction -> inDisk];
NIntegrate[1, {x, y} ∈ mr]
3.14118
Note that I added an argument f
to inDisk
, because that's the form RegionFunction
expects. Also BoundaryDiscretizeGraphics
should suffice here. Larger values of MaxRecursion
can make the mesh region more accurate.
The circumference of a unit disk is 2π.
When you hide the internal of the function and the ==
is the only thing ImplicitRegion
does see it tries to construct a region with RegionDimension
1:
Needs["NDSolve`FEM`"]
inDisk[x_?NumericQ, y_?NumericQ] := x^2 + y^2 <= 1
nrDisk = ToNumericalRegion[
ImplicitRegion[inDisk[x, y] == True, {{x, -1, 1}, {y, -1, 1}}]];
2 Pi - NIntegrate[1, {x, y} \[Element] nrDisk]
0.00264963
What will work better in this case is to use:
mesh = ToElementMesh[
ImplicitRegion[
If[inDisk[x, y], 1, -1] > 0, {{x, -1, 1}, {y, -1, 1}}]];
Pi - NIntegrate[1, {x, y} \[Element] mesh]
7.120859435438831`*^-7
Note that since there is no symbolic region associated with the mesh it's not really necessary to put the mesh in a NumericalRegion
.
You can do this:
nr = ToNumericalRegion[
ImplicitRegion[
If[inDisk[x, y], 1, -1] > 0, {{x, -1, 1}, {y, -1, 1}}]];
ToElementMesh[nr]
Pi - NIntegrate[1, {x, y} \[Element] nr]
3.9561815157185265`*^-7
I'd need to look at why one needs to help NIntegrate
with the numerical region in this case by calling ToElementMesh
prior to calling NIntegrate
.
There is a suggestion that ImplicitRegion
should be able handle boolean region specifications better but that's out of my control so I can not say when and if this will come.