Here areHere's a couple fully generic waysway with region functions. I'm not sure which is best yetImplicitRegion
.
First, we might want to simply use scaled
, or we might instead want to convert to a BoundaryMeshRegion
via
Second(As we'll see, we might wantthis seems to use InverseTransformedRegion[
$reg,f,n$]
, which gives the region $\{p \in \mathbb{R}^n \mid f(p) \in reg\}$—in other words, exactly what you want, minus the bounds restrictions!improve performance.)
OrSecond, with surface
being your function of $u$ and $v$, we might want to use ImplicitRegion[surface[u,v] \[Element] reg, {{u, 0, 2}, {v, 0, 2}}]
.
(There is also InverseTransformedRegion[
$reg,f,n$]
instead of ImplicitRegion
, which gives the region $\{p \in \mathbb{R}^n \mid f(p) \in reg\}$—in other words, exactly what you want, minus the bounds restrictions! However, as we'll see, there are computational problems with this option.)
Finally, if we discretize the result, we might want to discretize it via DsicretizeRegionDiscretizeRegion
or via BoundaryDiscretizeRegion
. I'm not sure which is best.
Though, that part might depend on your application: if you don't need to discretize the resulting region, don't. Discretization of these regions takes a lot ofsome time! The first one to return (DiscretizeRegion[uvImplicit]
; see below) takes between 3 and 4 minutes on my laptop, depending on whether I'm connectedYou might be able to poweruse the region numerically even without discretizing it. A lot ofsome functions will work directly (and numerically) with the returned InverseTransformedRegion
or ImplicitRegion
anyway, so you might not need to discretize at all. However, if you're going to be doing a lot of different things with it, and if those computations are a bit slow, you might get better performance overall by discretizing from the outset.
I wrote a test to time all the different combinations. Here's:
scaled
vs.bscaled
ImplicitRegion
vs.InverseTransformedRegion
DiscretizeRegion
vs.BoundaryDiscretizeRegion
.
The best was BoundaryDiscretizeRegion
on an ImplicitRegion
that testreferred to bscaled
, plus allwhich clocked in at around 44 seconds.
(* Best performance: *)
surface[u_, v_] := {(u^2 + v^2)/3, (u^2 - v^2)/3}
bscaled = BoundaryDiscretizeRegion[scaled];
BoundaryDiscretizeRegion[
ImplicitRegion[surface[u, v] \[Element] bscaled,
{{u, 0, 2}, {v, 0, 2}}]
]
Contrast with using scaled
instead, which took almost 3 minutes. It performed about the codesame as using DiscretizeRegion
on the outer level, but since BoundaryDiscretizeRegion
seems to work better as an input, you might want to use BoundaryDiscretizeRegion
anyway.
When I tried to discretize InverseTransformedRegion
, it made my CPU temperature shoot up to 100ºC and wasn't any quicker. So if you're going to discretize it, I would recommend using ImplicitRegion
instead of InverseTransformedRegion
. However, there's always the chance that it will perform better with other operations; it all depends on how you'll be using this.
Maybe someone can suggest good option values for BoundaryDiscretizeRegion
or DiscretizeRegion
that would speed things up, or a tweak to this approach. I do think that an approach like this at least has the advantage of giving you "the right kind of thing" as a result—namely, a region. But I'm sure there are improvements that can be made.
For reference, here's the test I used. I wound up evaluating some individually when I wanted to skip some. I don't recommend running the test.
ClearAll[scaled, bscaled, method, reg, surface, uvImplicit, uvInverseTransformed, inputregiontype]
scaled =
TransformedRegion[
RegionResize[
DiscretizeRegion[
GeoGridPosition[Entity["Country", "Portugal"]["Polygon"],
"Mercator"]], 1/2], TranslationTransform[{9.5, -43.4}]];
bscaled = BoundaryDiscretizeRegion[scaled];
surface[u_, v_] := {(u^2 + v^2)/3, (u^2 - v^2)/3}
(* Example of both methods, here using scaled instead of bscaled *)
uvImplicit = ImplicitRegion[surface[u, v] \[Element] scaledbscaled, {{u, 0, 2}, {v, 0, 2}}]
uvInverseTransformed = InverseTransformedRegion[scaledInverseTransformedRegion[bscaled, surface, 2]
(* Discretization test: *)
method["Implicit"] = ImplicitRegion[surface[u, v] \[Element] #1, {{u, 0, 2}, {v, 0, 2}}] &;
method["InverseTransformed"] = InverseTransformedRegion[#1, surface, 2] &;
inputregiontype["Mesh"] = scaled;
inputregiontype["BoundaryMesh"] = bscaled;
Table[
Echo@AbsoluteTiming[{ (* Label: *) {disc, m, reg},
(* Output: *) disc[method[m][inputregiontype[reg]]]}
],
{discm, {DiscretizeRegion, BoundaryDiscretizeRegion}},
{reg, {"Mesh""Implicit", "BoundaryMesh""InverseTransformed"}},
{mdisc, {"Implicit"DiscretizeRegion, "InverseTransformed"BoundaryDiscretizeRegion}}
]
I'll keep you updated as these return...but in the meantime, maybe someone can suggest good option values for DiscretizeRegion
that would speed things up, or a tweak to these approaches. I do think that an approach like this at least has the advantage of giving you "the right kind of thing" as a result—namely, a region. But I'm sure there are improvements that can be made.
So far, DiscretizeRegion[method["Implicit"][inputregiontype["BoundaryMesh"]]]
, i.e.
DiscretizeRegion[ImplicitRegion[surface[u, v] \[Element] bscaled,
{{u, 0reg, 2}, {v, 0"Mesh", 2"BoundaryMesh"}}
]
is in the lead at just under 44 seconds.