-
Notifications
You must be signed in to change notification settings - Fork 94
Add integrals over geometries #1333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
+496
−0
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
23eb0c9
Copy files from #1327
juliohm 6462530
Minor adjustments
juliohm 1aee514
Update tests
juliohm 2e21ddd
Update tests
juliohm dcca36f
Update default method
juliohm b0db2fb
Add tests
juliohm ac591d5
Add tests
juliohm ee1a535
Fix integrand
juliohm 963a8db
Update tests
juliohm 9f279a9
add IntegrationInterface.jl to [sources]
JoshuaLampert 2b12c72
most tests not broken anymore
JoshuaLampert 1e0e2cc
test for plane passes with rtol = 1e-3
JoshuaLampert 1b36eb3
Decompose Rope and Ring into Segment parts
juliohm ae368df
update to new integral interface
JoshuaLampert ca6c7ba
Strip units from integrand to help backends
juliohm bee5449
Undo strip units
juliohm 3aef841
Use HAdaptiveIntegration
juliohm f92ac2d
Minor refactor
juliohm b2f0e75
Update tests
juliohm 16cb6e6
Update tests
juliohm f338476
Use rtol in HAdaptiveIntegration backend
juliohm 7c60696
Uncomment test with PolyArea
juliohm f4ed9ff
remove sources section again
JoshuaLampert aeb5ae0
format
JoshuaLampert File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| # ------------------------------------------------------------------ | ||
| # Licensed under the MIT License. See LICENSE in the project root. | ||
| # ------------------------------------------------------------------ | ||
|
|
||
| # default integration method | ||
| const HADAPTIVE = II.Backend.HAdaptiveIntegration(rtol=1e-3) | ||
|
|
||
| """ | ||
| integral(fun, geom[, method]) | ||
|
|
||
| Calculate the integral over the `geom`etry of the `fun`ction that maps | ||
| [`Point`](@ref)s to values in a linear space. | ||
|
|
||
| integral(fun, dom[, method]) | ||
|
|
||
| Alternatively, calculate the integral over the `dom`ain (e.g., mesh) by | ||
| summing the integrals for each constituent geometry. | ||
|
|
||
| By default, use h-adaptive integration for good accuracy on a wide range of geometries. | ||
|
|
||
| See also [`localintegral`](@ref). | ||
| """ | ||
| integral(fun, geom::Geometry, method=HADAPTIVE) = _integral(fun, geom, method) | ||
|
|
||
| # cylinder surface is the union of the curved surface and the top and bottom disks | ||
| integral(fun, cylsurf::CylinderSurface, method=HADAPTIVE) = | ||
| localintegral(fun ∘ cylsurf, cylsurf, method) + | ||
| integral(fun, top(cylsurf), method) + | ||
| integral(fun, bottom(cylsurf), method) | ||
|
|
||
| # cone surface is the union of the curved surface and the base disk | ||
| integral(fun, conesurf::ConeSurface, method=HADAPTIVE) = | ||
| localintegral(fun ∘ conesurf, conesurf, method) + integral(fun, base(conesurf), method) | ||
|
|
||
| # frustum surface is the union of the curved surface and the top and bottom disks | ||
| integral(fun, frustumsurf::FrustumSurface, method=HADAPTIVE) = | ||
| localintegral(fun ∘ frustumsurf, frustumsurf, method) + | ||
| integral(fun, top(frustumsurf), method) + | ||
| integral(fun, bottom(frustumsurf), method) | ||
|
|
||
| # rope is the union of its constituent segments | ||
| integral(fun, rope::Rope, method=HADAPTIVE) = sum(integral(fun, seg, method) for seg in segments(rope)) | ||
|
|
||
| # ring is the union of its constituent segments | ||
| integral(fun, ring::Ring, method=HADAPTIVE) = sum(integral(fun, seg, method) for seg in segments(ring)) | ||
|
|
||
| # polygon is the union of its constituent ngons | ||
| integral(fun, poly::Polygon, method=HADAPTIVE) = sum(integral(fun, ngon, method) for ngon in discretize(poly)) | ||
|
|
||
| # integrate triangles with local integration | ||
| integral(fun, tri::Triangle, method=HADAPTIVE) = _integral(fun, tri, method) | ||
|
|
||
| # integrate quadrangle with local integration | ||
| integral(fun, quad::Quadrangle, method=HADAPTIVE) = _integral(fun, quad, method) | ||
JoshuaLampert marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # multi-geometry is the union of its constituent geometries | ||
| integral(fun, multi::Multi, method=HADAPTIVE) = sum(integral(fun, geom, method) for geom in parent(multi)) | ||
|
|
||
| # domain is the union of its constituent geometries | ||
| integral(fun, dom::Domain, method=HADAPTIVE) = sum(integral(fun, geom, method) for geom in dom) | ||
|
|
||
| # fallback to local integration of fun ∘ geom | ||
| _integral(fun, geom, method) = localintegral(fun ∘ geom, geom, method) | ||
|
|
||
| """ | ||
| localintegral(fun, geom[, method]) | ||
|
|
||
| Calculate the integral over the `geom`etry of the `fun`ction that maps | ||
| parametric coordinates `uvw` to values in a linear space. | ||
|
|
||
| By default, use h-adaptive integration for good accuracy on a wide range of geometries. | ||
|
|
||
| See also [`integral`](@ref). | ||
| """ | ||
| function localintegral(fun, geom::Geometry, method=HADAPTIVE) | ||
| # integrand is equal to function times differential element | ||
| integrand(uvw...) = fun(uvw...) * differential(geom, uvw) | ||
JoshuaLampert marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # domain of integration for the given geometry | ||
| domain = ∫domain(geom) | ||
|
|
||
| # extract units of integral by assuming | ||
| # integrand can be evaluated at zeros | ||
| N = paramdim(geom) | ||
| T = numtype(lentype(geom)) | ||
| o = ntuple(_ -> zero(T), N) | ||
| u = unit.(integrand(o...)) | ||
|
|
||
| # strip units to help integration backends | ||
| f(uvw...) = ustrip.(integrand(uvw...)) | ||
|
|
||
| # perform numerical integration | ||
| II.integral(f, domain; backend=method) .* u | ||
| end | ||
|
|
||
| function ∫domain(geom::Geometry) | ||
| N = paramdim(geom) | ||
| T = numtype(lentype(geom)) | ||
| a = ntuple(_ -> zero(T), N) | ||
| b = ntuple(_ -> one(T), N) | ||
| II.Domain.Box(a, b) | ||
| end | ||
|
|
||
| function ∫domain(ray::Ray) | ||
| T = numtype(lentype(ray)) | ||
| a = (zero(T),) | ||
| b = (II.Infinity(one(T)),) | ||
| II.Domain.Box(a, b) | ||
| end | ||
|
|
||
| function ∫domain(line::Line) | ||
| T = numtype(lentype(line)) | ||
| a = (-II.Infinity(one(T)),) | ||
| b = (II.Infinity(one(T)),) | ||
| II.Domain.Box(a, b) | ||
| end | ||
|
|
||
| function ∫domain(plane::Plane) | ||
| T = numtype(lentype(plane)) | ||
| a = (-II.Infinity(one(T)), -II.Infinity(one(T))) | ||
| b = (II.Infinity(one(T)), II.Infinity(one(T))) | ||
| II.Domain.Box(a, b) | ||
| end | ||
|
|
||
| function ∫domain(tri::Triangle) | ||
| T = numtype(lentype(tri)) | ||
| a = (zero(T), zero(T)) | ||
| b = (one(T), zero(T)) | ||
| c = (zero(T), one(T)) | ||
| II.Domain.Simplex(a, b, c) | ||
| end | ||
|
|
||
| function ∫domain(tetra::Tetrahedron) | ||
| T = numtype(lentype(tetra)) | ||
| a = (zero(T), zero(T), zero(T)) | ||
| b = (one(T), zero(T), zero(T)) | ||
| c = (zero(T), one(T), zero(T)) | ||
| d = (zero(T), zero(T), one(T)) | ||
| II.Domain.Simplex(a, b, c, d) | ||
| end | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering whether it makes sense to make
rtoldepending on the floating point type. The default for this issqrt(eps(T)), which evaluates to1.4901161193847656e-8forFloat64and to0.00034526698f0forFloat32. So setting this always to1e-3means we loose quite some accuracy for theFloat64case. Maybe it would be more sensible to use something like10 * sqrt(eps(T))(sincesqrt(eps(T))was too small), which forFloat32is close to1e-3, but gives us more accuracy for theFloat64case. We can also add that in another PR though because I think we wanted to touch the default anyway and make it a function depending on the geometry, right?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I played with
atol=Meshes.atol(numtype(eltype(geom)))in the II.jl backend, but forgot to play withrtoltoo. We could investigate this issue in a separate PR to avoid delaying the progress 👍🏽