Skip to content

Commit 6444ff1

Browse files
authored
improve projection of PseudoDensities (#159)
* improve projection of PseudoDensities * bump version * more exports and tests * formatter toml and formatting
1 parent 2fcd133 commit 6444ff1

File tree

6 files changed

+62
-16
lines changed

6 files changed

+62
-16
lines changed

.JuliaFormatter.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
style = "blue"

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "TopOpt"
22
uuid = "53a1e1a5-51bb-58a9-8a02-02056cc81109"
33
authors = ["mohamed82008 <mohamed82008@gmail.com>", "yijiangh <yijiang94817@gmail.com>"]
4-
version = "0.7.3"
4+
version = "0.8.0"
55

66
[deps]
77
AbstractDifferentiation = "c29ec348-61ec-40c8-8164-b8c60e9d9f3d"

src/TopOpt.jl

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,28 @@ using Requires, Reexport, ChainRulesCore
88
struct PseudoDensities{I,P,F,T,N,A<:AbstractArray{T,N}} <: AbstractArray{T,N}
99
x::A
1010
end
11+
function Base.setindex!(A::PseudoDensities, x, inds...)
12+
return A.x[inds...] = x
13+
end
1114
function PseudoDensities(x::A) where {T,N,A<:AbstractArray{T,N}}
1215
return PseudoDensities{false,false,false,T,N,A}(x)
1316
end
1417
function PseudoDensities{I,P,F}(x::A) where {I,P,F,T,N,A<:AbstractArray{T,N}}
1518
return PseudoDensities{I,P,F,T,N,A}(x)
1619
end
1720

21+
Base.BroadcastStyle(::Type{T}) where {T<:PseudoDensities} = Broadcast.ArrayStyle{T}()
22+
function Base.similar(
23+
bc::Broadcast.Broadcasted{Broadcast.ArrayStyle{T}}, ::Type{ElType}
24+
) where {T,ElType}
25+
return similar(T, axes(bc))
26+
end
27+
function Base.similar(
28+
::Type{<:TV}, axes::Tuple{Union{Integer,Base.OneTo},Vararg{Union{Integer,Base.OneTo}}}
29+
) where {I,P,F,T,N,A,TV<:PseudoDensities{I,P,F,T,N,A}}
30+
return PseudoDensities{I,P,F}(similar(A, axes))
31+
end
32+
1833
function ChainRulesCore.rrule(
1934
::Type{PseudoDensities{I,P,F,T,N,A}}, x::Matrix
2035
) where {I,P,F,T,N,A}
@@ -104,6 +119,6 @@ export TopOpt,
104119
MMA87,
105120
MMA02,
106121
HeavisideProjection,
107-
ProjectedPenalty,
108-
PowerPenalty
122+
SigmoidProjection,
123+
ProjectedPenalty
109124
end

src/Utilities/Utilities.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ using ForwardDiff, Ferrite, IterativeSolvers, Requires
55
export AbstractPenalty,
66
PowerPenalty,
77
RationalPenalty,
8+
SinhPenalty,
89
HeavisideProjection,
910
SigmoidProjection,
1011
ProjectedPenalty,

src/Utilities/penalties.jl

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
1+
import ..TopOpt: PseudoDensities
2+
13
abstract type AbstractPenalty{T} end
24
abstract type AbstractCPUPenalty{T} <: AbstractPenalty{T} end
35
abstract type AbstractProjection end
46

7+
function (P::AbstractCPUPenalty)(x::PseudoDensities{I,<:Any,F}) where {I,F}
8+
return PseudoDensities{I,true,F}(P.(x.x))
9+
end
10+
511
mutable struct PowerPenalty{T} <: AbstractCPUPenalty{T}
612
p::T
713
end
8-
@inline (P::PowerPenalty)(x) = x^(P.p)
14+
(P::PowerPenalty)(x::Real) = x^(P.p)
915

1016
mutable struct RationalPenalty{T} <: AbstractCPUPenalty{T}
1117
p::T
1218
end
13-
@inline (R::RationalPenalty)(x) = x / (1 + R.p * (1 - x))
19+
(R::RationalPenalty)(x::Real) = x / (1 + R.p * (1 - x))
1420

1521
mutable struct SinhPenalty{T} <: AbstractCPUPenalty{T}
1622
p::T
1723
end
18-
@inline (R::SinhPenalty)(x) = sinh(R.p * x) / sinh(R.p)
24+
(R::SinhPenalty)(x::Real) = sinh(R.p * x) / sinh(R.p)
1925

2026
struct ProjectedPenalty{T,Tpen<:AbstractPenalty{T},Tproj} <: AbstractCPUPenalty{T}
2127
penalty::Tpen
@@ -24,17 +30,20 @@ end
2430
function ProjectedPenalty(penalty::AbstractPenalty{T}) where {T}
2531
return ProjectedPenalty(penalty, HeavisideProjection(10 * one(T)))
2632
end
27-
@inline (P::ProjectedPenalty)(x) = P.penalty(P.proj(x))
33+
@inline (P::ProjectedPenalty)(x::Real) = P.penalty(P.proj(x))
2834
@forward_property ProjectedPenalty penalty
2935

3036
mutable struct HeavisideProjection{T} <: AbstractProjection
3137
β::T
3238
end
33-
@inline (P::HeavisideProjection)(x) = 1 - exp(-P.β * x) + x * exp(-P.β)
39+
@inline (P::HeavisideProjection)(x::Real) = 1 - exp(-P.β * x) + x * exp(-P.β)
40+
(P::HeavisideProjection)(x::AbstractArray) = P.(x)
41+
3442
mutable struct SigmoidProjection{T} <: AbstractProjection
3543
β::T
3644
end
37-
@inline (P::SigmoidProjection)(x) = 1 / (1 + exp((P.β + 1) * (-x + 0.5)))
45+
@inline (P::SigmoidProjection)(x::Real) = 1 / (1 + exp((P.β + 1) * (-x + 0.5)))
46+
(P::SigmoidProjection)(x::AbstractArray) = P.(x)
3847

3948
import Base: copy
4049
copy(p::TP) where {TP<:AbstractPenalty} = TP(p.p)

test/Functions/test_common_fns.jl

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,31 @@ using Ferrite: ndofs_per_cell, getncells
66

77
Random.seed!(1)
88

9+
get_pen_T(::PseudoDensities{<:Any,T,<:Any}) where {T} = T
10+
11+
@testset "Projections and penalties" begin
12+
for proj in (HeavisideProjection(5.0), SigmoidProjection(4.0))
13+
for T1 in (true, false), T2 in (true, false), T3 in (true, false)
14+
x = PseudoDensities{T1,T2,T3}(rand(4))
15+
@test typeof(proj(x)) === typeof(x)
16+
@test typeof(proj.(x)) === typeof(x)
17+
end
18+
end
19+
20+
for pen in (PowerPenalty(3.0), RationalPenalty(3.0), SinhPenalty(3.0))
21+
for T1 in (true, false), T2 in (true, false), T3 in (true, false)
22+
x = PseudoDensities{T1,T2,T3}(rand(4))
23+
@test get_pen_T(pen(x)) === true
24+
@test get_pen_T(ProjectedPenalty(pen)(x)) === true
25+
end
26+
end
27+
end
28+
929
@testset "Compliance" begin
1030
nels = (2, 2)
1131
problem = HalfMBB(Val{:Linear}, nels, (1.0, 1.0), 1.0, 0.3, 1.0)
1232
for p in (1.0, 2.0, 3.0)
13-
solver = FEASolver(Direct, problem; xmin=0.01, penalty=TopOpt.PowerPenalty(p))
33+
solver = FEASolver(Direct, problem; xmin=0.01, penalty=PowerPenalty(p))
1434
comp = Compliance(solver)
1535
f = x -> comp(PseudoDensities(x))
1636
for i in 1:3
@@ -29,7 +49,7 @@ end
2949
nels = (2, 2)
3050
problem = HalfMBB(Val{:Linear}, nels, (1.0, 1.0), 1.0, 0.3, 1.0)
3151
for p in (1.0, 2.0, 3.0)
32-
solver = FEASolver(Direct, problem; xmin=0.01, penalty=TopOpt.PowerPenalty(p))
52+
solver = FEASolver(Direct, problem; xmin=0.01, penalty=PowerPenalty(p))
3353
dp = Displacement(solver)
3454
u = dp(PseudoDensities(solver.vars))
3555
for _ in 1:3
@@ -50,7 +70,7 @@ end
5070
nels = (2, 2)
5171
problem = HalfMBB(Val{:Linear}, nels, (1.0, 1.0), 1.0, 0.3, 1.0)
5272
for p in (1.0, 2.0, 3.0)
53-
solver = FEASolver(Direct, problem; xmin=0.01, penalty=TopOpt.PowerPenalty(p))
73+
solver = FEASolver(Direct, problem; xmin=0.01, penalty=PowerPenalty(p))
5474
vol = Volume(solver)
5575
constr = x -> vol(PseudoDensities(x)) - 0.3
5676
for i in 1:3
@@ -69,8 +89,8 @@ end
6989
nels = (2, 2)
7090
problem = HalfMBB(Val{:Linear}, nels, (1.0, 1.0), 1.0, 0.3, 1.0)
7191
for p in (1.0, 2.0, 3.0)
72-
solver = FEASolver(Direct, problem; xmin=0.01, penalty=TopOpt.PowerPenalty(p))
73-
filter = TopOpt.DensityFilter(solver; rmin=4.0)
92+
solver = FEASolver(Direct, problem; xmin=0.01, penalty=PowerPenalty(p))
93+
filter = DensityFilter(solver; rmin=4.0)
7494
for i in 1:3
7595
x = rand(prod(nels))
7696
v = rand(prod(nels))
@@ -114,7 +134,7 @@ end
114134
end
115135
problem = MultiLoad(base_problem, F)
116136
for p in (1.0, 2.0, 3.0)
117-
solver = FEASolver(Direct, problem; xmin=0.01, penalty=TopOpt.PowerPenalty(p))
137+
solver = FEASolver(Direct, problem; xmin=0.01, penalty=PowerPenalty(p))
118138
exact_svd_block = BlockCompliance(problem, solver; method=:exact)
119139
constr = Nonconvex.FunctionWrapper(
120140
x -> exact_svd_block(x) .- 1000.0,
@@ -138,7 +158,7 @@ end
138158
nels = (2, 2)
139159
problem = HalfMBB(Val{:Linear}, nels, (1.0, 1.0), 1.0, 0.3, 1.0)
140160
for p in (1.0, 2.0, 3.0)
141-
solver = FEASolver(Direct, problem; xmin=0.01, penalty=TopOpt.PowerPenalty(p))
161+
solver = FEASolver(Direct, problem; xmin=0.01, penalty=PowerPenalty(p))
142162
st = StressTensor(solver)
143163
# element stress tensor - element 1
144164
est = st[1]

0 commit comments

Comments
 (0)