Try   HackMD
tags: Curso Julia

Interfaces - Materialis.jl

Forward problem

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)
"""
- `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

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

.. 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

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