-
Notifications
You must be signed in to change notification settings - Fork 4
Iterator api #3
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
base: main
Are you sure you want to change the base?
Iterator api #3
Changes from 7 commits
6608115
18eadb0
e0acfce
22ea4c5
d7016ef
e88960e
8054a5f
b946834
19982ef
3f6973e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
struct LinearSimplex{D, N, Tv} | ||
points::SVector{N, Point{D, Tv}} | ||
values::SVector{N, Tv} | ||
end | ||
|
||
values(s::LinearSimplex) = s.values | ||
points(s::LinearSimplex) = s.points | ||
|
||
|
||
function LinearSimplex(::Type{Val{D}}, points::Union{Vector, Tuple}, values::Union{Vector, Tuple}) where {D} | ||
spoints = SVector{D + 1, Point{D, Float32}}(points...) | ||
svalues = SVector{D + 1, Float32}(values...) | ||
return LinearSimplex(spoints, svalues) | ||
end | ||
|
||
function LinearSimplex(::Type{Val{1}}, points::AbstractMatrix, values::AbstractVector) | ||
@views spoints = SVector{2, Point{1, Float32}}(points[:, 1], points[:, 2]) | ||
svalues = SVector{2, Float32}(values[1], values[2]) | ||
return LinearSimplex(spoints, svalues) | ||
end | ||
|
||
function LinearSimplex(::Type{Val{2}}, points::AbstractMatrix, values::AbstractVector) | ||
@views spoints = SVector{3, Point{2, Float32}}(points[:, 1], points[:, 2], points[:, 3]) | ||
svalues = SVector{3, Float32}(values[1], values[2], values[3]) | ||
return LinearSimplex(spoints, svalues) | ||
end | ||
|
||
function LinearSimplex(::Type{Val{3}}, points::AbstractMatrix, values::AbstractVector) | ||
@views spoints = SVector{4, Point{3, Float32}}(points[:, 1], points[:, 2], points[:, 3], points[:, 4]) | ||
svalues = SVector{4, Float32}(values[1], values[2], values[3], values[4]) | ||
return LinearSimplex(spoints, svalues) | ||
end | ||
|
||
|
||
function LinearSimplex(::Type{Val{1}}, points::AbstractMatrix, values::AbstractVector, coordscale) | ||
@views spoints = SVector{2, Point{1, Float32}}(points[:, 1] * coordscale, points[:, 2] * coordscale) | ||
svalues = SVector{2, Float32}(values[1], values[2]) | ||
return LinearSimplex(spoints, svalues) | ||
end | ||
|
||
function LinearSimplex(::Type{Val{2}}, points::AbstractMatrix, values::AbstractVector, coordscale) | ||
@views spoints = SVector{3, Point{2, Float32}}(points[:, 1] * coordscale, points[:, 2] * coordscale, points[:, 3] * coordscale) | ||
svalues = SVector{3, Float32}(values[1], values[2], values[3]) | ||
return LinearSimplex(spoints, svalues) | ||
end | ||
|
||
function LinearSimplex(::Type{Val{3}}, points::AbstractMatrix, values::AbstractVector, coordscale) | ||
@views spoints = SVector{4, Point{3, Float32}}(points[:, 1] * coordscale, points[:, 2] * coordscale, points[:, 3] * coordscale, points[:, 4] * coordscale) | ||
svalues = SVector{4, Float32}(values[1], values[2], values[3], values[4]) | ||
return LinearSimplex(spoints, svalues) | ||
end | ||
|
||
LinearEdge(points, values) = LinearSimplex(Val{1}, points, values) | ||
LinearTriangle(points, values) = LinearSimplex(Val{2}, points, values) | ||
LinearTetrahedron(points, values) = LinearSimplex(Val{3}, points, values) | ||
|
||
|
||
""" | ||
abstract type LinearSimplexIterator{D} | ||
|
||
Iterator over D-dimensional linear simplices. | ||
|
||
Any subtype `TSub` should comply with the [iteration interface](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration) | ||
and implement | ||
```julia | ||
Base.iterate(vs::TSub{D}, state):: (LinearSimplex{D}, state) where D | ||
``` | ||
The optional methods (in particular, size, length) are not needed. | ||
""" | ||
abstract type LinearSimplexIterator{D} end | ||
|
||
""" | ||
testloop(iterators::AbstractVector{T}) where T<:LinearSimplexIterator | ||
|
||
Sum up all values passed via the iterator. Designed for testing iterators. | ||
|
||
Useful for: | ||
- Consistency test - e.g. when passing constant ones, the sum can be calculated by | ||
other means and compared to the return value of testloop | ||
- Allocation test. `testloop` itself does allocate only a few (<1000) bytes in | ||
very few (<10) allocations. So any allocations beyond this from a | ||
call to `testloop` hint at possibilities to improve an iterator implementation. | ||
""" | ||
function testloop(iterators::AbstractVector{T}) where {T <: LinearSimplexIterator} | ||
threads = map(iterators) do iterator | ||
begin | ||
local x = 0.0 | ||
for vt in iterator | ||
x += sum(vt.values) | ||
end | ||
x | ||
end | ||
end | ||
return sum(fetch.(threads)) | ||
end |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -61,7 +61,7 @@ end | |||||
This method can be used both for the evaluation of plane sections and for | ||||||
the evaluation of function isosurfaces. | ||||||
""" | ||||||
function calculate_plane_tetrahedron_intersection!( | ||||||
function calculatCe_plane_tetrahedron_intersection!( | ||||||
ixcoord, | ||||||
ixvalues, | ||||||
coordinates, | ||||||
|
@@ -78,7 +78,6 @@ function calculate_plane_tetrahedron_intersection!( | |||||
) | ||||||
return 0 | ||||||
end | ||||||
|
||||||
amount_intersections = 0 | ||||||
|
||||||
@inbounds for n1 in 1:4 | ||||||
|
@@ -233,7 +232,7 @@ function marching_tetrahedra( | |||||
|
||||||
function pushtris(ns, ixcoord, ixvalues) | ||||||
# number of intersection points can be 3 or 4 | ||||||
if ns >= 3 | ||||||
return if ns >= 3 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This early return inverts the original logic by skipping valid cases when
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
last_i = length(all_ixvalues) | ||||||
for is in 1:ns | ||||||
@views push!(all_ixcoord, ixcoord[:, is]) | ||||||
|
@@ -356,7 +355,6 @@ function marching_triangles( | |||||
points = Vector{Tp}(undef, 0) | ||||||
values = Vector{Tv}(undef, 0) | ||||||
adjacencies = Vector{SVector{2, Ti}}(undef, 0) | ||||||
|
||||||
for igrid in 1:length(coords) | ||||||
func = funcs[igrid] | ||||||
coord = coords[igrid] | ||||||
|
@@ -416,7 +414,6 @@ function marching_triangles( | |||||
# connect last two points | ||||||
push!(adjacencies, SVector{2, Ti}((length(points) - 1, length(points)))) | ||||||
end | ||||||
|
||||||
return | ||||||
end | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,64 @@ | ||||||||||||||||||||||||||||||
function pushintersection!(intersection_points, triangle::LinearSimplex{2}, levels) | ||||||||||||||||||||||||||||||
f = values(triangle) | ||||||||||||||||||||||||||||||
coord = points(triangle) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
(n1, n2, n3) = (1, 2, 3) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
f[1] <= f[2] ? (n1, n2) = (1, 2) : (n1, n2) = (2, 1) | ||||||||||||||||||||||||||||||
f[n2] <= f[3] ? n3 = 3 : (n2, n3) = (3, n2) | ||||||||||||||||||||||||||||||
f[n1] > f[n2] ? (n1, n2) = (n2, n1) : nothing | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
dx31 = coord[n3][1] - coord[n1][1] | ||||||||||||||||||||||||||||||
dx21 = coord[n2][1] - coord[n1][1] | ||||||||||||||||||||||||||||||
dx32 = coord[n3][1] - coord[n2][1] | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
dy31 = coord[n3][2] - coord[n1][2] | ||||||||||||||||||||||||||||||
dy21 = coord[n2][2] - coord[n1][2] | ||||||||||||||||||||||||||||||
dy32 = coord[n3][2] - coord[n2][2] | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
df31 = f[n3] != f[n1] ? 1 / (f[n3] - f[n1]) : 0.0 | ||||||||||||||||||||||||||||||
df21 = f[n2] != f[n1] ? 1 / (f[n2] - f[n1]) : 0.0 | ||||||||||||||||||||||||||||||
df32 = f[n3] != f[n2] ? 1 / (f[n3] - f[n2]) : 0.0 | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
for level in levels | ||||||||||||||||||||||||||||||
if (f[n1] <= level) && (level < f[n3]) | ||||||||||||||||||||||||||||||
α = (level - f[n1]) * df31 | ||||||||||||||||||||||||||||||
x1 = coord[n1][1] + α * dx31 | ||||||||||||||||||||||||||||||
y1 = coord[n1][2] + α * dy31 | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
if (level < f[n2]) | ||||||||||||||||||||||||||||||
α = (level - f[n1]) * df21 | ||||||||||||||||||||||||||||||
x2 = coord[n1][1] + α * dx21 | ||||||||||||||||||||||||||||||
y2 = coord[n1][2] + α * dy21 | ||||||||||||||||||||||||||||||
else | ||||||||||||||||||||||||||||||
α = (level - f[n2]) * df32 | ||||||||||||||||||||||||||||||
x2 = coord[n2][1] + α * dx32 | ||||||||||||||||||||||||||||||
y2 = coord[n2][2] + α * dy32 | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
push!(intersection_points, Point{2, Float32}(x1, y1)) | ||||||||||||||||||||||||||||||
push!(intersection_points, Point{2, Float32}(x2, y2)) | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
function intersections(triangles::T, levels) where {T <: LinearSimplexIterator{2}} | ||||||||||||||||||||||||||||||
local intersection_points = Vector{Point{2, Float32}}(undef, 0) | ||||||||||||||||||||||||||||||
for triangle in triangles | ||||||||||||||||||||||||||||||
pushintersection!(intersection_points, triangle, levels) | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
return intersection_points | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
function marching_triangles(triangle_iterators::Vector{T}, levels) where {T <: LinearSimplexIterator{2}} | ||||||||||||||||||||||||||||||
return if Threads.nthreads() == 1 | ||||||||||||||||||||||||||||||
map(triangle_iterators) do triangles | ||||||||||||||||||||||||||||||
intersections(triangles, levels) | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
else | ||||||||||||||||||||||||||||||
threads = map(triangle_iterators) do triangles | ||||||||||||||||||||||||||||||
Threads.@spawn intersections(triangles, levels) | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
Comment on lines
+55
to
+61
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The call to
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback
Comment on lines
+59
to
+61
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same issue with argument ordering in threads = map(triangles -> Threads.@spawn intersections(triangles, levels), triangle_iterators)
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||||||||||
fetch.(threads) | ||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||
end |
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.
[nitpick] There's a TODO-style comment suggesting a future replacement of this import. Consider addressing or removing this to avoid lingering technical debt.
Copilot uses AI. Check for mistakes.