Skip to content

Commit

Permalink
Reducing compiler overhead of functions as getters
Browse files Browse the repository at this point in the history
  • Loading branch information
kaipartmann committed Mar 12, 2024
1 parent a907c6c commit 93a69e9
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 127 deletions.
6 changes: 3 additions & 3 deletions src/Peridynamics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ end
export BBMaterial, CKIMaterial, NOSBMaterial, OSBMaterial, Body, point_set!,
failure_permit!, material!, velocity_bc!, velocity_ic!, forcedensity_bc!, precrack!,
VelocityVerlet, MultibodySetup, contact!, Job, read_vtk, uniform_box, submit,
process_each_export, @eff
process_each_export

const MPI_INITIALIZED = Ref(false)
const MPI_RANK = Ref(-1)
Expand All @@ -34,7 +34,7 @@ const ELASTIC_KWARGS = (:E, :nu)
const FRAC_KWARGS = (:Gc, :epsilon_c)
const DEFAULT_POINT_KWARGS = (:horizon, :rho, ELASTIC_KWARGS..., FRAC_KWARGS...)
const CONTACT_KWARGS = (:radius, :sc)
const EXPORT_KWARGS = (:path, :freq, :eff)
const EXPORT_KWARGS = (:path, :freq, :fields)
const DEFAULT_EXPORT_FIELDS = (:displacement, :damage)
const JOB_KWARGS = (EXPORT_KWARGS...,)
const SUBMIT_KWARGS = (:quiet,)
Expand Down Expand Up @@ -127,7 +127,7 @@ include("auxiliary/process_each_export.jl")
try
include("auxiliary/precompile_workload.jl")
catch err
@error "precompilation errored - can be safely ignored!\n" exception=err
@error "precompilation errored\n" exception=err
end

end
49 changes: 14 additions & 35 deletions src/auxiliary/io.jl
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
const ExportField = Tuple{Symbol,DataType}

struct ExportOptions{F<:Function}
struct ExportOptions{N}
exportflag::Bool
root::String
vtk::String
logfile::String
freq::Int
eff::F
fields::NTuple{N,Symbol}

function ExportOptions(root::String, freq::Int, eff::F) where {F<:Function}
function ExportOptions(root::String, freq::Int, fields::NTuple{N,Symbol}) where {N}
if isempty(root)
_eff = ()->()
return new{typeof(_eff)}(false, "", "", "", 0, _eff)
return new{0}(false, "", "", "", 0, NTuple{0,Symbol}())
end
vtk = joinpath(root, "vtk")
logfile = joinpath(root, "logfile.log")
return new{F}(true, root, vtk, logfile, freq, eff)
return new{N}(true, root, vtk, logfile, freq, fields)
end
end

function (eo::ExportOptions{F})(s::AbstractStorage) where {F<:Function}
return eo.eff(s)
end

function get_export_options(::Type{S}, o::Dict{Symbol,Any}) where {S<:AbstractStorage}
local root::String
local freq::Int
Expand All @@ -42,32 +35,18 @@ function get_export_options(::Type{S}, o::Dict{Symbol,Any}) where {S<:AbstractSt
end
freq < 0 && throw(ArgumentError("`freq` should be larger than zero!\n"))

eff = get_exported_fields_function(S, o)

return ExportOptions(root, freq, eff)
end

function export_disp_and_dmg(s::AbstractStorage)
return (("displacement", s.displacement), ("damage", s.damage))
end
exfields = get_exported_fields(S, o)

macro eff(vars...)
local args = Expr[]
for var in vars
var isa QuoteNode || error("only symbols are allowed args!\n")
local name = string(var)[begin+1:end]
push!(args, :($(name), Core.getfield(x, $(esc(var)))))
end
return Expr(:->, :x, Expr(:tuple, args...))
return ExportOptions(root, freq, exfields)
end

function get_exported_fields_function(::Type{S}, o::Dict{Symbol,Any}) where {S}
if haskey(o, :eff)
eff = o[:eff]
function get_exported_fields(::Type{S}, o::Dict{Symbol,Any}) where {S}
if haskey(o, :fields)
fields = o[:fields]
else
eff = export_disp_and_dmg
fields = DEFAULT_EXPORT_FIELDS
end
return eff
return fields
end

function export_results(dh::AbstractDataHandler, options::ExportOptions, chunk_id::Int,
Expand All @@ -92,8 +71,8 @@ function _export_results(b::AbstractBodyChunk, chunk_id::Int, n_chunks::Int,
filename = @sprintf("timestep_%05d", n)
position = get_loc_position(b)
pvtk_grid(filename, position, b.cells; part=chunk_id, nparts=n_chunks) do vtk
for (name, field) in options(b.store)
vtk[name] = field
for field in options.fields
vtk[string(field)] = get_storage_field(b.store, field)
end
vtk["time", VTKFieldData()] = t
end
Expand Down
36 changes: 11 additions & 25 deletions src/conditions/boundary_conditions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,18 @@
"""
"""
struct SingleDimBC{F<:Function,G<:Function} <: AbstractCondition
struct SingleDimBC{F<:Function} <: AbstractCondition
fun::F
cff::G
field::Symbol
point_set::Symbol
dim::UInt8
end

@inline function (b::SingleDimBC{F,G})(t::Float64) where {F,G}
@inline function (b::SingleDimBC{F})(t::Float64) where {F}
value::Float64 = b.fun(t)
return value
end

@inline function (b::SingleDimBC{F,G})(s::AbstractStorage) where {F,G}
return b.cff(s)
end

@inline get_cff_velocity_half(s::AbstractStorage) = s.velocity_half
@inline get_cff_velocity(s::AbstractStorage) = s.velocity
@inline get_cff_b_ext(s::AbstractStorage) = s.b_ext

function override_eachother(a::SingleDimBC, b::SingleDimBC)
same_field = a.field === b.field
same_point_set = a.point_set === b.point_set
Expand All @@ -41,10 +32,10 @@ function apply_bcs!(b::AbstractBodyChunk, time::Float64)
end

function apply_bc!(s::AbstractStorage, psets::Dict{Symbol,Vector{Int}},
bc::SingleDimBC{F,G}, time::Float64) where {F,G}
bc::SingleDimBC{F}, time::Float64) where {F}
value = bc(time)
isnan(value) && return nothing
apply_sdbc!(bc(s), value, bc.dim, psets[bc.point_set])
apply_sdbc!(get_storage_field(s, bc.field), value, bc.dim, psets[bc.point_set])
return nothing
end

Expand All @@ -56,23 +47,18 @@ end
return nothing
end

struct PosDepSingleDimBC{F<:Function,G<:Function} <: AbstractCondition
struct PosDepSingleDimBC{F<:Function} <: AbstractCondition
fun::F
cff::G
field::Symbol
point_set::Symbol
dim::UInt8
end

@inline function (b::PosDepSingleDimBC{F,G})(p::AbstractVector, t::Float64) where {F,G}
@inline function (b::PosDepSingleDimBC{F})(p::AbstractVector, t::Float64) where {F}
value::Float64 = b.fun(p, t)
return value
end

@inline function (b::PosDepSingleDimBC{F,G})(s::AbstractStorage) where {F,G}
return b.cff(s)
end

function override_eachother(a::PosDepSingleDimBC, b::PosDepSingleDimBC)
same_field = a.field === b.field
same_point_set = a.point_set === b.point_set
Expand All @@ -81,15 +67,15 @@ function override_eachother(a::PosDepSingleDimBC, b::PosDepSingleDimBC)
end

function apply_bc!(s::AbstractStorage, psets::Dict{Symbol,Vector{Int}},
bc::PosDepSingleDimBC{F,G}, position::Matrix{Float64},
time::Float64) where {F,G}
apply_pdsdbc!(bc(s), position, bc, psets[bc.point_set], time)
bc::PosDepSingleDimBC{F}, position::Matrix{Float64},
time::Float64) where {F}
apply_pdsdbc!(get_storage_field(s, bc.field), position, bc, psets[bc.point_set], time)
return nothing
end

@inline function apply_pdsdbc!(field::Matrix{Float64}, pos::Matrix{Float64},
bc::PosDepSingleDimBC{F,G}, point_ids::Vector{Int},
t::Float64) where {F,G}
bc::PosDepSingleDimBC{F}, point_ids::Vector{Int},
t::Float64) where {F}
@simd for i in point_ids
@inbounds field[bc.dim, i] = bc(SVector{3}(pos[1,i], pos[2,i], pos[3,i]), t)
end
Expand Down
9 changes: 2 additions & 7 deletions src/conditions/initial_conditions.jl
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
"""
"""
struct SingleDimIC{G<:Function} <: AbstractCondition
struct SingleDimIC <: AbstractCondition
value::Float64
cff::G
field::Symbol
point_set::Symbol
dim::UInt8
end

@inline function (sdic::SingleDimIC{G})(s::AbstractStorage) where {G<:Function}
return sdic.cff(s)
end

function override_eachother(a::SingleDimIC, b::SingleDimIC)
same_field = a.field === b.field
same_point_set = a.point_set === b.point_set
Expand All @@ -22,7 +17,7 @@ end

function apply_ic!(b::AbstractBodyChunk, ic::SingleDimIC)
for point_id in b.psets[ic.point_set]
setindex!(ic(b.store), ic.value, ic.dim, point_id)
setindex!(get_storage_field(b.store, ic.field), ic.value, ic.dim, point_id)
end
return nothing
end
10 changes: 5 additions & 5 deletions src/discretizations/body.jl
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,10 @@ function velocity_bc!(f::F, b::Body, name::Symbol, d::DimensionSpec) where {F<:F
type = check_condition_function(f)
dim = get_dim(d)
if type === :sdbc
sdbc = SingleDimBC(f, get_cff_velocity_half, :velocity_half, name, dim)
sdbc = SingleDimBC(f, :velocity_half, name, dim)
_condition!(b.single_dim_bcs, sdbc)
elseif type === :pdsdbc
pdsdbc = PosDepSingleDimBC(f, get_cff_velocity_half, :velocity_half, name, dim)
pdsdbc = PosDepSingleDimBC(f, :velocity_half, name, dim)
_condition!(b.posdep_single_dim_bcs, pdsdbc)
end
return nothing
Expand All @@ -197,7 +197,7 @@ TODO
function velocity_ic!(b::Body, name::Symbol, d::DimensionSpec, value::Real)
check_if_set_is_defined(b.point_sets, name)
dim = get_dim(d)
sdic = SingleDimIC(convert(Float64, value), get_cff_velocity, :velocity, name, dim)
sdic = SingleDimIC(convert(Float64, value), :velocity, name, dim)
_condition!(b.single_dim_ics, sdic)
return nothing
end
Expand All @@ -210,10 +210,10 @@ function forcedensity_bc!(f::F, b::Body, name::Symbol, d::DimensionSpec) where {
type = check_condition_function(f)
dim = get_dim(d)
if type === :sdbc
sdbc = SingleDimBC(f, get_cff_b_ext, :b_ext, name, dim)
sdbc = SingleDimBC(f, :b_ext, name, dim)
_condition!(b.single_dim_bcs, sdbc)
elseif type === :pdsdbc
pdsdbc = PosDepSingleDimBC(f, get_cff_b_ext, :b_ext, name, dim)
pdsdbc = PosDepSingleDimBC(f, :b_ext, name, dim)
_condition!(b.posdep_single_dim_bcs, pdsdbc)
end
return nothing
Expand Down
28 changes: 25 additions & 3 deletions src/physics/material_interface.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@

#---- mandatory interface functions ----#

function point_param_type(mat::AbstractMaterial)
throw(MethodError(point_param_type, mat))
end
Expand Down Expand Up @@ -29,4 +27,28 @@ function get_halo_write_fields(s::AbstractStorage)
throw(MethodError(get_halo_write_fields, s))
end

#---- optional interface functions ----#
function get_storage_field(s::S, field::Symbol) where {S<:AbstractStorage}
if field === :position
return getfield(s, :position)
elseif field === :displacement
return getfield(s, :displacement)
elseif field === :velocity
return getfield(s, :velocity)
elseif field === :velocity_half
return getfield(s, :velocity_half)
elseif field === :acceleration
return getfield(s, :acceleration)
elseif field === :b_int
return getfield(s, :b_int)
elseif field === :b_ext
return getfield(s, :b_ext)
elseif field === :damage
return getfield(s, :damage)
else
return get_custom_field(s, field)
end
end

function get_custom_field(::S, field::Symbol) where {S<:AbstractStorage}
return throw(ArgumentError("field $field no known in $(S)\n"))
end
54 changes: 5 additions & 49 deletions test/auxiliary/test_io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@test eo.vtk == abspath(joinpath("rootpath", "vtk"))
@test eo.logfile == abspath(joinpath("rootpath", "logfile.log"))
@test eo.freq == 10
@test eo.eff == Peridynamics.export_disp_and_dmg
@test eo.fields == Peridynamics.DEFAULT_EXPORT_FIELDS

o = Dict{Symbol,Any}(:path => "rootpath")
eo = Peridynamics.get_export_options(Peridynamics.BBVerletStorage, o)
Expand All @@ -15,7 +15,7 @@
@test eo.vtk == abspath(joinpath("rootpath", "vtk"))
@test eo.logfile == abspath(joinpath("rootpath", "logfile.log"))
@test eo.freq == 10
@test eo.eff == Peridynamics.export_disp_and_dmg
@test eo.fields == Peridynamics.DEFAULT_EXPORT_FIELDS

o = Dict{Symbol,Any}(:freq => 10)
msg = "if `freq` is spedified, the keyword `path` is also needed!\n"
Expand All @@ -30,64 +30,20 @@
@test eo.vtk == ""
@test eo.logfile == ""
@test eo.freq == 0
@test eo.eff isa Function
@test eo.eff() == ()
@test eo.fields == ()

o = Dict{Symbol,Any}(:path => "rootpath", :freq => -10)
msg = "`freq` should be larger than zero!\n"
@test_throws ArgumentError(msg) begin
Peridynamics.get_export_options(Peridynamics.BBVerletStorage, o)
end

eff = x -> (("disp", x.displacement), ("dmg", x.damage), ("b_int", x.b_int))
o = Dict{Symbol,Any}(:path => "rootpath", :eff => eff)
o = Dict{Symbol,Any}(:path => "rootpath", :fields => (:displacement, :b_ext))
eo = Peridynamics.get_export_options(Peridynamics.BBVerletStorage, o)
@test eo.exportflag == true
@test eo.root == abspath("rootpath")
@test eo.vtk == abspath(joinpath("rootpath", "vtk"))
@test eo.logfile == abspath(joinpath("rootpath", "logfile.log"))
@test eo.freq == 10
@test eo.eff == eff
end

@testitem "exported fields function" begin
position = rand(3,10)
displacement = rand(3,10)
velocity = rand(3,10)
velocity_half = rand(3,10)
acceleration = rand(3,10)
b_int = rand(3,10)
b_ext = rand(3,10)
damage = rand(10)
bond_active = rand(Bool,20)
n_active_bonds = rand(Int,20)
s = Peridynamics.BBVerletStorage(position, displacement, velocity, velocity_half,
acceleration, b_int, b_ext, damage, bond_active,
n_active_bonds)

o = Dict{Symbol,Any}(:path => "rootpath")
eo = Peridynamics.get_export_options(Peridynamics.BBVerletStorage, o)
tpl = eo(s)
@test length(tpl) == 2
@test tpl[1] == ("displacement", displacement)
@test tpl[2] == ("damage", damage)

_eff = x -> (("disp", x.displacement), ("dmg", x.damage), ("b_int", x.b_int))
o = Dict{Symbol,Any}(:path => "rootpath", :eff => _eff)
eo = Peridynamics.get_export_options(Peridynamics.BBVerletStorage, o)
tpl = eo(s)
@test length(tpl) == 3
@test tpl[1] == ("disp", displacement)
@test tpl[2] == ("dmg", damage)
@test tpl[3] == ("b_int", b_int)

_eff = @eff :displacement :acceleration :damage :b_int
o = Dict{Symbol,Any}(:path => "rootpath", :eff => _eff)
eo = Peridynamics.get_export_options(Peridynamics.BBVerletStorage, o)
tpl = eo(s)
@test length(tpl) == 4
@test tpl[1] == ("displacement", displacement)
@test tpl[2] == ("acceleration", acceleration)
@test tpl[3] == ("damage", damage)
@test tpl[4] == ("b_int", b_int)
@test eo.fields == (:displacement, :b_ext)
end

0 comments on commit 93a69e9

Please sign in to comment.