###### tags: `Curso Julia` # Interfaces - Materialis.jl ## Forward problem ```julia abstract type AbstractForwardProblem struct ForwardProblem{D<:FEMData} <: AbstractForwardProblem data::D materials::Dict{<:AbstractMaterial,Function} end # constructor generico function ForwardProblem(data::FEMData, materials) foreach(initialize!(data.grid, m, func) for (m, func) in materials) ForwardProblem{typeof(data)}(data, material) end initialize!(grid::Ferrite.Grid, m::AbstractMaterial, func::Function) = addfaceset!(grid, name(m), func) ``` ```julia """ - `name(p::AbstractParameter)` - `set!(p::AbstractParameter{N}, x::N)::x` - `isassigned(p::AbstractParameter)::Bool` - `get(p::AbstractParameter{N})::Union{N, Missing}` - `range(p::AbstractParameter{N})::Tuple{N,N}` """ abstract type AbstractParameter{N} end mutable struct Parameter{N} <: AbstractParameter{N} val::Union{N,Missing} name::String range::Tuple{N,N} assigned::Bool function Parameter(name::Union{Symbol,String}) new{Float64}(missing, string(name), (-Inf,Inf), false) end function Parameter(val::N, name::Union{Symbol,String}) where {N} new{N}(val, string(name), (-Inf,Inf), true) end function Parameter(val::N, name::Union{Symbol,String}, range::Tuple{N,N}) where {N} new{N}(val, string(name), range, true) end function Parameter(name::Union{Symbol,String}, range::Tuple{N,N}) where {N} new{N}(missing, string(name), range, false) end end # TODO : simplificar los cuatro constructores por uno solo usando valores por defecto # function Parameter(val::Union{N,Missing}=missing, name::Union{Symbol,String}, # range::Union{Tuple{N,N},Missing}=missing, isdefined::Bool=false) where {N} # new{ismissing(val) ? }(missing, string(name), ismissing(range) ? (-Inf,Inf) : range, #ismissing(val)) # end # TODO2: capaz no hace falta guardar assigned como un campo ya que se puede chequear # con una funcion: isassigned(p) = ismissing(p.val) """ Interface functions: - `name(m::AbstractMaterial)::String` - `parameters(m::AbstractMaterial)` Available methods: - `isassigned(m::AbstractMaterial, s::String)::Bool` """ abstract type AbstractMaterial end function isassigned(m::AbstractMaterial, nam) f = findall(p -> nam(p) == n, parameters(m)) @assert length(f) == 1 # no lo encontre o hay mas de uno isassigned(first(f)) end function get(m::AbstractMaterial, nam) f = findall(p -> nam(p) == n, parameters(m)) @assert length(f) == 1 # no lo encontre o hay mas de uno isassigned(first(f)) end # TODO1: hacer un method parameters fallback que usa Base.getfields y ntuple # TODO2: hacer un metodo name generico que usa el nombre (String) del struct correspondiente struct SVK <: AbstractMaterial E::Parameter nu::Parameter end name(::SVK) = "SVK" parameters(m::SVK) = (m.E, m.nu) # energy(m::SVK) = get(m[:E])^2 + get(m[:nu])^2 # USO: # m = SVK(Parameter(:E, -3 .. 3), Parameter(:nu, 1.5)) # get(m[:E]) # value[m[:E]] # set!(m[:E], 1.0) # # Dict(m => (x -> ....)) # TODO Extender `Base.getindex` para que ande m[:E] por lo tanto la implementaciones se simplifican: # isassigned(m::AbstractMaterial, nam) = isassigned(m[name]) ``` ## Implementacion de Parameter ```julia abstract type AbstractParameter{N} end mutable struct Parameter{N} <: AbstractParameter{N} val::Union{N,Missing} name::String range::Tuple{N,N} assigned::Bool function Parameter(name::Union{Symbol,String}) new{Float64}(missing, string(name), (-Inf,Inf), false) end function Parameter(val::N, name::Union{Symbol,String}) where {N} new{N}(val, string(name), (-Inf,Inf), true) end function Parameter(val::N, name::Union{Symbol,String}, range::Tuple{N,N}) where {N} new{N}(val, string(name), range, true) end function Parameter(name::Union{Symbol,String}, range::Tuple{N,N}) where {N} new{N}(missing, string(name), range, false) end end isassigned(p::AbstractParameter) = p.assigned function set!(p::AbstractParameter, x::Number) p.range[1] < x < p.range[2] || throw(ArgumentError("valor no pertenece al rango")) p.val = x p.assigned = true p end function set!(p::AbstractParameter, x::Missing) p.val = missing p.assigned = false p end function get(p::AbstractParameter) !isassigned(p) && throw(ArgumentError("parametro no asignado")) p.val end p = Parameter(:E, (-3.0, 3.0)) set!(p, 1.0) get(p) set!(p, 0.0) get(p) set!(p, missing) get(p) ``` ## Functores ```julia .. AbstractImage .. struct A{N, IT} x::IT end struct A x::Float64 end x = A(1.0) x(1.0) (z::A)(y) = z.x + y x(2.0) evaluar(z::A, y) = z.x + y evaluar(x, 2.0) function _solve(....) ... # agregar un paso .... end function solve(ivp::IVP{<:AbstractContinuousSystem}, alg::AbstractSolver, args...; kwargs...) sdprob = init(ivp, alg, args...; kwargs...) sol = _solve(sdprob.alg, sdprob.ivp, sdprob.NSTEPS; kwargs...) for x in 1... q end end ``` ## Algoritmos genericos ```julia interpolate(data1::MeshGrid, p; kwargs...) = (......, .....) interpolate(data1::MyMesh, p) = (......) solve(alg::MySolver, x, y, z, t) = .. solve(alg::ExternalSolver, ...) = ... (alg::ExternalSolver)(...) = ... # "algoritmo generico" function f(p, data1::AbstractGrid, data2::AbstractImages) x = interpolate(data1, p; kwargs...) for (...) out = alg(args...) end end ```