feat: added option to modify singular boundary elements
This commit is contained in:
parent
7abc911a09
commit
28cb5416f5
@ -289,3 +289,37 @@ function setBoundarySideConstant!(
|
|||||||
|
|
||||||
boundary.boundaries[Int(side)] = [BoundaryElement{T}(value) for _ = 1:n]
|
boundary.boundaries[Int(side)] = [BoundaryElement{T}(value) for _ = 1:n]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
"""
|
||||||
|
setBoundarySideElement(boundary::Boundary{T}, side::SIDE, index::Int, be::BoundaryElement{T})::BoundaryElement{T} where {T}
|
||||||
|
|
||||||
|
Sets the boundary element at the specified side and index.
|
||||||
|
|
||||||
|
# Arguments
|
||||||
|
- `boundary::Boundary{T}`: The boundary.
|
||||||
|
- `side::SIDE`: The side of the boundary.
|
||||||
|
- `index::Int`: The index of the boundary element.
|
||||||
|
- `be::BoundaryElement{T}`: The boundary element.
|
||||||
|
|
||||||
|
# Returns
|
||||||
|
The boundary element at the specified side and index.
|
||||||
|
"""
|
||||||
|
function setBoundarySideElement(
|
||||||
|
boundary::Boundary{T},
|
||||||
|
side::SIDE,
|
||||||
|
index::Int,
|
||||||
|
be::BoundaryElement{T},
|
||||||
|
)::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
|
||||||
|
if index < 1 || index > (side in (LEFT, RIGHT) ? boundary.rows : boundary.cols)
|
||||||
|
throw(ArgumentError("Index out of bounds!"))
|
||||||
|
end
|
||||||
|
|
||||||
|
boundary.boundaries[Int(side)][index] = be
|
||||||
|
end
|
||||||
|
|||||||
@ -37,7 +37,6 @@ function createCoeffMatrix(
|
|||||||
rowIndex::Int,
|
rowIndex::Int,
|
||||||
sx::T,
|
sx::T,
|
||||||
)::Tridiagonal{T} where {T}
|
)::Tridiagonal{T} where {T}
|
||||||
# Determine left side boundary coefficients based on boundary condition
|
|
||||||
centerCoeffTop, rightCoeffTop = calcBoundaryCoeff(
|
centerCoeffTop, rightCoeffTop = calcBoundaryCoeff(
|
||||||
alpha[rowIndex, 1],
|
alpha[rowIndex, 1],
|
||||||
alpha[rowIndex, 2],
|
alpha[rowIndex, 2],
|
||||||
@ -45,7 +44,6 @@ function createCoeffMatrix(
|
|||||||
getType(bcLeft[rowIndex]),
|
getType(bcLeft[rowIndex]),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Determine right side boundary coefficients based on boundary condition
|
|
||||||
centerCoeffBottom, leftCoeffBottom = calcBoundaryCoeff(
|
centerCoeffBottom, leftCoeffBottom = calcBoundaryCoeff(
|
||||||
alpha[rowIndex, numCols],
|
alpha[rowIndex, numCols],
|
||||||
alpha[rowIndex, numCols-1],
|
alpha[rowIndex, numCols-1],
|
||||||
@ -95,7 +93,6 @@ function calcExplicitConcentrationsBoundaryClosed(
|
|||||||
return (sy .* alpha .+ (1 .- sy .* alpha)) .* conc_center
|
return (sy .* alpha .+ (1 .- sy .* alpha)) .* conc_center
|
||||||
end
|
end
|
||||||
|
|
||||||
# creates a solution vector for next time step from the current state of concentrations
|
|
||||||
function writeSolutionVector!(
|
function writeSolutionVector!(
|
||||||
sv::Vector{T},
|
sv::Vector{T},
|
||||||
concentrations::Matrix{T},
|
concentrations::Matrix{T},
|
||||||
@ -112,7 +109,6 @@ function writeSolutionVector!(
|
|||||||
numRows = size(concentrations, 1)
|
numRows = size(concentrations, 1)
|
||||||
length = size(sv, 1)
|
length = size(sv, 1)
|
||||||
|
|
||||||
# First row
|
|
||||||
if rowIndex == 1
|
if rowIndex == 1
|
||||||
@inbounds for i = 1:length
|
@inbounds for i = 1:length
|
||||||
if getType(bcTop[i]) == CONSTANT
|
if getType(bcTop[i]) == CONSTANT
|
||||||
@ -136,14 +132,13 @@ function writeSolutionVector!(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Inner rows
|
|
||||||
if rowIndex > 1 && rowIndex < numRows
|
if rowIndex > 1 && rowIndex < numRows
|
||||||
@inbounds for i = 1:length
|
@inbounds for i = 1:length
|
||||||
alpha_here_below =
|
alpha_here_below =
|
||||||
calcAlphaIntercell(alphaY[rowIndex, i], alphaY[rowIndex+1, i])
|
calcAlphaIntercell(alphaY[rowIndex, i], alphaY[rowIndex+1, i])
|
||||||
alpha_here_above =
|
alpha_here_above =
|
||||||
alphaY[rowIndex+1, i] == alphaY[rowIndex-1, i] ? alpha_here_below :
|
alphaY[rowIndex+1, i] == alphaY[rowIndex-1, i] ? alpha_here_below :
|
||||||
calcAlphaIntercell(alphaY[rowIndex-1, i], alphaY[rowIndex, i]) # calcAlphaIntercell is symmetric, so we can use it for both directions
|
calcAlphaIntercell(alphaY[rowIndex-1, i], alphaY[rowIndex, i])
|
||||||
sv[i] =
|
sv[i] =
|
||||||
sy * alpha_here_below * concentrations[rowIndex+1, i] +
|
sy * alpha_here_below * concentrations[rowIndex+1, i] +
|
||||||
(1 - sy * (alpha_here_below + alpha_here_above)) *
|
(1 - sy * (alpha_here_below + alpha_here_above)) *
|
||||||
@ -152,7 +147,6 @@ function writeSolutionVector!(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Last row
|
|
||||||
if rowIndex == numRows
|
if rowIndex == numRows
|
||||||
@inbounds for i = 1:length
|
@inbounds for i = 1:length
|
||||||
if getType(bcBottom[i]) == CONSTANT
|
if getType(bcBottom[i]) == CONSTANT
|
||||||
@ -176,12 +170,10 @@ function writeSolutionVector!(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# First column - additional fixed concentration change from perpendicular dimension in constant BC case
|
|
||||||
if getType(bcLeft[rowIndex]) == CONSTANT
|
if getType(bcLeft[rowIndex]) == CONSTANT
|
||||||
sv[1] += 2 * sx * alphaX[rowIndex, 1] * getValue(bcLeft[rowIndex])
|
sv[1] += 2 * sx * alphaX[rowIndex, 1] * getValue(bcLeft[rowIndex])
|
||||||
end
|
end
|
||||||
|
|
||||||
# Last column - additional fixed concentration change from perpendicular dimension in constant BC case
|
|
||||||
if getType(bcRight[rowIndex]) == CONSTANT
|
if getType(bcRight[rowIndex]) == CONSTANT
|
||||||
sv[end] += 2 * sx * alphaX[rowIndex, end] * getValue(bcRight[rowIndex])
|
sv[end] += 2 * sx * alphaX[rowIndex, end] * getValue(bcRight[rowIndex])
|
||||||
end
|
end
|
||||||
|
|||||||
@ -14,7 +14,6 @@ function calcHorizontalChange(
|
|||||||
concentration_prev::T,
|
concentration_prev::T,
|
||||||
concentration_current::T,
|
concentration_current::T,
|
||||||
) where {T}
|
) where {T}
|
||||||
|
|
||||||
intercellAlpha_next = calcAlphaIntercell(alphaX_next, alphaX_current)
|
intercellAlpha_next = calcAlphaIntercell(alphaX_next, alphaX_current)
|
||||||
intercellAlpha_prev = calcAlphaIntercell(alphaX_prev, alphaX_current)
|
intercellAlpha_prev = calcAlphaIntercell(alphaX_prev, alphaX_current)
|
||||||
|
|
||||||
@ -134,7 +133,6 @@ function FTCS_1D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
|
|
||||||
row = 1
|
row = 1
|
||||||
|
|
||||||
# inner cells
|
|
||||||
for col = 2:colMax-1
|
for col = 2:colMax-1
|
||||||
concentrations_t1[row, col] +=
|
concentrations_t1[row, col] +=
|
||||||
sx * calcHorizontalChange(
|
sx * calcHorizontalChange(
|
||||||
@ -147,7 +145,6 @@ function FTCS_1D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# left boundary
|
|
||||||
leftBoundaryType = getBoundaryElementType(bc, LEFT, row)
|
leftBoundaryType = getBoundaryElementType(bc, LEFT, row)
|
||||||
leftBoundaryValue = getBoundaryElementValue(bc, LEFT, row)
|
leftBoundaryValue = getBoundaryElementValue(bc, LEFT, row)
|
||||||
concentrations_t1[row, 1] +=
|
concentrations_t1[row, 1] +=
|
||||||
@ -160,7 +157,6 @@ function FTCS_1D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
leftBoundaryValue,
|
leftBoundaryValue,
|
||||||
)
|
)
|
||||||
|
|
||||||
# right boundary
|
|
||||||
rightBoundaryType = getBoundaryElementType(bc, RIGHT, row)
|
rightBoundaryType = getBoundaryElementType(bc, RIGHT, row)
|
||||||
rightBoundaryValue = getBoundaryElementValue(bc, RIGHT, row)
|
rightBoundaryValue = getBoundaryElementValue(bc, RIGHT, row)
|
||||||
concentrations_t1[row, colMax] +=
|
concentrations_t1[row, colMax] +=
|
||||||
@ -187,12 +183,6 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
concentrations = getConcentrations(grid)
|
concentrations = getConcentrations(grid)
|
||||||
concentrations_t1 = copy(concentrations)
|
concentrations_t1 = copy(concentrations)
|
||||||
|
|
||||||
# Currently boundary sides can only be set for the whole side, not for each cell individually
|
|
||||||
leftBoundaryType = getBoundaryElementType(bc, LEFT, 1)
|
|
||||||
rightBoundaryType = getBoundaryElementType(bc, RIGHT, 1)
|
|
||||||
topBoundaryType = getBoundaryElementType(bc, TOP, 1)
|
|
||||||
bottomBoundaryType = getBoundaryElementType(bc, BOTTOM, 1)
|
|
||||||
|
|
||||||
Threads.@threads for row = 2:rowMax-1
|
Threads.@threads for row = 2:rowMax-1
|
||||||
for col = 2:colMax-1
|
for col = 2:colMax-1
|
||||||
concentrations_t1[row, col] +=
|
concentrations_t1[row, col] +=
|
||||||
@ -214,17 +204,14 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Boundary conditions for each row
|
|
||||||
# Left boundary without corners
|
|
||||||
leftBoundaryValue = getBoundaryElementValue(bc, LEFT, row)
|
|
||||||
concentrations_t1[row, 1] +=
|
concentrations_t1[row, 1] +=
|
||||||
sx * calcHorizontalChangeLeftBoundary(
|
sx * calcHorizontalChangeLeftBoundary(
|
||||||
leftBoundaryType,
|
getBoundaryElementType(bc, LEFT, row),
|
||||||
alphaX[row, 2],
|
alphaX[row, 2],
|
||||||
alphaX[row, 1],
|
alphaX[row, 1],
|
||||||
concentrations[row, 2],
|
concentrations[row, 2],
|
||||||
concentrations[row, 1],
|
concentrations[row, 1],
|
||||||
leftBoundaryValue,
|
getBoundaryElementValue(bc, LEFT, row),
|
||||||
) +
|
) +
|
||||||
sy * calcVerticalChange(
|
sy * calcVerticalChange(
|
||||||
alphaY[row+1, 1],
|
alphaY[row+1, 1],
|
||||||
@ -235,16 +222,14 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
concentrations[row, 1],
|
concentrations[row, 1],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Right boundary without corners
|
|
||||||
rightBoundaryValue = getBoundaryElementValue(bc, RIGHT, row)
|
|
||||||
concentrations_t1[row, colMax] +=
|
concentrations_t1[row, colMax] +=
|
||||||
sx * calcHorizontalChangeRightBoundary(
|
sx * calcHorizontalChangeRightBoundary(
|
||||||
rightBoundaryType,
|
getBoundaryElementType(bc, RIGHT, row),
|
||||||
alphaX[row, colMax-1],
|
alphaX[row, colMax-1],
|
||||||
alphaX[row, colMax],
|
alphaX[row, colMax],
|
||||||
concentrations[row, colMax-1],
|
concentrations[row, colMax-1],
|
||||||
concentrations[row, colMax],
|
concentrations[row, colMax],
|
||||||
rightBoundaryValue,
|
getBoundaryElementValue(bc, RIGHT, row),
|
||||||
) +
|
) +
|
||||||
sy * calcVerticalChange(
|
sy * calcVerticalChange(
|
||||||
alphaY[row+1, colMax],
|
alphaY[row+1, colMax],
|
||||||
@ -256,18 +241,15 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Handle top/bottom boundaries
|
|
||||||
Threads.@threads for col = 2:colMax-1
|
Threads.@threads for col = 2:colMax-1
|
||||||
# Top boundary
|
|
||||||
topBoundaryValue = getBoundaryElementValue(bc, TOP, col)
|
|
||||||
concentrations_t1[1, col] +=
|
concentrations_t1[1, col] +=
|
||||||
sy * calcVerticalChangeTopBoundary(
|
sy * calcVerticalChangeTopBoundary(
|
||||||
topBoundaryType,
|
getBoundaryElementType(bc, TOP, col),
|
||||||
alphaY[2, col],
|
alphaY[2, col],
|
||||||
alphaY[1, col],
|
alphaY[1, col],
|
||||||
concentrations[2, col],
|
concentrations[2, col],
|
||||||
concentrations[1, col],
|
concentrations[1, col],
|
||||||
topBoundaryValue,
|
getBoundaryElementValue(bc, TOP, col),
|
||||||
) +
|
) +
|
||||||
sx * calcHorizontalChange(
|
sx * calcHorizontalChange(
|
||||||
alphaX[1, col+1],
|
alphaX[1, col+1],
|
||||||
@ -278,16 +260,14 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
concentrations[1, col],
|
concentrations[1, col],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Bottom boundary
|
|
||||||
bottomBoundaryValue = getBoundaryElementValue(bc, BOTTOM, col)
|
|
||||||
concentrations_t1[rowMax, col] +=
|
concentrations_t1[rowMax, col] +=
|
||||||
sy * calcVerticalChangeBottomBoundary(
|
sy * calcVerticalChangeBottomBoundary(
|
||||||
bottomBoundaryType,
|
getBoundaryElementType(bc, BOTTOM, col),
|
||||||
alphaY[rowMax, col],
|
alphaY[rowMax, col],
|
||||||
alphaY[rowMax-1, col],
|
alphaY[rowMax-1, col],
|
||||||
concentrations[rowMax, col],
|
concentrations[rowMax, col],
|
||||||
concentrations[rowMax-1, col],
|
concentrations[rowMax-1, col],
|
||||||
bottomBoundaryValue,
|
getBoundaryElementValue(bc, BOTTOM, col),
|
||||||
) +
|
) +
|
||||||
sx * calcHorizontalChange(
|
sx * calcHorizontalChange(
|
||||||
alphaX[rowMax, col+1],
|
alphaX[rowMax, col+1],
|
||||||
@ -299,9 +279,6 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Handle corners
|
|
||||||
# Top left corner
|
|
||||||
topBoundaryValue = getBoundaryElementValue(bc, TOP, 1)
|
|
||||||
concentrations_t1[1, 1] +=
|
concentrations_t1[1, 1] +=
|
||||||
sx * calcHorizontalChange(
|
sx * calcHorizontalChange(
|
||||||
alphaX[1, 2],
|
alphaX[1, 2],
|
||||||
@ -312,16 +289,14 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
concentrations[1, 1],
|
concentrations[1, 1],
|
||||||
) +
|
) +
|
||||||
sy * calcVerticalChangeTopBoundary(
|
sy * calcVerticalChangeTopBoundary(
|
||||||
topBoundaryType,
|
getBoundaryElementType(bc, TOP, 1),
|
||||||
alphaY[2, 1],
|
alphaY[2, 1],
|
||||||
alphaY[1, 1],
|
alphaY[1, 1],
|
||||||
concentrations[2, 1],
|
concentrations[2, 1],
|
||||||
concentrations[1, 1],
|
concentrations[1, 1],
|
||||||
topBoundaryValue,
|
getBoundaryElementValue(bc, TOP, 1),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Top right corner
|
|
||||||
topBoundaryValue = getBoundaryElementValue(bc, TOP, colMax)
|
|
||||||
concentrations_t1[1, colMax] +=
|
concentrations_t1[1, colMax] +=
|
||||||
sx * calcHorizontalChange(
|
sx * calcHorizontalChange(
|
||||||
alphaX[1, colMax-1],
|
alphaX[1, colMax-1],
|
||||||
@ -332,16 +307,14 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
concentrations[1, colMax],
|
concentrations[1, colMax],
|
||||||
) +
|
) +
|
||||||
sy * calcVerticalChangeTopBoundary(
|
sy * calcVerticalChangeTopBoundary(
|
||||||
topBoundaryType,
|
getBoundaryElementType(bc, TOP, colMax),
|
||||||
alphaY[2, colMax],
|
alphaY[2, colMax],
|
||||||
alphaY[1, colMax],
|
alphaY[1, colMax],
|
||||||
concentrations[2, colMax],
|
concentrations[2, colMax],
|
||||||
concentrations[1, colMax],
|
concentrations[1, colMax],
|
||||||
topBoundaryValue,
|
getBoundaryElementValue(bc, TOP, colMax),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Bottom left corner
|
|
||||||
bottomBoundaryValue = getBoundaryElementValue(bc, BOTTOM, 1)
|
|
||||||
concentrations_t1[rowMax, 1] +=
|
concentrations_t1[rowMax, 1] +=
|
||||||
sx * calcHorizontalChange(
|
sx * calcHorizontalChange(
|
||||||
alphaX[rowMax, 2],
|
alphaX[rowMax, 2],
|
||||||
@ -352,16 +325,14 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
concentrations[rowMax, 1],
|
concentrations[rowMax, 1],
|
||||||
) +
|
) +
|
||||||
sy * calcVerticalChangeBottomBoundary(
|
sy * calcVerticalChangeBottomBoundary(
|
||||||
bottomBoundaryType,
|
getBoundaryElementType(bc, BOTTOM, 1),
|
||||||
alphaY[rowMax, 1],
|
alphaY[rowMax, 1],
|
||||||
alphaY[rowMax-1, 1],
|
alphaY[rowMax-1, 1],
|
||||||
concentrations[rowMax, 1],
|
concentrations[rowMax, 1],
|
||||||
concentrations[rowMax-1, 1],
|
concentrations[rowMax-1, 1],
|
||||||
bottomBoundaryValue,
|
getBoundaryElementValue(bc, BOTTOM, 1),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Bottom right corner
|
|
||||||
bottomBoundaryValue = getBoundaryElementValue(bc, BOTTOM, colMax)
|
|
||||||
concentrations_t1[rowMax, colMax] +=
|
concentrations_t1[rowMax, colMax] +=
|
||||||
sx * calcHorizontalChange(
|
sx * calcHorizontalChange(
|
||||||
alphaX[rowMax, colMax-1],
|
alphaX[rowMax, colMax-1],
|
||||||
@ -372,12 +343,12 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
|
|||||||
concentrations[rowMax, colMax],
|
concentrations[rowMax, colMax],
|
||||||
) +
|
) +
|
||||||
sy * calcVerticalChangeBottomBoundary(
|
sy * calcVerticalChangeBottomBoundary(
|
||||||
bottomBoundaryType,
|
getBoundaryElementType(bc, BOTTOM, colMax),
|
||||||
alphaY[rowMax, colMax],
|
alphaY[rowMax, colMax],
|
||||||
alphaY[rowMax-1, colMax],
|
alphaY[rowMax-1, colMax],
|
||||||
concentrations[rowMax, colMax],
|
concentrations[rowMax, colMax],
|
||||||
concentrations[rowMax-1, colMax],
|
concentrations[rowMax-1, colMax],
|
||||||
bottomBoundaryValue,
|
getBoundaryElementValue(bc, BOTTOM, colMax),
|
||||||
)
|
)
|
||||||
|
|
||||||
setConcentrations!(grid, concentrations_t1)
|
setConcentrations!(grid, concentrations_t1)
|
||||||
|
|||||||
@ -24,11 +24,12 @@ export Boundary,
|
|||||||
BoundaryElement, TYPE, SIDE, BC_TYPE_CLOSED, BC_TYPE_CONSTANT, LEFT, RIGHT, TOP, BOTTOM
|
BoundaryElement, TYPE, SIDE, BC_TYPE_CLOSED, BC_TYPE_CONSTANT, LEFT, RIGHT, TOP, BOTTOM
|
||||||
export getType,
|
export getType,
|
||||||
getValue,
|
getValue,
|
||||||
setBoundarySideClosed!,
|
|
||||||
setBoundarySideConstant!,
|
|
||||||
getBoundarySide,
|
getBoundarySide,
|
||||||
getBoundaryElementType,
|
getBoundaryElementType,
|
||||||
getBoundaryElementValue
|
getBoundaryElementValue,
|
||||||
|
setBoundarySideClosed!,
|
||||||
|
setBoundarySideConstant!,
|
||||||
|
setBoundarySideElement
|
||||||
|
|
||||||
include("AbstractSimulation.jl")
|
include("AbstractSimulation.jl")
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user