131 lines
4.2 KiB
Julia
131 lines
4.2 KiB
Julia
# Boundary.jl
|
|
# API of Boundary class, that holds all information for each boundary
|
|
# condition at the edges of the diffusion grid.
|
|
# Translated from C++'s Boundary.hpp.
|
|
|
|
@enum TYPE CLOSED CONSTANT
|
|
@enum SIDE LEFT = 1 RIGHT = 2 TOP = 3 BOTTOM = 4
|
|
|
|
|
|
# BoundaryElement class
|
|
struct BoundaryElement{T}
|
|
type::TYPE
|
|
value::T
|
|
|
|
# Generic constructor for closed case
|
|
BoundaryElement{T}() where {T} = new{T}(CLOSED, convert(T, -1))
|
|
|
|
# Constructor for constant case
|
|
BoundaryElement{T}(value::T) where {T} = new{T}(CONSTANT, value)
|
|
end
|
|
|
|
function getType(be::BoundaryElement{T})::TYPE where {T}
|
|
be.type
|
|
end
|
|
|
|
function getValue(be::BoundaryElement{T})::T where {T}
|
|
be.value
|
|
end
|
|
|
|
function getValue(be::Vector{BoundaryElement{T}})::Vector{T} where {T}
|
|
[b.value for b in be]
|
|
end
|
|
|
|
function setType!(be::BoundaryElement{T}, type::Symbol) where {T}
|
|
be.type = type
|
|
end
|
|
|
|
function setValue!(be::BoundaryElement{T}, value::T) where {T}
|
|
if value < 0
|
|
throw(ArgumentError("No negative concentration allowed."))
|
|
end
|
|
if be.type == BC_TYPE_CLOSED
|
|
throw(ArgumentError("No constant boundary concentrations can be set for closed boundaries. Please change type first."))
|
|
end
|
|
|
|
be.value = value
|
|
end
|
|
|
|
|
|
# Boundary class
|
|
struct Boundary{T}
|
|
dim::UInt8
|
|
cols::UInt32
|
|
rows::UInt32
|
|
boundaries::Vector{Vector{BoundaryElement{T}}}
|
|
|
|
# Constructor
|
|
function Boundary(grid::Grid{T}) where {T}
|
|
dim = grid.dim
|
|
cols = grid.cols
|
|
rows = grid.rows
|
|
boundaries = Vector{Vector{BoundaryElement{T}}}(undef, 4)
|
|
|
|
if dim == 1
|
|
boundaries[Int(LEFT)] = [BoundaryElement{T}()]
|
|
boundaries[Int(RIGHT)] = [BoundaryElement{T}()]
|
|
elseif dim == 2
|
|
boundaries[Int(LEFT)] = [BoundaryElement{T}() for _ in 1:rows]
|
|
boundaries[Int(RIGHT)] = [BoundaryElement{T}() for _ in 1:rows]
|
|
boundaries[Int(TOP)] = [BoundaryElement{T}() for _ in 1:cols]
|
|
boundaries[Int(BOTTOM)] = [BoundaryElement{T}() for _ in 1:cols]
|
|
else
|
|
throw(ArgumentError("Only 1- and 2-dimensional grids are defined!"))
|
|
end
|
|
|
|
new{T}(dim, cols, rows, boundaries)
|
|
end
|
|
end
|
|
|
|
function getBoundaryElementType(boundary::Boundary{T}, side::SIDE, index::Int)::TYPE where {T}
|
|
if boundary.dim == 1 && (side == BOTTOM || side == TOP)
|
|
throw(ArgumentError("For the one-dimensional case, only the left and right borders exist."))
|
|
end
|
|
if index < 1 || index > (side in (LEFT, RIGHT) ? boundary.rows : boundary.cols)
|
|
throw(ArgumentError("Index out of bounds!"))
|
|
end
|
|
|
|
getType(boundary.boundaries[Int(side)][index])
|
|
end
|
|
|
|
function getBoundaryElementValue(boundary::Boundary{T}, side::SIDE, index::Int)::T where {T}
|
|
if boundary.dim == 1 && (side == BOTTOM || side == TOP)
|
|
throw(ArgumentError("For the one-dimensional case, only the left and right borders exist."))
|
|
end
|
|
if index < 1 || index > (side in (LEFT, RIGHT) ? boundary.rows : boundary.cols)
|
|
throw(ArgumentError("Index out of bounds!"))
|
|
end
|
|
|
|
getValue(boundary.boundaries[Int(side)][index])
|
|
end
|
|
|
|
function getBoundarySide(boundary::Boundary{T}, side::SIDE)::Vector{BoundaryElement{T}} where {T}
|
|
if boundary.dim == 1 && (side == BOTTOM || side == TOP)
|
|
throw(ArgumentError("For the one-dimensional case, only the left and right borders exist."))
|
|
end
|
|
|
|
boundary.boundaries[Int(side)]
|
|
end
|
|
|
|
function setBoundarySideClosed!(boundary::Boundary{T}, side::SIDE) where {T}
|
|
if boundary.dim == 1 && (side == BOTTOM || side == TOP)
|
|
throw(ArgumentError("For the one-dimensional case, only the left and right borders exist."))
|
|
end
|
|
|
|
is_vertical = side in (LEFT, RIGHT)
|
|
n = is_vertical ? boundary.rows : boundary.cols
|
|
|
|
boundary.boundaries[Int(side)] = [BoundaryElement{T}() for _ in 1:n]
|
|
end
|
|
|
|
function setBoundarySideConstant!(boundary::Boundary{T}, side::SIDE, value::T) where {T}
|
|
if boundary.dim == 1 && (side == BOTTOM || side == TOP)
|
|
throw(ArgumentError("For the one-dimensional case, only the left and right borders exist."))
|
|
end
|
|
|
|
is_vertical = side in (LEFT, RIGHT)
|
|
n = is_vertical ? boundary.rows : boundary.cols
|
|
|
|
boundary.boundaries[Int(side)] = [BoundaryElement{T}(value) for _ in 1:n]
|
|
end
|