diff --git a/src/DistMesh.jl b/src/DistMesh.jl index d2bf7dd..69b1ad6 100644 --- a/src/DistMesh.jl +++ b/src/DistMesh.jl @@ -26,14 +26,22 @@ struct DistMeshSetup{T,RT} ptol::T end +function DistMeshSetup(;iso=0,ptol=.001,deltat=0.05,retriangulation_criteria=RetriangulateMaxMove(0.02)) + T = promote_type(typeof(iso),typeof(ptol),typeof(deltat)) + DistMeshSetup{T,typeof(retriangulation_criteria)}(iso,deltat,retriangulation_criteria,ptol) +end + abstract type AbstractRetriangulationCriteria end +""" + retriangulate if a move over a given tolerance occurs +""" struct RetriangulateMaxMove{T} <: AbstractRetriangulationCriteria ttol::T end """ - retriangulate on a positive delta over N moves, after M iterations + retriangulate on a positive delta over N moves, after M force iterations """ struct RetriangulateMaxMoveDelta <: AbstractRetriangulationCriteria move_count::Int diff --git a/src/distmeshnd.jl b/src/distmeshnd.jl index cfb08bb..66ee524 100644 --- a/src/distmeshnd.jl +++ b/src/distmeshnd.jl @@ -15,15 +15,16 @@ d(p) = sqrt(sum(p.^2))-1 p,t = distmeshnd(d,huniform,0.2) """ -function distmesh(fdist::Function,fh::Function,h::Number, ::Type{VertType}=GeometryBasics.Point{3,Float64}; origin=VertType(-1,-1,-1), +function distmesh(fdist::Function,fh::Function,h::Number, setup::DistMeshSetup{T,ReTri}=DistMeshSetup(), ::Type{VertType}=GeometryBasics.Point{3,Float64}; origin=VertType(-1,-1,-1), widths=VertType(2,2,2), fix::Vector{VertType}=VertType[], - vis=true, stats=false, - distribution=:regular) where {VertType} + distribution=:regular) where {VertType, T, ReTri} - dim=length(VertType) - ptol=.001; ttol=0.02; L0mult=1+.4/2^(dim-1); deltat=0.05; geps=1e-1*h; + ptol=setup.ptol + L0mult=1+.4/2^2 + deltat=setup.deltat + geps=1e-1*h+setup.iso #ptol=.001; ttol=.1; L0mult=1+.4/2^(dim-1); deltat=.2; geps=1e-1*h; # # % 2. Remove points outside the region, apply the rejection method @@ -38,10 +39,10 @@ function distmesh(fdist::Function,fh::Function,h::Number, ::Type{VertType}=Geome p = copy(fix) if distribution == :regular - simplecubic!(fdist, p, h, origin, widths, VertType) + simplecubic!(fdist, p, h, setup.iso, origin, widths, VertType) elseif distribution == :packed # face-centered cubic point distribution - facecenteredcubic!(fdist, p, h, origin, widths, VertType) + facecenteredcubic!(fdist, p, h, setup.iso, origin, widths, VertType) end dcount = 0 lcount = 0 @@ -68,7 +69,7 @@ function distmesh(fdist::Function,fh::Function,h::Number, ::Type{VertType}=Geome # Retriangulation by Delaunay # if large move, retriangulation - if maxmove>ttol*h + if ReTri <: RetriangulateMaxMove && maxmove>setup.retriangulation_criteria.ttol*h triangulation = delaunayn(p) t_d = triangulation.tetrahedra resize!(t, length(t_d)) @@ -118,8 +119,8 @@ function distmesh(fdist::Function,fh::Function,h::Number, ::Type{VertType}=Geome bars[i] = barvec L[i] = sqrt(sum(barvec.^2)) # length L0[i] = fh((b1+b2)./2) - Lsum = Lsum + L[i].^dim - L0sum = L0sum + L0[i].^dim + Lsum = Lsum + L[i].^3 + L0sum = L0sum + L0[i].^3 end # zero out force at each node @@ -159,7 +160,7 @@ function distmesh(fdist::Function,fh::Function,h::Number, ::Type{VertType}=Geome maxdp = max(maxdp, deltat*sqrt(sum(dp[i].^2))) end - if d <= 0 + if d <= setup.iso maxmove = max(sqrt(sum((p[i]-p0).^2)),maxmove) # determine movements continue end @@ -172,7 +173,7 @@ function distmesh(fdist::Function,fh::Function,h::Number, ::Type{VertType}=Geome dz = (fdist(p[i].+VertType(0,0,deps)) - fdist(p[i].-VertType(0,0,deps)))/(2deps) grad = VertType(dx,dy,dz) #normalize? # project back to boundary - p[i] = p[i] - grad.*d + p[i] = p[i] - grad.*(d+setup.iso) maxmove = max(sqrt(sum((p[i]-p0).^2)),maxmove) end diff --git a/src/pointdistribution.jl b/src/pointdistribution.jl index de91e1c..fc682a7 100644 --- a/src/pointdistribution.jl +++ b/src/pointdistribution.jl @@ -1,17 +1,17 @@ -function simplecubic!(fdist, points, h, origin, widths, ::Type{VertType}) where VertType +function simplecubic!(fdist, points, h, iso, origin, widths, ::Type{VertType}) where VertType @inbounds for xi = origin[1]:h:(origin[1]+widths[1]), yi = origin[2]:h:(origin[2]+widths[2]), zi = origin[3]:h:(origin[3]+widths[3]) point = VertType(xi,yi,zi) - fdist(point) < 0 && push!(points,point) + fdist(point) < iso && push!(points,point) end end -function facecenteredcubic!(fdist, points, h, origin, widths, ::Type{VertType}) where VertType +function facecenteredcubic!(fdist, points, h, iso, origin, widths, ::Type{VertType}) where VertType # face-centered cubic point distribution r = h/2 counts = round.(widths./h).+2 @inbounds for xi = -1:Int(counts[1]), yi = -1:Int(counts[2]), zi = -1:Int(counts[3]) point = VertType(2xi+((yi+zi)%2), sqrt(3)*(yi+(zi%2)/3),2*sqrt(6)*zi/3).*r + origin - fdist(point) < 0 && push!(points,point) + fdist(point) < iso && push!(points,point) end end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index d10c52b..05898b6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,19 +4,16 @@ using MAT using GeometryTypes using StaticArrays -# use makie to visualize triangulations -_VIS = false - @testset "distmesh 3D" begin d(p) = sqrt(sum(p.^2))-1 - p,t,_ = distmesh(d,huniform,0.2, vis=_VIS) + p,t,_ = distmesh(d,huniform,0.2) @test length(p) == 485 @test length(t) == 2207 - p,t,_ = distmesh(d,huniform,0.2, vis=_VIS, distribution=:packed) + p,t,_ = distmesh(d,huniform,0.2, distribution=:packed) @test length(p) == 742 - @test_broken length(t) == 3455 #3453 on unix? + @test length(t) == 3455 end @@ -44,7 +41,7 @@ end @testset "simple cubic" begin pts = [] f(x) = -1 - DistMesh.simplecubic!(f, pts, 0.5, Point{3,Float64}(0),Point{3,Float64}(1),Point{3,Float64}) + DistMesh.simplecubic!(f, pts, 0.5, 0, Point{3,Float64}(0),Point{3,Float64}(1),Point{3,Float64}) @test length(pts) == 27 @test isapprox(vlen(pts[1],pts[2]),0.5) @test length(pts) == length(unique(pts)) @@ -53,7 +50,7 @@ end @testset "face centered cubic" begin pts = [] f(x) = -1 - DistMesh.facecenteredcubic!(f, pts, 0.5, Point{3,Float64}(0),Point{3,Float64}(1),Point{3,Float64}) + DistMesh.facecenteredcubic!(f, pts, 0.5, 0, Point{3,Float64}(0),Point{3,Float64}(1),Point{3,Float64}) @test length(pts) == 216 @test isapprox(vlen(pts[1],pts[2]),0.5) @test length(pts) == length(unique(pts))