Mercurial > repos > public > sbplib_julia
diff src/SbpOperators/readoperator.jl @ 866:1784b1c0af3e feature/laplace_opset
Merge with default
author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
---|---|
date | Wed, 19 Jan 2022 14:44:24 +0100 |
parents | 568058183791 |
children | 06c510d40ebb 7bf3121c6864 |
line wrap: on
line diff
--- a/src/SbpOperators/readoperator.jl Fri Jul 02 14:23:33 2021 +0200 +++ b/src/SbpOperators/readoperator.jl Wed Jan 19 14:44:24 2022 +0100 @@ -1,155 +1,160 @@ using TOML -export read_D2_operator -export read_stencil -export read_stencils -export read_tuple +export read_stencil_set +export get_stencil_set + +export parse_stencil +export parse_scalar +export parse_tuple + +export sbp_operators_path + -export get_stencil -export get_stencils -export get_tuple +""" + read_stencil_set(filename; filters) -function read_D2_operator(fn; order) - operators = TOML.parsefile(fn)["order$order"] - D2 = operators["D2"] - H = operators["H"] - e = operators["e"] - d1 = operators["d1"] +Picks out a stencil set from a TOML file based on some key-value +filters. If more than one set matches the filters an error is raised. The +returned stencil set contains parsed TOML intended for functions like +`parse_scalar` and `parse_stencil`. + +The stencil set is not parsed beyond the inital TOML parse. To get usable +stencils use the `parse_stencil` functions on the fields of the stencil set. + +The reason for this is that since stencil sets are intended to be very +general, and currently do not include any way to specify how to parse a given +section, the exact parsing is left to the user. - # Create inner stencil - innerStencil = get_stencil(operators, "D2", "inner_stencil") +For more information see [Operator file format](@ref) in the documentation. + +See also [`sbp_operators_path`](@ref), [`get_stencil_set`](@ref), [`parse_stencil`](@ref), [`parse_scalar`](@ref), [`parse_tuple`](@ref),. +""" +read_stencil_set(filename; filters...) = get_stencil_set(TOML.parsefile(filename); filters...) + +""" + get_stencil_set(parsed_toml; filters...) + +Picks out a stencil set from an already parsed TOML based on some key-value +filters. - # Create boundary stencils - boundarySize = length(D2["closure_stencils"]) - closureStencils = Vector{typeof(innerStencil)}() # TBD: is the the right way to get the correct type? - for i ∈ 1:boundarySize - closureStencils = (closureStencils..., get_stencil(operators, "D2", "closure_stencils", i; center=i)) +See also [`read_stencil_set`](@ref). +""" +function get_stencil_set(parsed_toml; filters...) + matches = findall(parsed_toml["stencil_set"]) do set + for (key, val) ∈ filters + if set[string(key)] != val + return false + end + end + + return true end - # TODO: Get rid of the padding here. Any padding should be handled by the consturctor accepting the stencils. - eClosure = Stencil(pad_tuple(toml_string_array_to_tuple(Float64, e["closure"]), boundarySize)..., center=1) - dClosure = Stencil(pad_tuple(toml_string_array_to_tuple(Float64, d1["closure"]), boundarySize)..., center=1) - q_tuple = pad_tuple(toml_string_array_to_tuple(Float64, H["closure"]), boundarySize) - quadratureClosure = Vector{typeof(innerStencil)}() - for i ∈ 1:boundarySize - quadratureClosure = (quadratureClosure..., Stencil(q_tuple[i], center=1)) + if length(matches) != 1 + throw(ArgumentError("filters must pick out a single stencil set")) end - d2 = SbpOperators.D2( - innerStencil, - closureStencils, - eClosure, - dClosure, - quadratureClosure, - even - ) + i = matches[1] + return parsed_toml["stencil_set"][i] +end + +""" + parse_stencil(parsed_toml) + +Accepts parsed TOML and reads it as a stencil. + +See also [`read_stencil_set`](@ref), [`parse_scalar`](@ref), [`parse_tuple`](@ref). +""" +function parse_stencil(parsed_toml) + check_stencil_toml(parsed_toml) + + if parsed_toml isa Array + weights = parse_rational.(parsed_toml) + return CenteredStencil(weights...) + end + + weights = parse_rational.(parsed_toml["s"]) + return Stencil(weights..., center = parsed_toml["c"]) +end + +""" + parse_stencil(T, parsed_toml) + +Parses the input as a stencil with element type `T`. +""" +parse_stencil(T, parsed_toml) = Stencil{T}(parse_stencil(parsed_toml)) + +function check_stencil_toml(parsed_toml) + if !(parsed_toml isa Dict || parsed_toml isa Vector{String}) + throw(ArgumentError("the TOML for a stencil must be a vector of strings or a table.")) + end + + if parsed_toml isa Vector{String} + return + end - return d2 + if !(haskey(parsed_toml, "s") && haskey(parsed_toml, "c")) + throw(ArgumentError("the table form of a stencil must have fields `s` and `c`.")) + end + + if !(parsed_toml["s"] isa Vector{String}) + throw(ArgumentError("a stencil must be specified as a vector of strings.")) + end + + if !(parsed_toml["c"] isa Int) + throw(ArgumentError("the center of a stencil must be specified as an integer.")) + end +end + +""" + parse_scalar(parsed_toml) + +Parse a scalar, represented as a string or a number in the TOML, and return it as a `Rational` + +See also [`read_stencil_set`](@ref), [`parse_stencil`](@ref) [`parse_tuple`](@ref). +""" +function parse_scalar(parsed_toml) + try + return parse_rational(parsed_toml) + catch e + throw(ArgumentError("must be a number or a string representing a number.")) + end +end + +""" + parse_tuple(parsed_toml) + +Parse an array as a tuple of scalars. + +See also [`read_stencil_set`](@ref), [`parse_stencil`](@ref), [`parse_scalar`](@ref). +""" +function parse_tuple(parsed_toml) + if !(parsed_toml isa Array) + throw(ArgumentError("argument must be an array")) + end + return Tuple(parse_scalar.(parsed_toml)) end """ - read_stencil(fn, path...; [center]) - -Read a stencil at `path` from the file with name `fn`. -If a center is specified the given element of the stecil is set as the center. - -See also: [`read_stencils`](@ref), [`read_tuple`](@ref), [`get_stencil`](@ref). + parse_rational(parsed_toml) -# Examples -``` -read_stencil(sbp_operators_path()*"standard_diagonal.toml", "order2", "D2", "inner_stencil") -read_stencil(sbp_operators_path()*"standard_diagonal.toml", "order2", "d1", "closure"; center=1) -``` -""" -read_stencil(fn, path...; center=nothing) = get_stencil(TOML.parsefile(fn), path...; center=center) - -""" - read_stencils(fn, path...; centers) - -Read stencils at `path` from the file `fn`. -Centers of the stencils are specified as a tuple or array in `centers`. - -See also: [`read_stencil`](@ref), [`read_tuple`](@ref), [`get_stencils`](@ref). -""" -read_stencils(fn, path...; centers) = get_stencils(TOML.parsefile(fn), path...; centers=centers) - +Parse a string or a number as a rational. """ - read_tuple(fn, path...) - -Read tuple at `path` from the file `fn`. - -See also: [`read_stencil`](@ref), [`read_stencils`](@ref), [`get_tuple`](@ref). -""" -read_tuple(fn, path...) = get_tuple(TOML.parsefile(fn), path...) - -""" - get_stencil(parsed_toml, path...; center=nothing) - -Same as [`read_stencil`](@ref)) but takes already parsed toml. -""" -get_stencil(parsed_toml, path...; center=nothing) = get_stencil(parsed_toml[path[1]], path[2:end]...; center=center) -function get_stencil(parsed_toml; center=nothing) - @assert parsed_toml isa Vector{String} - stencil_weights = Float64.(parse_rational.(parsed_toml)) - - width = length(stencil_weights) - - if isnothing(center) - center = div(width,2)+1 +function parse_rational(parsed_toml) + if parsed_toml isa String + expr = Meta.parse(replace(parsed_toml, "/"=>"//")) + return eval(:(Rational($expr))) + else + return Rational(parsed_toml) end - - return Stencil(stencil_weights..., center=center) end """ - get_stencils(parsed_toml, path...; centers) - -Same as [`read_stencils`](@ref)) but takes already parsed toml. -""" -get_stencils(parsed_toml, path...; centers) = get_stencils(parsed_toml[path[1]], path[2:end]...; centers=centers) -function get_stencils(parsed_toml; centers) - @assert parsed_toml isa Vector{Vector{String}} - @assert length(centers) == length(parsed_toml) + sbp_operators_path() - stencils = () - for i ∈ 1:length(parsed_toml) - stencil = get_stencil(parsed_toml[i], center = centers[i]) - stencils = (stencils..., stencil) - end +Calculate the path for the operators folder with included stencil sets. - return stencils -end - -""" - get_tuple(parsed_toml, path...) - -Same as [`read_tuple`](@ref)) but takes already parsed toml. +See also [`read_stencil_set`](@ref) """ -get_tuple(parsed_toml, path...) = get_tuple(parsed_toml[path[1]], path[2:end]...) -function get_tuple(parsed_toml) - @assert parsed_toml isa Vector{String} - t = Tuple(Float64.(parse_rational.(parsed_toml))) - return t -end - -# TODO: Probably should be deleted once we have gotten rid of read_D2_operator() -function toml_string_array_to_tuple(::Type{T}, arr::AbstractVector{String}) where T - return Tuple(T.(parse_rational.(arr))) -end - -function parse_rational(str) - expr = Meta.parse(replace(str, "/"=>"//")) - return eval(:(Rational($expr))) -end - -function pad_tuple(t::NTuple{N, T}, n::Integer) where {N,T} - if N >= n - return t - else - return pad_tuple((t..., zero(T)), n) - end -end - sbp_operators_path() = (@__DIR__) * "/operators/" -export sbp_operators_path