From a195d340591eeb0b7e638ba198197d7cde2abf36 Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 15:23:30 -0300 Subject: [PATCH 01/13] Add support por predicates in 'TriRefinement' --- src/refinement/tri.jl | 62 ++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index 235f09c69..f412d27b5 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -7,10 +7,19 @@ Refinement of polygonal meshes into triangles. A n-gon is subdivided into n triangles. + + TriRefinement(pred) + +Refine only the elements of the mesh where +`pred(element)` returns `true`. """ -struct TriRefinement <: RefinementMethod end +struct TriRefinement{F} <: RefinementMethod + pred::F +end + +TriRefinement() = TriRefinement(_ -> true) -function refine(mesh, ::TriRefinement) +function refine(mesh, method::TriRefinement) assertion(paramdim(mesh) == 2, "TriRefinement only defined for surface meshes") (eltype(mesh) <: Triangle) || return simplexify(mesh) @@ -21,33 +30,36 @@ function refine(mesh, ::TriRefinement) # convert to half-edge structure t = convert(HalfEdgeTopology, connec) - # add centroids of elements + # used to extract the vertex indices ∂₂₀ = Boundary{2,0}(t) - epts = map(1:nelements(t)) do elem - is = ∂₂₀(elem) - cₒ = sum(i -> to(points[i]), is) / length(is) - withcrs(mesh, cₒ) - end - - # original vertices - vpts = points - # new points in refined mesh - newpoints = [vpts; epts] + # offset to new vertex indices + offset = length(points) - offset = length(vpts) - - # connect vertices into new triangles + # add centroids of elements and connect vertices + # into new triangles if necessary + newpoints = copy(points) newconnec = Connectivity{Triangle,3}[] - for elem in 1:nelements(t) - verts = ∂₂₀(elem) - nv = length(verts) - for i in 1:nv - u = elem + offset - v = verts[mod1(i, nv)] - w = verts[mod1(i + 1, nv)] - tri = connect((u, v, w)) - push!(newconnec, tri) + for eᵢ in 1:nelements(t) + elem = element(mesh, eᵢ) + # check if the element should be refined + if method.pred(elem) + # add new centroid vertex + push!(newpoints, centroid(elem)) + + # add new connectivities + verts = ∂₂₀(eᵢ) + nv = length(verts) + for i in 1:nv + u = eᵢ + offset + v = verts[mod1(i, nv)] + w = verts[mod1(i + 1, nv)] + tri = connect((u, v, w)) + push!(newconnec, tri) + end + else + # otherwise, just use the original connectivity + push!(newconnec, element(t, eᵢ)) end end From ad2eacf48e84e97ebff38c90abba7bbb801f2b60 Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 15:44:04 -0300 Subject: [PATCH 02/13] Apply suggestions --- src/refinement/tri.jl | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index f412d27b5..559cd6bfd 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -17,7 +17,7 @@ struct TriRefinement{F} <: RefinementMethod pred::F end -TriRefinement() = TriRefinement(_ -> true) +TriRefinement() = TriRefinement(nothing) function refine(mesh, method::TriRefinement) assertion(paramdim(mesh) == 2, "TriRefinement only defined for surface meshes") @@ -36,20 +36,29 @@ function refine(mesh, method::TriRefinement) # offset to new vertex indices offset = length(points) + # predicate function + pred = if isnothing(method.pred) + _ -> true + else + eᵢ -> method.pred(element(mesh, eᵢ)) + end + # add centroids of elements and connect vertices # into new triangles if necessary newpoints = copy(points) newconnec = Connectivity{Triangle,3}[] for eᵢ in 1:nelements(t) - elem = element(mesh, eᵢ) # check if the element should be refined - if method.pred(elem) + if pred(eᵢ) + verts = ∂₂₀(eᵢ) + nv = length(verts) + # add new centroid vertex - push!(newpoints, centroid(elem)) + cₒ = sum(i -> to(points[i]), verts) / length(verts) + pₒ = withcrs(mesh, cₒ) + push!(newpoints, pₒ) # add new connectivities - verts = ∂₂₀(eᵢ) - nv = length(verts) for i in 1:nv u = eᵢ + offset v = verts[mod1(i, nv)] From 9c001cc9c234b8099d9d4a72ab0d632b69b5d499 Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 16:04:56 -0300 Subject: [PATCH 03/13] Apply suggestions --- src/refinement/tri.jl | 72 +++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index 559cd6bfd..806819469 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -30,45 +30,63 @@ function refine(mesh, method::TriRefinement) # convert to half-edge structure t = convert(HalfEdgeTopology, connec) - # used to extract the vertex indices + # add centroids of elements ∂₂₀ = Boundary{2,0}(t) - - # offset to new vertex indices - offset = length(points) - - # predicate function - pred = if isnothing(method.pred) - _ -> true + epts = if isnothing(method.pred) + map(1:nelements(t)) do elem + is = ∂₂₀(elem) + cₒ = sum(i -> to(points[i]), is) / length(is) + withcrs(mesh, cₒ) + end else - eᵢ -> method.pred(element(mesh, eᵢ)) + pts = eltype(points)[] + for elem in mesh + e = element(mesh, elem) + if method.pred(e) + push!(pts, centroid(e)) + end + end + pts end - # add centroids of elements and connect vertices - # into new triangles if necessary - newpoints = copy(points) + # original vertices + vpts = points + + # new points in refined mesh + newpoints = [vpts; epts] + + offset = length(vpts) + + # connect vertices into new triangles newconnec = Connectivity{Triangle,3}[] - for eᵢ in 1:nelements(t) - # check if the element should be refined - if pred(eᵢ) - verts = ∂₂₀(eᵢ) + if isnothing(method.pred) + for elem in 1:nelements(t) + verts = ∂₂₀(elem) nv = length(verts) - - # add new centroid vertex - cₒ = sum(i -> to(points[i]), verts) / length(verts) - pₒ = withcrs(mesh, cₒ) - push!(newpoints, pₒ) - - # add new connectivities for i in 1:nv - u = eᵢ + offset + u = elem + offset v = verts[mod1(i, nv)] w = verts[mod1(i + 1, nv)] tri = connect((u, v, w)) push!(newconnec, tri) end - else - # otherwise, just use the original connectivity - push!(newconnec, element(t, eᵢ)) + end + else + u = offset + for elem in 1:nelements(t) + if method.pred(element(mesh, elem)) + verts = ∂₂₀(elem) + nv = length(verts) + u += 1 + for i in 1:nv + v = verts[mod1(i, nv)] + w = verts[mod1(i + 1, nv)] + tri = connect((u, v, w)) + push!(newconnec, tri) + end + else + push!(newconnec, element(t, elem)) + end end end From 7298d54e71467eb4ab3b26759c24111e54454616 Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 16:55:12 -0300 Subject: [PATCH 04/13] Apply suggestions --- src/refinement/tri.jl | 87 ++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 51 deletions(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index 806819469..69ccda1af 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -3,15 +3,12 @@ # ------------------------------------------------------------------ """ - TriRefinement() + TriRefinement([pred]) Refinement of polygonal meshes into triangles. -A n-gon is subdivided into n triangles. - - TriRefinement(pred) - -Refine only the elements of the mesh where -`pred(element)` returns `true`. +A n-gon for which the predicate `pred` holds true +is subdivided into n triangles. The method refines all +n-gons if the `pred` is ommited. """ struct TriRefinement{F} <: RefinementMethod pred::F @@ -30,23 +27,22 @@ function refine(mesh, method::TriRefinement) # convert to half-edge structure t = convert(HalfEdgeTopology, connec) + # indices to refine + einds = if isnothing(method.pred) + 1:nelements(t) + else + einds = filter(i -> method.pred(mesh[i]), 1:nelements(t)) + end + + # indices to preserve + vinds = setdiff(einds, 1:nelements(t)) + # add centroids of elements ∂₂₀ = Boundary{2,0}(t) - epts = if isnothing(method.pred) - map(1:nelements(t)) do elem - is = ∂₂₀(elem) - cₒ = sum(i -> to(points[i]), is) / length(is) - withcrs(mesh, cₒ) - end - else - pts = eltype(points)[] - for elem in mesh - e = element(mesh, elem) - if method.pred(e) - push!(pts, centroid(e)) - end - end - pts + epts = map(einds) do elem + is = ∂₂₀(elem) + cₒ = sum(i -> to(points[i]), is) / length(is) + withcrs(mesh, cₒ) end # original vertices @@ -55,38 +51,27 @@ function refine(mesh, method::TriRefinement) # new points in refined mesh newpoints = [vpts; epts] + # offset to new vertex indices offset = length(vpts) - # connect vertices into new triangles + # new connectivities in refined mesh newconnec = Connectivity{Triangle,3}[] - if isnothing(method.pred) - for elem in 1:nelements(t) - verts = ∂₂₀(elem) - nv = length(verts) - for i in 1:nv - u = elem + offset - v = verts[mod1(i, nv)] - w = verts[mod1(i + 1, nv)] - tri = connect((u, v, w)) - push!(newconnec, tri) - end - end - else - u = offset - for elem in 1:nelements(t) - if method.pred(element(mesh, elem)) - verts = ∂₂₀(elem) - nv = length(verts) - u += 1 - for i in 1:nv - v = verts[mod1(i, nv)] - w = verts[mod1(i + 1, nv)] - tri = connect((u, v, w)) - push!(newconnec, tri) - end - else - push!(newconnec, element(t, elem)) - end + + # push connects of preserved elements + for elem in vinds + push!(newconnec, element(t, elem)) + end + + # connect vertices into new triangles + for (i, elem) in enumerate(einds) + verts = ∂₂₀(elem) + nv = length(verts) + for j in 1:nv + u = i + offset + v = verts[mod1(j, nv)] + w = verts[mod1(j + 1, nv)] + tri = connect((u, v, w)) + push!(newconnec, tri) end end From bb24ffbab214edc90337118bf6929bfd0dc0f2b7 Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 16:57:04 -0300 Subject: [PATCH 05/13] Apply suggestions --- src/refinement/tri.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index 69ccda1af..4f68679f4 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -56,12 +56,12 @@ function refine(mesh, method::TriRefinement) # new connectivities in refined mesh newconnec = Connectivity{Triangle,3}[] - - # push connects of preserved elements + + # connectivities of preserved elements for elem in vinds push!(newconnec, element(t, elem)) end - + # connect vertices into new triangles for (i, elem) in enumerate(einds) verts = ∂₂₀(elem) From 3f1d5e20cd3d2a605dbf778172fe5e39135d28bb Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 16:58:46 -0300 Subject: [PATCH 06/13] Rename variables --- src/refinement/tri.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index 4f68679f4..5ffa4287e 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -28,18 +28,18 @@ function refine(mesh, method::TriRefinement) t = convert(HalfEdgeTopology, connec) # indices to refine - einds = if isnothing(method.pred) + rinds = if isnothing(method.pred) 1:nelements(t) else - einds = filter(i -> method.pred(mesh[i]), 1:nelements(t)) + rinds = filter(i -> method.pred(mesh[i]), 1:nelements(t)) end # indices to preserve - vinds = setdiff(einds, 1:nelements(t)) + pinds = setdiff(rinds, 1:nelements(t)) # add centroids of elements ∂₂₀ = Boundary{2,0}(t) - epts = map(einds) do elem + epts = map(rinds) do elem is = ∂₂₀(elem) cₒ = sum(i -> to(points[i]), is) / length(is) withcrs(mesh, cₒ) @@ -58,12 +58,12 @@ function refine(mesh, method::TriRefinement) newconnec = Connectivity{Triangle,3}[] # connectivities of preserved elements - for elem in vinds + for elem in pinds push!(newconnec, element(t, elem)) end # connect vertices into new triangles - for (i, elem) in enumerate(einds) + for (i, elem) in enumerate(rinds) verts = ∂₂₀(elem) nv = length(verts) for j in 1:nv From cdfac27129a2cf06a1b8ee79ee92bb7d535e8b7a Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 17:00:17 -0300 Subject: [PATCH 07/13] Fix typo --- src/refinement/tri.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index 5ffa4287e..f75e6439d 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -31,7 +31,7 @@ function refine(mesh, method::TriRefinement) rinds = if isnothing(method.pred) 1:nelements(t) else - rinds = filter(i -> method.pred(mesh[i]), 1:nelements(t)) + filter(i -> method.pred(mesh[i]), 1:nelements(t)) end # indices to preserve From 060ae7a94788ef5a750a04374b0330b7a45860bf Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 17:04:22 -0300 Subject: [PATCH 08/13] Rename variables --- src/refinement/tri.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index f75e6439d..edd62fef4 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -39,7 +39,7 @@ function refine(mesh, method::TriRefinement) # add centroids of elements ∂₂₀ = Boundary{2,0}(t) - epts = map(rinds) do elem + rpts = map(rinds) do elem is = ∂₂₀(elem) cₒ = sum(i -> to(points[i]), is) / length(is) withcrs(mesh, cₒ) @@ -49,7 +49,7 @@ function refine(mesh, method::TriRefinement) vpts = points # new points in refined mesh - newpoints = [vpts; epts] + newpoints = [vpts; rpts] # offset to new vertex indices offset = length(vpts) From 3b98e69d77870dc3e9218dc6b1d578432bbf406f Mon Sep 17 00:00:00 2001 From: Elias Carvalho <73039601+eliascarv@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:17:47 -0300 Subject: [PATCH 09/13] Update src/refinement/tri.jl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Júlio Hoffimann --- src/refinement/tri.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index edd62fef4..c7aa39dfa 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -62,7 +62,7 @@ function refine(mesh, method::TriRefinement) push!(newconnec, element(t, elem)) end - # connect vertices into new triangles + # connectivities of new triangles for (i, elem) in enumerate(rinds) verts = ∂₂₀(elem) nv = length(verts) From 96e5e4824f927a339c4340a0fa4aa82c86a49abe Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 17:45:39 -0300 Subject: [PATCH 10/13] Add tests --- src/refinement/tri.jl | 2 +- test/refinement.jl | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index c7aa39dfa..026bef78e 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -35,7 +35,7 @@ function refine(mesh, method::TriRefinement) end # indices to preserve - pinds = setdiff(rinds, 1:nelements(t)) + pinds = setdiff(1:nelements(t), rinds) # add centroids of elements ∂₂₀ = Boundary{2,0}(t) diff --git a/test/refinement.jl b/test/refinement.jl index 02896e365..9263a337e 100644 --- a/test/refinement.jl +++ b/test/refinement.jl @@ -15,6 +15,14 @@ grid = CartesianGrid((3, 3), merc(0, 0), (T(1), T(1))) ref = refine(grid, TriRefinement()) @test crs(ref) === crs(grid) + + # predicate + points = cart.([(0, 0), (4, 0), (8, 0), (3, 1), (5, 1), (2, 2), (4, 2), (6, 2), (4, 4)]) + connec = connect.([(1, 2, 6), (2, 3, 8), (6, 8, 9), (2, 5, 4), (4, 5, 7), (4, 7, 6), (5, 8, 7)]) + mesh = SimpleMesh(points, connec) + ref = refine(mesh, TriRefinement(e -> measure(e) > T(1) * u"m^2")) + @test nelements(ref) == 13 + @test nvertices(ref) == 12 end @testitem "QuadRefinement" setup = [Setup] begin From 63d88419394074e9d6ed47c441eb51fc037949ab Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 17:51:48 -0300 Subject: [PATCH 11/13] Add more tests --- test/refinement.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/refinement.jl b/test/refinement.jl index 9263a337e..a1f6d5c0c 100644 --- a/test/refinement.jl +++ b/test/refinement.jl @@ -23,6 +23,9 @@ ref = refine(mesh, TriRefinement(e -> measure(e) > T(1) * u"m^2")) @test nelements(ref) == 13 @test nvertices(ref) == 12 + ref = refine(mesh, TriRefinement(e -> measure(e) ≤ T(1) * u"m^2")) + @test nelements(ref) == 15 + @test nvertices(ref) == 13 end @testitem "QuadRefinement" setup = [Setup] begin From 0d67a74bef8b40773b2bf1dbf157c9f3f9264f1a Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 17:57:34 -0300 Subject: [PATCH 12/13] Update code order --- src/refinement/tri.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index 026bef78e..2b68a6d8d 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -57,11 +57,6 @@ function refine(mesh, method::TriRefinement) # new connectivities in refined mesh newconnec = Connectivity{Triangle,3}[] - # connectivities of preserved elements - for elem in pinds - push!(newconnec, element(t, elem)) - end - # connectivities of new triangles for (i, elem) in enumerate(rinds) verts = ∂₂₀(elem) @@ -75,5 +70,10 @@ function refine(mesh, method::TriRefinement) end end + # connectivities of preserved elements + for elem in pinds + push!(newconnec, element(t, elem)) + end + SimpleMesh(newpoints, newconnec) end From 7765f47044ec5b435596fc14ea001998ac404af1 Mon Sep 17 00:00:00 2001 From: Elias Carvalho Date: Wed, 18 Sep 2024 17:58:07 -0300 Subject: [PATCH 13/13] Update code order --- src/refinement/tri.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/refinement/tri.jl b/src/refinement/tri.jl index 2b68a6d8d..8a5e86eef 100644 --- a/src/refinement/tri.jl +++ b/src/refinement/tri.jl @@ -51,12 +51,12 @@ function refine(mesh, method::TriRefinement) # new points in refined mesh newpoints = [vpts; rpts] - # offset to new vertex indices - offset = length(vpts) - # new connectivities in refined mesh newconnec = Connectivity{Triangle,3}[] + # offset to new vertex indices + offset = length(vpts) + # connectivities of new triangles for (i, elem) in enumerate(rinds) verts = ∂₂₀(elem)