style: applied linting recommendations

This commit is contained in:
nebmit 2023-12-04 19:21:23 +01:00
parent 1e57d8b5b5
commit 39eacff904
No known key found for this signature in database
10 changed files with 922 additions and 178 deletions

View File

@ -32,7 +32,13 @@ Enum representing the level of CSV file output for the simulation.
abstract type AbstractSimulation{T} end abstract type AbstractSimulation{T} end
function adjustTimestep(grid::Grid{T}, approach::APPROACH, timestep::T, iterations::Int, verbose::Bool)::Tuple{T,Int} where {T} function adjustTimestep(
grid::Grid{T},
approach::APPROACH,
timestep::T,
iterations::Int,
verbose::Bool,
)::Tuple{T,Int} where {T}
if approach == FTCS if approach == FTCS
if getDim(grid) == 1 if getDim(grid) == 1
deltaSquare = getDeltaCol(grid) deltaSquare = getDeltaCol(grid)
@ -55,7 +61,13 @@ function adjustTimestep(grid::Grid{T}, approach::APPROACH, timestep::T, iteratio
iterations = iterations * innerIterations iterations = iterations * innerIterations
timestep = timestep / innerIterations timestep = timestep / innerIterations
if verbose if verbose
println("Warning: Timestep is too large for FTCS approach. Adjusting timestep to ", timestep, " and iterations to ", iterations, ".") println(
"Warning: Timestep is too large for FTCS approach. Adjusting timestep to ",
timestep,
" and iterations to ",
iterations,
".",
)
end end
else else
timestep = timestep timestep = timestep
@ -64,7 +76,10 @@ function adjustTimestep(grid::Grid{T}, approach::APPROACH, timestep::T, iteratio
return timestep, iterations return timestep, iterations
end end
function createCSVfile(simulation::AbstractSimulation{T}, grid::Union{Grid{T},Nothing}=nothing) where {T} function createCSVfile(
simulation::AbstractSimulation{T},
grid::Union{Grid{T},Nothing} = nothing,
) where {T}
grid = grid === nothing ? simulation.grid : grid grid = grid === nothing ? simulation.grid : grid
approachString = string(simulation.approach) approachString = string(simulation.approach)
rows = getRows(grid) rows = getRows(grid)
@ -76,7 +91,18 @@ function createCSVfile(simulation::AbstractSimulation{T}, grid::Union{Grid{T},No
appendIdent = 0 appendIdent = 0
while isfile(filename) while isfile(filename)
appendIdent += 1 appendIdent += 1
filename = string(approachString, "_", rows, "_", cols, "_", numIterations, "-", appendIdent, ".csv") filename = string(
approachString,
"_",
rows,
"_",
cols,
"_",
numIterations,
"-",
appendIdent,
".csv",
)
end end
# Write boundary conditions if required # Write boundary conditions if required
@ -103,12 +129,19 @@ function writeBoundarySideValuesToCSV(file::IOStream, bc::Boundary{T}, side) whe
write(file, formatted_values, "\n") write(file, formatted_values, "\n")
end end
function writeConcentrationsToCLI(simulation::AbstractSimulation{T}, grid::Union{Grid{T},Nothing}=nothing) where {T} function writeConcentrationsToCLI(
simulation::AbstractSimulation{T},
grid::Union{Grid{T},Nothing} = nothing,
) where {T}
grid = grid === nothing ? simulation.grid : grid grid = grid === nothing ? simulation.grid : grid
println(getConcentrations(grid)) println(getConcentrations(grid))
end end
function writeConcentrationsToCSV(file::IOStream, simulation::AbstractSimulation{T}, grid::Union{Grid{T},Nothing}=nothing) where {T} function writeConcentrationsToCSV(
file::IOStream,
simulation::AbstractSimulation{T},
grid::Union{Grid{T},Nothing} = nothing,
) where {T}
grid = grid === nothing ? simulation.grid : grid grid = grid === nothing ? simulation.grid : grid
concentrations = getConcentrations(grid) concentrations = getConcentrations(grid)

View File

@ -128,10 +128,10 @@ struct Boundary{T}
boundaries[Int(LEFT)] = [BoundaryElement{T}()] boundaries[Int(LEFT)] = [BoundaryElement{T}()]
boundaries[Int(RIGHT)] = [BoundaryElement{T}()] boundaries[Int(RIGHT)] = [BoundaryElement{T}()]
elseif dim == 2 elseif dim == 2
boundaries[Int(LEFT)] = [BoundaryElement{T}() for _ in 1:rows] boundaries[Int(LEFT)] = [BoundaryElement{T}() for _ = 1:rows]
boundaries[Int(RIGHT)] = [BoundaryElement{T}() for _ in 1:rows] boundaries[Int(RIGHT)] = [BoundaryElement{T}() for _ = 1:rows]
boundaries[Int(TOP)] = [BoundaryElement{T}() for _ in 1:cols] boundaries[Int(TOP)] = [BoundaryElement{T}() for _ = 1:cols]
boundaries[Int(BOTTOM)] = [BoundaryElement{T}() for _ in 1:cols] boundaries[Int(BOTTOM)] = [BoundaryElement{T}() for _ = 1:cols]
else else
throw(ArgumentError("Only 1- and 2-dimensional grids are defined!")) throw(ArgumentError("Only 1- and 2-dimensional grids are defined!"))
end end
@ -153,9 +153,17 @@ Retrieves the type of the boundary element at the specified side and index.
# Returns # Returns
The type of the boundary element (`TYPE`). The type of the boundary element (`TYPE`).
""" """
function getBoundaryElementType(boundary::Boundary{T}, side::SIDE, index::Int)::TYPE where {T} function getBoundaryElementType(
boundary::Boundary{T},
side::SIDE,
index::Int,
)::TYPE where {T}
if boundary.dim == 1 && (side == BOTTOM || side == TOP) if boundary.dim == 1 && (side == BOTTOM || side == TOP)
throw(ArgumentError("For the one-dimensional case, only the left and right borders exist.")) throw(
ArgumentError(
"For the one-dimensional case, only the left and right borders exist.",
),
)
end end
if index < 1 || index > (side in (LEFT, RIGHT) ? boundary.rows : boundary.cols) if index < 1 || index > (side in (LEFT, RIGHT) ? boundary.rows : boundary.cols)
throw(ArgumentError("Index out of bounds!")) throw(ArgumentError("Index out of bounds!"))
@ -180,7 +188,11 @@ The value of the boundary element.
""" """
function getBoundaryElementValue(boundary::Boundary{T}, side::SIDE, index::Int)::T where {T} function getBoundaryElementValue(boundary::Boundary{T}, side::SIDE, index::Int)::T where {T}
if boundary.dim == 1 && (side == BOTTOM || side == TOP) if boundary.dim == 1 && (side == BOTTOM || side == TOP)
throw(ArgumentError("For the one-dimensional case, only the left and right borders exist.")) throw(
ArgumentError(
"For the one-dimensional case, only the left and right borders exist.",
),
)
end end
if index < 1 || index > (side in (LEFT, RIGHT) ? boundary.rows : boundary.cols) if index < 1 || index > (side in (LEFT, RIGHT) ? boundary.rows : boundary.cols)
throw(ArgumentError("Index out of bounds!")) throw(ArgumentError("Index out of bounds!"))
@ -201,9 +213,16 @@ Retrieves the boundary elements at the specified side.
# Returns # Returns
The boundary elements at the specified side. The boundary elements at the specified side.
""" """
function getBoundarySide(boundary::Boundary{T}, side::SIDE)::Vector{BoundaryElement{T}} where {T} function getBoundarySide(
boundary::Boundary{T},
side::SIDE,
)::Vector{BoundaryElement{T}} where {T}
if boundary.dim == 1 && (side == BOTTOM || side == TOP) if boundary.dim == 1 && (side == BOTTOM || side == TOP)
throw(ArgumentError("For the one-dimensional case, only the left and right borders exist.")) throw(
ArgumentError(
"For the one-dimensional case, only the left and right borders exist.",
),
)
end end
boundary.boundaries[Int(side)] boundary.boundaries[Int(side)]
@ -221,15 +240,22 @@ Sets the boundary elements at the specified side to CLOSED.
# Returns # Returns
The boundary elements at the specified side. The boundary elements at the specified side.
""" """
function setBoundarySideClosed!(boundary::Boundary{T}, side::SIDE)::Vector{BoundaryElement{T}} where {T} function setBoundarySideClosed!(
boundary::Boundary{T},
side::SIDE,
)::Vector{BoundaryElement{T}} where {T}
if boundary.dim == 1 && (side == BOTTOM || side == TOP) if boundary.dim == 1 && (side == BOTTOM || side == TOP)
throw(ArgumentError("For the one-dimensional case, only the left and right borders exist.")) throw(
ArgumentError(
"For the one-dimensional case, only the left and right borders exist.",
),
)
end end
is_vertical = side in (LEFT, RIGHT) is_vertical = side in (LEFT, RIGHT)
n = is_vertical ? boundary.rows : boundary.cols n = is_vertical ? boundary.rows : boundary.cols
boundary.boundaries[Int(side)] = [BoundaryElement{T}() for _ in 1:n] boundary.boundaries[Int(side)] = [BoundaryElement{T}() for _ = 1:n]
end end
""" """
@ -245,13 +271,21 @@ Sets the boundary elements at the specified side to CONSTANT with the specified
# Returns # Returns
The boundary elements at the specified side. The boundary elements at the specified side.
""" """
function setBoundarySideConstant!(boundary::Boundary{T}, side::SIDE, value::T)::Vector{BoundaryElement{T}} where {T} function setBoundarySideConstant!(
boundary::Boundary{T},
side::SIDE,
value::T,
)::Vector{BoundaryElement{T}} where {T}
if boundary.dim == 1 && (side == BOTTOM || side == TOP) if boundary.dim == 1 && (side == BOTTOM || side == TOP)
throw(ArgumentError("For the one-dimensional case, only the left and right borders exist.")) throw(
ArgumentError(
"For the one-dimensional case, only the left and right borders exist.",
),
)
end end
is_vertical = side in (LEFT, RIGHT) is_vertical = side in (LEFT, RIGHT)
n = is_vertical ? boundary.rows : boundary.cols n = is_vertical ? boundary.rows : boundary.cols
boundary.boundaries[Int(side)] = [BoundaryElement{T}(value) for _ in 1:n] boundary.boundaries[Int(side)] = [BoundaryElement{T}(value) for _ = 1:n]
end end

View File

@ -8,7 +8,12 @@ using Base.Threads
using LinearAlgebra using LinearAlgebra
using SparseArrays using SparseArrays
function calcBoundaryCoeff(alpha_center::T, alpha_side::T, sx::T, bcType::TYPE)::Tuple{T,T} where {T} function calcBoundaryCoeff(
alpha_center::T,
alpha_side::T,
sx::T,
bcType::TYPE,
)::Tuple{T,T} where {T}
alpha = calcAlphaIntercell(alpha_center, alpha_side) alpha = calcAlphaIntercell(alpha_center, alpha_side)
sideCoeff = -sx * alpha sideCoeff = -sx * alpha
@ -23,12 +28,31 @@ function calcBoundaryCoeff(alpha_center::T, alpha_side::T, sx::T, bcType::TYPE):
return (centerCoeff, sideCoeff) return (centerCoeff, sideCoeff)
end end
function createCoeffMatrix(alpha::Matrix{T}, alpha_left::Vector{T}, alpha_right::Vector{T}, bcLeft::Vector{BoundaryElement{T}}, bcRight::Vector{BoundaryElement{T}}, numCols::Int, rowIndex::Int, sx::T)::Tridiagonal{T} where {T} function createCoeffMatrix(
alpha::Matrix{T},
alpha_left::Vector{T},
alpha_right::Vector{T},
bcLeft::Vector{BoundaryElement{T}},
bcRight::Vector{BoundaryElement{T}},
numCols::Int,
rowIndex::Int,
sx::T,
)::Tridiagonal{T} where {T}
# Determine left side boundary coefficients based on boundary condition # Determine left side boundary coefficients based on boundary condition
centerCoeffTop, rightCoeffTop = calcBoundaryCoeff(alpha[rowIndex, 1], alpha[rowIndex, 2], sx, getType(bcLeft[rowIndex])) centerCoeffTop, rightCoeffTop = calcBoundaryCoeff(
alpha[rowIndex, 1],
alpha[rowIndex, 2],
sx,
getType(bcLeft[rowIndex]),
)
# Determine right side boundary coefficients based on boundary condition # Determine right side boundary coefficients based on boundary condition
centerCoeffBottom, leftCoeffBottom = calcBoundaryCoeff(alpha[rowIndex, numCols], alpha[rowIndex, numCols-1], sx, getType(bcRight[rowIndex])) centerCoeffBottom, leftCoeffBottom = calcBoundaryCoeff(
alpha[rowIndex, numCols],
alpha[rowIndex, numCols-1],
sx,
getType(bcRight[rowIndex]),
)
dl = [-sx .* alpha_left; leftCoeffBottom] dl = [-sx .* alpha_left; leftCoeffBottom]
d = [centerCoeffTop; 1 .+ sx .* (alpha_right + alpha_left); centerCoeffBottom] d = [centerCoeffTop; 1 .+ sx .* (alpha_right + alpha_left); centerCoeffBottom]
@ -37,26 +61,55 @@ function createCoeffMatrix(alpha::Matrix{T}, alpha_left::Vector{T}, alpha_right:
end end
function calcExplicitConcentrationsBoundaryClosed(conc_center::T, alpha_center::T, alpha_neighbor::T, sy::T)::T where {T} function calcExplicitConcentrationsBoundaryClosed(
conc_center::T,
alpha_center::T,
alpha_neighbor::T,
sy::T,
)::T where {T}
alpha = calcAlphaIntercell(alpha_center, alpha_neighbor) alpha = calcAlphaIntercell(alpha_center, alpha_neighbor)
return (sy * alpha + (1 - sy * alpha)) * conc_center return (sy * alpha + (1 - sy * alpha)) * conc_center
end end
function calcExplicitConcentrationsBoundaryConstant(conc_center::T, conc_bc::T, alpha_center::T, alpha_neighbor::T, sy::T)::T where {T} function calcExplicitConcentrationsBoundaryConstant(
conc_center::T,
conc_bc::T,
alpha_center::T,
alpha_neighbor::T,
sy::T,
)::T where {T}
alpha_center_neighbor = calcAlphaIntercell(alpha_center, alpha_neighbor) alpha_center_neighbor = calcAlphaIntercell(alpha_center, alpha_neighbor)
alpha_center_center = alpha_center == alpha_neighbor ? alpha_center_neighbor : calcAlphaIntercell(alpha_center, alpha_center) alpha_center_center =
alpha_center == alpha_neighbor ? alpha_center_neighbor :
calcAlphaIntercell(alpha_center, alpha_center)
return sy * alpha_center_neighbor * conc_center + return sy * alpha_center_neighbor * conc_center +
(1 - sy * (alpha_center_center + 2 * alpha_center)) * conc_center + (1 - sy * (alpha_center_center + 2 * alpha_center)) * conc_center +
sy * alpha_center * conc_bc sy * alpha_center * conc_bc
end end
function calcExplicitConcentrationsBoundaryClosed(conc_center::Vector{T}, alpha::Vector{T}, sy::T)::T where {T} function calcExplicitConcentrationsBoundaryClosed(
conc_center::Vector{T},
alpha::Vector{T},
sy::T,
)::T where {T}
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 # creates a solution vector for next time step from the current state of concentrations
function writeSolutionVector!(sv::Vector{T}, concentrations::Matrix{T}, alphaX::Matrix{T}, alphaY::Matrix{T}, bcLeft::Vector{BoundaryElement{T}}, bcRight::Vector{BoundaryElement{T}}, bcTop::Vector{BoundaryElement{T}}, bcBottom::Vector{BoundaryElement{T}}, rowIndex::Int, sx::T, sy::T) where {T} function writeSolutionVector!(
sv::Vector{T},
concentrations::Matrix{T},
alphaX::Matrix{T},
alphaY::Matrix{T},
bcLeft::Vector{BoundaryElement{T}},
bcRight::Vector{BoundaryElement{T}},
bcTop::Vector{BoundaryElement{T}},
bcBottom::Vector{BoundaryElement{T}},
rowIndex::Int,
sx::T,
sy::T,
) where {T}
numRows = size(concentrations, 1) numRows = size(concentrations, 1)
length = size(sv, 1) length = size(sv, 1)
@ -64,9 +117,20 @@ function writeSolutionVector!(sv::Vector{T}, concentrations::Matrix{T}, alphaX::
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
sv[i] = calcExplicitConcentrationsBoundaryConstant(concentrations[rowIndex, i], getValue(bcTop[i]), alphaY[rowIndex, i], alphaY[rowIndex+1, i], sy) sv[i] = calcExplicitConcentrationsBoundaryConstant(
concentrations[rowIndex, i],
getValue(bcTop[i]),
alphaY[rowIndex, i],
alphaY[rowIndex+1, i],
sy,
)
elseif getType(bcTop[i]) == CLOSED elseif getType(bcTop[i]) == CLOSED
sv[i] = calcExplicitConcentrationsBoundaryClosed(concentrations[rowIndex, i], alphaY[rowIndex, i], alphaY[rowIndex+1, i], sy) sv[i] = calcExplicitConcentrationsBoundaryClosed(
concentrations[rowIndex, i],
alphaY[rowIndex, i],
alphaY[rowIndex+1, i],
sy,
)
else else
error("Undefined Boundary Condition Type somewhere on Left or Top!") error("Undefined Boundary Condition Type somewhere on Left or Top!")
end end
@ -76,11 +140,16 @@ function writeSolutionVector!(sv::Vector{T}, concentrations::Matrix{T}, alphaX::
# Inner rows # 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 = calcAlphaIntercell(alphaY[rowIndex, i], alphaY[rowIndex+1, i]) alpha_here_below =
alpha_here_above = 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, i], alphaY[rowIndex+1, i])
sv[i] = sy * alpha_here_below * concentrations[rowIndex+1, i] + alpha_here_above =
(1 - sy * (alpha_here_below + alpha_here_above)) * concentrations[rowIndex, i] + alphaY[rowIndex+1, i] == alphaY[rowIndex-1, i] ? alpha_here_below :
sy * alpha_here_above * concentrations[rowIndex-1, i] calcAlphaIntercell(alphaY[rowIndex-1, i], alphaY[rowIndex, i]) # calcAlphaIntercell is symmetric, so we can use it for both directions
sv[i] =
sy * alpha_here_below * concentrations[rowIndex+1, i] +
(1 - sy * (alpha_here_below + alpha_here_above)) *
concentrations[rowIndex, i] +
sy * alpha_here_above * concentrations[rowIndex-1, i]
end end
end end
@ -88,9 +157,20 @@ function writeSolutionVector!(sv::Vector{T}, concentrations::Matrix{T}, alphaX::
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
sv[i] = calcExplicitConcentrationsBoundaryConstant(concentrations[rowIndex, i], getValue(bcBottom[i]), alphaY[rowIndex, i], alphaY[rowIndex-1, i], sy) sv[i] = calcExplicitConcentrationsBoundaryConstant(
concentrations[rowIndex, i],
getValue(bcBottom[i]),
alphaY[rowIndex, i],
alphaY[rowIndex-1, i],
sy,
)
elseif getType(bcBottom[i]) == CLOSED elseif getType(bcBottom[i]) == CLOSED
sv[i] = calcExplicitConcentrationsBoundaryClosed(concentrations[rowIndex, i], alphaY[rowIndex, i], alphaY[rowIndex-1, i], sy) sv[i] = calcExplicitConcentrationsBoundaryClosed(
concentrations[rowIndex, i],
alphaY[rowIndex, i],
alphaY[rowIndex-1, i],
sy,
)
else else
error("Undefined Boundary Condition Type somewhere on Right or Bottom!") error("Undefined Boundary Condition Type somewhere on Right or Bottom!")
end end
@ -108,7 +188,13 @@ function writeSolutionVector!(sv::Vector{T}, concentrations::Matrix{T}, alphaX::
end end
end end
function BTCS_1D(grid::Grid{T}, bc::Boundary{T}, alpha_left::Matrix{T}, alpha_right::Matrix{T}, timestep::T) where {T} function BTCS_1D(
grid::Grid{T},
bc::Boundary{T},
alpha_left::Matrix{T},
alpha_right::Matrix{T},
timestep::T,
) where {T}
sx = timestep / (getDeltaCol(grid) * getDeltaCol(grid)) sx = timestep / (getDeltaCol(grid) * getDeltaCol(grid))
alpha = getAlphaX(grid) alpha = getAlphaX(grid)
@ -118,7 +204,16 @@ function BTCS_1D(grid::Grid{T}, bc::Boundary{T}, alpha_left::Matrix{T}, alpha_ri
concentrations::Matrix{T} = getConcentrations(grid) concentrations::Matrix{T} = getConcentrations(grid)
A::Tridiagonal{T} = createCoeffMatrix(alpha, alpha_left[1, :], alpha_right[1, :], bcLeft, bcRight, length, 1, sx) A::Tridiagonal{T} = createCoeffMatrix(
alpha,
alpha_left[1, :],
alpha_right[1, :],
bcLeft,
bcRight,
length,
1,
sx,
)
b = concentrations[1, :] b = concentrations[1, :]
if getType(bcLeft[1]) == CONSTANT if getType(bcLeft[1]) == CONSTANT
@ -131,7 +226,15 @@ function BTCS_1D(grid::Grid{T}, bc::Boundary{T}, alpha_left::Matrix{T}, alpha_ri
concentrations[1, :] = A \ b concentrations[1, :] = A \ b
end end
function BTCS_2D(grid::Grid{T}, bc::Boundary{T}, alphaX_left::Matrix{T}, alphaX_right::Matrix{T}, alphaY_t_left::Matrix{T}, alphaY_t_right::Matrix{T}, timestep::T) where {T} function BTCS_2D(
grid::Grid{T},
bc::Boundary{T},
alphaX_left::Matrix{T},
alphaX_right::Matrix{T},
alphaY_t_left::Matrix{T},
alphaY_t_right::Matrix{T},
timestep::T,
) where {T}
rows = getRows(grid) rows = getRows(grid)
cols = getCols(grid) cols = getCols(grid)
sx = timestep / (2 * getDeltaCol(grid) * getDeltaCol(grid)) sx = timestep / (2 * getDeltaCol(grid) * getDeltaCol(grid))
@ -152,11 +255,32 @@ function BTCS_2D(grid::Grid{T}, bc::Boundary{T}, alphaX_left::Matrix{T}, alphaX_
bcTop = getBoundarySide(bc, TOP) bcTop = getBoundarySide(bc, TOP)
bcBottom = getBoundarySide(bc, BOTTOM) bcBottom = getBoundarySide(bc, BOTTOM)
localBs = [zeros(T, cols) for _ in 1:Threads.nthreads()] localBs = [zeros(T, cols) for _ = 1:Threads.nthreads()]
Threads.@threads for i = 1:rows Threads.@threads for i = 1:rows
localB = localBs[Threads.threadid()] localB = localBs[Threads.threadid()]
A::Tridiagonal{T} = createCoeffMatrix(alphaX, alphaX_left[i, :], alphaX_right[i, :], bcLeft, bcRight, cols, i, sx) A::Tridiagonal{T} = createCoeffMatrix(
writeSolutionVector!(localB, concentrations, alphaX, alphaY, bcLeft, bcRight, bcTop, bcBottom, i, sx, sy) alphaX,
alphaX_left[i, :],
alphaX_right[i, :],
bcLeft,
bcRight,
cols,
i,
sx,
)
writeSolutionVector!(
localB,
concentrations,
alphaX,
alphaY,
bcLeft,
bcRight,
bcTop,
bcBottom,
i,
sx,
sy,
)
concentrations_intermediate[i, :] = A \ localB concentrations_intermediate[i, :] = A \ localB
end end
@ -165,11 +289,32 @@ function BTCS_2D(grid::Grid{T}, bc::Boundary{T}, alphaX_left::Matrix{T}, alphaX_
concentrations_t = fetch(concentrations_t_task) concentrations_t = fetch(concentrations_t_task)
# Swap alphas, boundary conditions and sx/sy for column-wise calculation # Swap alphas, boundary conditions and sx/sy for column-wise calculation
localBs = [zeros(T, rows) for _ in 1:Threads.nthreads()] localBs = [zeros(T, rows) for _ = 1:Threads.nthreads()]
Threads.@threads for i = 1:cols Threads.@threads for i = 1:cols
localB = localBs[Threads.threadid()] localB = localBs[Threads.threadid()]
A::Tridiagonal{T} = createCoeffMatrix(alphaY_t, alphaY_t_left[i, :], alphaY_t_right[i, :], bcTop, bcBottom, rows, i, sy) A::Tridiagonal{T} = createCoeffMatrix(
writeSolutionVector!(localB, concentrations_intermediate, alphaY_t, alphaX_t, bcTop, bcBottom, bcLeft, bcRight, i, sy, sx) alphaY_t,
alphaY_t_left[i, :],
alphaY_t_right[i, :],
bcTop,
bcBottom,
rows,
i,
sy,
)
writeSolutionVector!(
localB,
concentrations_intermediate,
alphaY_t,
alphaX_t,
bcTop,
bcBottom,
bcLeft,
bcRight,
i,
sy,
sx,
)
concentrations_t[i, :] = A \ localB concentrations_t[i, :] = A \ localB
end end
@ -179,18 +324,28 @@ function BTCS_2D(grid::Grid{T}, bc::Boundary{T}, alphaX_left::Matrix{T}, alphaX_
setConcentrations!(grid, concentrations) setConcentrations!(grid, concentrations)
end end
function runBTCS(grid::Grid{T}, bc::Boundary{T}, timestep::T, iterations::Int, stepCallback::Function) where {T} function runBTCS(
grid::Grid{T},
bc::Boundary{T},
timestep::T,
iterations::Int,
stepCallback::Function,
) where {T}
if getDim(grid) == 1 if getDim(grid) == 1
length = getCols(grid) length = getCols(grid)
alpha = getAlphaX(grid) alpha = getAlphaX(grid)
alpha_left_task = Threads.@spawn calcAlphaIntercell(alpha[:, 1:(length-2)], alpha[:, 2:(length-1)]) alpha_left_task = Threads.@spawn calcAlphaIntercell(
alpha_right_task = Threads.@spawn calcAlphaIntercell(alpha[:, 2:(length-1)], alpha[:, 3:length]) alpha[:, 1:(length-2)],
alpha[:, 2:(length-1)],
)
alpha_right_task =
Threads.@spawn calcAlphaIntercell(alpha[:, 2:(length-1)], alpha[:, 3:length])
alpha_left = fetch(alpha_left_task) alpha_left = fetch(alpha_left_task)
alpha_right = fetch(alpha_right_task) alpha_right = fetch(alpha_right_task)
for _ in 1:(iterations) for _ = 1:(iterations)
BTCS_1D(grid, bc, alpha_left, alpha_right, timestep) BTCS_1D(grid, bc, alpha_left, alpha_right, timestep)
stepCallback() stepCallback()
@ -201,18 +356,32 @@ function runBTCS(grid::Grid{T}, bc::Boundary{T}, timestep::T, iterations::Int, s
alphaX = getAlphaX(grid) alphaX = getAlphaX(grid)
alphaY_t = getAlphaY_t(grid) alphaY_t = getAlphaY_t(grid)
alphaX_left_task = Threads.@spawn calcAlphaIntercell(alphaX[:, 1:(cols-2)], alphaX[:, 2:(cols-1)]) alphaX_left_task =
alphaX_right_task = Threads.@spawn calcAlphaIntercell(alphaX[:, 2:(cols-1)], alphaX[:, 3:cols]) Threads.@spawn calcAlphaIntercell(alphaX[:, 1:(cols-2)], alphaX[:, 2:(cols-1)])
alphaY_t_left_task = Threads.@spawn calcAlphaIntercell(alphaY_t[:, 1:(rows-2)], alphaY_t[:, 2:(rows-1)]) alphaX_right_task =
alphaY_t_right_task = Threads.@spawn calcAlphaIntercell(alphaY_t[:, 2:(rows-1)], alphaY_t[:, 3:rows]) Threads.@spawn calcAlphaIntercell(alphaX[:, 2:(cols-1)], alphaX[:, 3:cols])
alphaY_t_left_task = Threads.@spawn calcAlphaIntercell(
alphaY_t[:, 1:(rows-2)],
alphaY_t[:, 2:(rows-1)],
)
alphaY_t_right_task =
Threads.@spawn calcAlphaIntercell(alphaY_t[:, 2:(rows-1)], alphaY_t[:, 3:rows])
alphaX_left = fetch(alphaX_left_task) alphaX_left = fetch(alphaX_left_task)
alphaX_right = fetch(alphaX_right_task) alphaX_right = fetch(alphaX_right_task)
alphaY_t_left = fetch(alphaY_t_left_task) alphaY_t_left = fetch(alphaY_t_left_task)
alphaY_t_right = fetch(alphaY_t_right_task) alphaY_t_right = fetch(alphaY_t_right_task)
for _ in 1:(iterations) for _ = 1:(iterations)
BTCS_2D(grid, bc, alphaX_left, alphaX_right, alphaY_t_left, alphaY_t_right, timestep) BTCS_2D(
grid,
bc,
alphaX_left,
alphaX_right,
alphaY_t_left,
alphaY_t_right,
timestep,
)
stepCallback() stepCallback()
end end

View File

@ -7,8 +7,14 @@ using Base.Threads
using LinearAlgebra using LinearAlgebra
using SparseArrays using SparseArrays
function calcHorizontalChange(alphaX_next::T, alphaX_prev::T, alphaX_current::T, function calcHorizontalChange(
concentration_next::T, concentration_prev::T, concentration_current::T) where {T} alphaX_next::T,
alphaX_prev::T,
alphaX_current::T,
concentration_next::T,
concentration_prev::T,
concentration_current::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)
@ -18,8 +24,14 @@ function calcHorizontalChange(alphaX_next::T, alphaX_prev::T, alphaX_current::T,
intercellAlpha_prev * concentration_prev intercellAlpha_prev * concentration_prev
end end
function calcHorizontalChangeLeftBoundary(boundaryType::TYPE, alphaX_next::T, alphaX_current::T, function calcHorizontalChangeLeftBoundary(
concentration_next::T, concentration_current::T, boundaryValue::T) where {T} boundaryType::TYPE,
alphaX_next::T,
alphaX_current::T,
concentration_next::T,
concentration_current::T,
boundaryValue::T,
) where {T}
intercellAlpha = calcAlphaIntercell(alphaX_next, alphaX_current) intercellAlpha = calcAlphaIntercell(alphaX_next, alphaX_current)
if boundaryType == CONSTANT if boundaryType == CONSTANT
@ -33,8 +45,14 @@ function calcHorizontalChangeLeftBoundary(boundaryType::TYPE, alphaX_next::T, al
end end
end end
function calcHorizontalChangeRightBoundary(boundaryType::TYPE, alphaX_prev::T, alphaX_current::T, function calcHorizontalChangeRightBoundary(
concentration_prev::T, concentration_current::T, boundaryValue::T) where {T} boundaryType::TYPE,
alphaX_prev::T,
alphaX_current::T,
concentration_prev::T,
concentration_current::T,
boundaryValue::T,
) where {T}
intercellAlpha = calcAlphaIntercell(alphaX_prev, alphaX_current) intercellAlpha = calcAlphaIntercell(alphaX_prev, alphaX_current)
if boundaryType == CONSTANT if boundaryType == CONSTANT
@ -48,8 +66,14 @@ function calcHorizontalChangeRightBoundary(boundaryType::TYPE, alphaX_prev::T, a
end end
end end
function calcVerticalChange(alphaY_above::T, alphaY_below::T, alphaY_current::T, function calcVerticalChange(
concentration_above::T, concentration_below::T, concentration_current::T) where {T} alphaY_above::T,
alphaY_below::T,
alphaY_current::T,
concentration_above::T,
concentration_below::T,
concentration_current::T,
) where {T}
intercellAlpha_above = calcAlphaIntercell(alphaY_above, alphaY_current) intercellAlpha_above = calcAlphaIntercell(alphaY_above, alphaY_current)
intercellAlpha_below = calcAlphaIntercell(alphaY_below, alphaY_current) intercellAlpha_below = calcAlphaIntercell(alphaY_below, alphaY_current)
@ -58,8 +82,14 @@ function calcVerticalChange(alphaY_above::T, alphaY_below::T, alphaY_current::T,
intercellAlpha_below * concentration_below intercellAlpha_below * concentration_below
end end
function calcVerticalChangeTopBoundary(boundaryType::TYPE, alphaY_above::T, alphaY_current::T, function calcVerticalChangeTopBoundary(
concentration_above::T, concentration_current::T, boundaryValue::T) where {T} boundaryType::TYPE,
alphaY_above::T,
alphaY_current::T,
concentration_above::T,
concentration_current::T,
boundaryValue::T,
) where {T}
intercellAlpha = calcAlphaIntercell(alphaY_above, alphaY_current) intercellAlpha = calcAlphaIntercell(alphaY_above, alphaY_current)
if boundaryType == CONSTANT if boundaryType == CONSTANT
@ -74,8 +104,14 @@ function calcVerticalChangeTopBoundary(boundaryType::TYPE, alphaY_above::T, alph
end end
function calcVerticalChangeBottomBoundary(boundaryType::TYPE, alphaY_current::T, alphaY_below::T, function calcVerticalChangeBottomBoundary(
concentration_current::T, concentration_below::T, boundaryValue::T) where {T} boundaryType::TYPE,
alphaY_current::T,
alphaY_below::T,
concentration_current::T,
concentration_below::T,
boundaryValue::T,
) where {T}
intercellAlpha = calcAlphaIntercell(alphaY_current, alphaY_below) intercellAlpha = calcAlphaIntercell(alphaY_current, alphaY_below)
if boundaryType == CONSTANT if boundaryType == CONSTANT
@ -101,21 +137,42 @@ function FTCS_1D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
# inner cells # inner cells
for col = 2:colMax-1 for col = 2:colMax-1
concentrations_t1[row, col] += sx * calcHorizontalChange(alphaX[row, col+1], alphaX[row, col-1], alphaX[row, col], concentrations_t1[row, col] +=
concentrations[row, col+1], concentrations[row, col-1], concentrations[row, col]) sx * calcHorizontalChange(
alphaX[row, col+1],
alphaX[row, col-1],
alphaX[row, col],
concentrations[row, col+1],
concentrations[row, col-1],
concentrations[row, col],
)
end end
# left boundary # 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] += sx * calcHorizontalChangeLeftBoundary(leftBoundaryType, alphaX[row, 2], alphaX[row, 1], concentrations_t1[row, 1] +=
concentrations[row, 2], concentrations[row, 1], leftBoundaryValue) sx * calcHorizontalChangeLeftBoundary(
leftBoundaryType,
alphaX[row, 2],
alphaX[row, 1],
concentrations[row, 2],
concentrations[row, 1],
leftBoundaryValue,
)
# right boundary # 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] += sx * calcHorizontalChangeRightBoundary(rightBoundaryType, alphaX[row, colMax-1], alphaX[row, colMax], concentrations_t1[row, colMax] +=
concentrations[row, colMax-1], concentrations[row, colMax], rightBoundaryValue) sx * calcHorizontalChangeRightBoundary(
rightBoundaryType,
alphaX[row, colMax-1],
alphaX[row, colMax],
concentrations[row, colMax-1],
concentrations[row, colMax],
rightBoundaryValue,
)
setConcentrations!(grid, concentrations_t1) setConcentrations!(grid, concentrations_t1)
end end
@ -139,78 +196,201 @@ function FTCS_2D(grid::Grid{T}, bc::Boundary{T}, timestep::T) where {T}
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] += sy * calcVerticalChange(alphaY[row+1, col], alphaY[row-1, col], alphaY[row, col], concentrations_t1[row, col] +=
concentrations[row+1, col], concentrations[row-1, col], concentrations[row, col]) + sy * calcVerticalChange(
sx * calcHorizontalChange(alphaX[row, col+1], alphaX[row, col-1], alphaX[row, col], alphaY[row+1, col],
concentrations[row, col+1], concentrations[row, col-1], concentrations[row, col]) alphaY[row-1, col],
alphaY[row, col],
concentrations[row+1, col],
concentrations[row-1, col],
concentrations[row, col],
) +
sx * calcHorizontalChange(
alphaX[row, col+1],
alphaX[row, col-1],
alphaX[row, col],
concentrations[row, col+1],
concentrations[row, col-1],
concentrations[row, col],
)
end end
# Boundary conditions for each row # Boundary conditions for each row
# Left boundary without corners # Left boundary without corners
leftBoundaryValue = getBoundaryElementValue(bc, LEFT, row) leftBoundaryValue = getBoundaryElementValue(bc, LEFT, row)
concentrations_t1[row, 1] += sx * calcHorizontalChangeLeftBoundary(leftBoundaryType, alphaX[row, 2], alphaX[row, 1], concentrations_t1[row, 1] +=
concentrations[row, 2], concentrations[row, 1], leftBoundaryValue) + sx * calcHorizontalChangeLeftBoundary(
sy * calcVerticalChange(alphaY[row+1, 1], alphaY[row-1, 1], alphaY[row, 1], leftBoundaryType,
concentrations[row+1, 1], concentrations[row-1, 1], concentrations[row, 1]) alphaX[row, 2],
alphaX[row, 1],
concentrations[row, 2],
concentrations[row, 1],
leftBoundaryValue,
) +
sy * calcVerticalChange(
alphaY[row+1, 1],
alphaY[row-1, 1],
alphaY[row, 1],
concentrations[row+1, 1],
concentrations[row-1, 1],
concentrations[row, 1],
)
# Right boundary without corners # Right boundary without corners
rightBoundaryValue = getBoundaryElementValue(bc, RIGHT, row) rightBoundaryValue = getBoundaryElementValue(bc, RIGHT, row)
concentrations_t1[row, colMax] += sx * calcHorizontalChangeRightBoundary(rightBoundaryType, alphaX[row, colMax-1], alphaX[row, colMax], concentrations_t1[row, colMax] +=
concentrations[row, colMax-1], concentrations[row, colMax], rightBoundaryValue) + sx * calcHorizontalChangeRightBoundary(
sy * calcVerticalChange(alphaY[row+1, colMax], alphaY[row-1, colMax], alphaY[row, colMax], rightBoundaryType,
concentrations[row+1, colMax], concentrations[row-1, colMax], concentrations[row, colMax]) alphaX[row, colMax-1],
alphaX[row, colMax],
concentrations[row, colMax-1],
concentrations[row, colMax],
rightBoundaryValue,
) +
sy * calcVerticalChange(
alphaY[row+1, colMax],
alphaY[row-1, colMax],
alphaY[row, colMax],
concentrations[row+1, colMax],
concentrations[row-1, colMax],
concentrations[row, colMax],
)
end end
# Handle top/bottom boundaries # Handle top/bottom boundaries
Threads.@threads for col = 2:colMax-1 Threads.@threads for col = 2:colMax-1
# Top boundary # Top boundary
topBoundaryValue = getBoundaryElementValue(bc, TOP, col) topBoundaryValue = getBoundaryElementValue(bc, TOP, col)
concentrations_t1[1, col] += sy * calcVerticalChangeTopBoundary(topBoundaryType, alphaY[2, col], alphaY[1, col], concentrations_t1[1, col] +=
concentrations[2, col], concentrations[1, col], topBoundaryValue) + sy * calcVerticalChangeTopBoundary(
sx * calcHorizontalChange(alphaX[1, col+1], alphaX[1, col-1], alphaX[1, col], topBoundaryType,
concentrations[1, col+1], concentrations[1, col-1], concentrations[1, col]) alphaY[2, col],
alphaY[1, col],
concentrations[2, col],
concentrations[1, col],
topBoundaryValue,
) +
sx * calcHorizontalChange(
alphaX[1, col+1],
alphaX[1, col-1],
alphaX[1, col],
concentrations[1, col+1],
concentrations[1, col-1],
concentrations[1, col],
)
# Bottom boundary # Bottom boundary
bottomBoundaryValue = getBoundaryElementValue(bc, BOTTOM, col) bottomBoundaryValue = getBoundaryElementValue(bc, BOTTOM, col)
concentrations_t1[rowMax, col] += sy * calcVerticalChangeBottomBoundary(bottomBoundaryType, alphaY[rowMax, col], alphaY[rowMax-1, col], concentrations_t1[rowMax, col] +=
concentrations[rowMax, col], concentrations[rowMax-1, col], bottomBoundaryValue) + sy * calcVerticalChangeBottomBoundary(
sx * calcHorizontalChange(alphaX[rowMax, col+1], alphaX[rowMax, col-1], alphaX[rowMax, col], bottomBoundaryType,
concentrations[rowMax, col+1], concentrations[rowMax, col-1], concentrations[rowMax, col]) alphaY[rowMax, col],
alphaY[rowMax-1, col],
concentrations[rowMax, col],
concentrations[rowMax-1, col],
bottomBoundaryValue,
) +
sx * calcHorizontalChange(
alphaX[rowMax, col+1],
alphaX[rowMax, col-1],
alphaX[rowMax, col],
concentrations[rowMax, col+1],
concentrations[rowMax, col-1],
concentrations[rowMax, col],
)
end end
# Handle corners # Handle corners
# Top left corner # Top left corner
topBoundaryValue = getBoundaryElementValue(bc, TOP, 1) topBoundaryValue = getBoundaryElementValue(bc, TOP, 1)
concentrations_t1[1, 1] += sx * calcHorizontalChange(alphaX[1, 2], alphaX[1, 1], alphaX[1, 1], concentrations_t1[1, 1] +=
concentrations[1, 2], concentrations[1, 1], concentrations[1, 1]) + sx * calcHorizontalChange(
sy * calcVerticalChangeTopBoundary(topBoundaryType, alphaY[2, 1], alphaY[1, 1], alphaX[1, 2],
concentrations[2, 1], concentrations[1, 1], topBoundaryValue) alphaX[1, 1],
alphaX[1, 1],
concentrations[1, 2],
concentrations[1, 1],
concentrations[1, 1],
) +
sy * calcVerticalChangeTopBoundary(
topBoundaryType,
alphaY[2, 1],
alphaY[1, 1],
concentrations[2, 1],
concentrations[1, 1],
topBoundaryValue,
)
# Top right corner # Top right corner
topBoundaryValue = getBoundaryElementValue(bc, TOP, colMax) topBoundaryValue = getBoundaryElementValue(bc, TOP, colMax)
concentrations_t1[1, colMax] += sx * calcHorizontalChange(alphaX[1, colMax-1], alphaX[1, colMax], alphaX[1, colMax], concentrations_t1[1, colMax] +=
concentrations[1, colMax-1], concentrations[1, colMax], concentrations[1, colMax]) + sx * calcHorizontalChange(
sy * calcVerticalChangeTopBoundary(topBoundaryType, alphaY[2, colMax], alphaY[1, colMax], alphaX[1, colMax-1],
concentrations[2, colMax], concentrations[1, colMax], topBoundaryValue) alphaX[1, colMax],
alphaX[1, colMax],
concentrations[1, colMax-1],
concentrations[1, colMax],
concentrations[1, colMax],
) +
sy * calcVerticalChangeTopBoundary(
topBoundaryType,
alphaY[2, colMax],
alphaY[1, colMax],
concentrations[2, colMax],
concentrations[1, colMax],
topBoundaryValue,
)
# Bottom left corner # Bottom left corner
bottomBoundaryValue = getBoundaryElementValue(bc, BOTTOM, 1) bottomBoundaryValue = getBoundaryElementValue(bc, BOTTOM, 1)
concentrations_t1[rowMax, 1] += sx * calcHorizontalChange(alphaX[rowMax, 2], alphaX[rowMax, 1], alphaX[rowMax, 1], concentrations_t1[rowMax, 1] +=
concentrations[rowMax, 2], concentrations[rowMax, 1], concentrations[rowMax, 1]) + sx * calcHorizontalChange(
sy * calcVerticalChangeBottomBoundary(bottomBoundaryType, alphaY[rowMax, 1], alphaY[rowMax-1, 1], alphaX[rowMax, 2],
concentrations[rowMax, 1], concentrations[rowMax-1, 1], bottomBoundaryValue) alphaX[rowMax, 1],
alphaX[rowMax, 1],
concentrations[rowMax, 2],
concentrations[rowMax, 1],
concentrations[rowMax, 1],
) +
sy * calcVerticalChangeBottomBoundary(
bottomBoundaryType,
alphaY[rowMax, 1],
alphaY[rowMax-1, 1],
concentrations[rowMax, 1],
concentrations[rowMax-1, 1],
bottomBoundaryValue,
)
# Bottom right corner # Bottom right corner
bottomBoundaryValue = getBoundaryElementValue(bc, BOTTOM, colMax) bottomBoundaryValue = getBoundaryElementValue(bc, BOTTOM, colMax)
concentrations_t1[rowMax, colMax] += sx * calcHorizontalChange(alphaX[rowMax, colMax-1], alphaX[rowMax, colMax], alphaX[rowMax, colMax], concentrations_t1[rowMax, colMax] +=
concentrations[rowMax, colMax-1], concentrations[rowMax, colMax], concentrations[rowMax, colMax]) + sx * calcHorizontalChange(
sy * calcVerticalChangeBottomBoundary(bottomBoundaryType, alphaY[rowMax, colMax], alphaY[rowMax-1, colMax], alphaX[rowMax, colMax-1],
concentrations[rowMax, colMax], concentrations[rowMax-1, colMax], bottomBoundaryValue) alphaX[rowMax, colMax],
alphaX[rowMax, colMax],
concentrations[rowMax, colMax-1],
concentrations[rowMax, colMax],
concentrations[rowMax, colMax],
) +
sy * calcVerticalChangeBottomBoundary(
bottomBoundaryType,
alphaY[rowMax, colMax],
alphaY[rowMax-1, colMax],
concentrations[rowMax, colMax],
concentrations[rowMax-1, colMax],
bottomBoundaryValue,
)
setConcentrations!(grid, concentrations_t1) setConcentrations!(grid, concentrations_t1)
end end
function runFTCS(grid::Grid{T}, bc::Boundary{T}, timestep::T, iterations::Int, stepCallback::Function) where {T} function runFTCS(
grid::Grid{T},
bc::Boundary{T},
timestep::T,
iterations::Int,
stepCallback::Function,
) where {T}
if getDim(grid) == 1 if getDim(grid) == 1
for _ = 1:iterations for _ = 1:iterations
FTCS_1D(grid, bc, timestep) FTCS_1D(grid, bc, timestep)

View File

@ -26,7 +26,12 @@ struct DynamicSimulation{T} <: AbstractSimulation{T}
iterations::Int iterations::Int
timestep::T timestep::T
function DynamicSimulation(grid::Grid{T}, bc::Boundary{T}, approach::APPROACH, timestep::T)::DynamicSimulation{T} where {T} function DynamicSimulation(
grid::Grid{T},
bc::Boundary{T},
approach::APPROACH,
timestep::T,
)::DynamicSimulation{T} where {T}
timestep, iterations = adjustTimestep(grid, approach, timestep, 1, false) timestep, iterations = adjustTimestep(grid, approach, timestep, 1, false)
new{T}(grid, Vector{Grid{T}}(), bc, approach, iterations, timestep) new{T}(grid, Vector{Grid{T}}(), bc, approach, iterations, timestep)
end end
@ -76,7 +81,10 @@ Prints the concentrations of a specific grid state to the console.
# Returns # Returns
Nothing, but outputs the grid's concentration matrix to the console. Nothing, but outputs the grid's concentration matrix to the console.
""" """
function printConcentrations(simulation::DynamicSimulation{T}, gridIndex::Int)::Nothing where {T} function printConcentrations(
simulation::DynamicSimulation{T},
gridIndex::Int,
)::Nothing where {T}
writeConcentrationsToCLI(simulation, simulation.grids[gridIndex]) writeConcentrationsToCLI(simulation, simulation.grids[gridIndex])
end end
@ -92,17 +100,35 @@ Writes the concentrations of a specific grid state to a CSV file.
# Returns # Returns
Nothing, but writes the grid's concentration matrix to a CSV file. Nothing, but writes the grid's concentration matrix to a CSV file.
""" """
function printConcentrationsCSV(simulation::DynamicSimulation{T}, gridIndex::Int)::Nothing where {T} function printConcentrationsCSV(
simulation::DynamicSimulation{T},
gridIndex::Int,
)::Nothing where {T}
file = createCSVfile(simulation, simulation.grids[gridIndex]) file = createCSVfile(simulation, simulation.grids[gridIndex])
writeConcentrationsToCSV(file, simulation, simulation.grids[gridIndex]) writeConcentrationsToCSV(file, simulation, simulation.grids[gridIndex])
close(file) close(file)
end end
function runSimulationForGrid(simulation::DynamicSimulation{T}, grid::Grid{T})::Nothing where {T} function runSimulationForGrid(
simulation::DynamicSimulation{T},
grid::Grid{T},
)::Nothing where {T}
if simulation.approach == BTCS if simulation.approach == BTCS
runBTCS(grid, simulation.bc, simulation.timestep, simulation.iterations, () -> nothing) runBTCS(
grid,
simulation.bc,
simulation.timestep,
simulation.iterations,
() -> nothing,
)
elseif simulation.approach == FTCS elseif simulation.approach == FTCS
runFTCS(grid, simulation.bc, simulation.timestep, simulation.iterations, () -> nothing) runFTCS(
grid,
simulation.bc,
simulation.timestep,
simulation.iterations,
() -> nothing,
)
else else
error("Undefined approach!") error("Undefined approach!")
end end
@ -120,7 +146,10 @@ Retrieves the concentrations of a specific grid state.
# Returns # Returns
The concentration matrix of the specified grid. The concentration matrix of the specified grid.
""" """
function getConcentrations(simulation::DynamicSimulation{T}, gridIndex::Int)::Matrix{T} where {T} function getConcentrations(
simulation::DynamicSimulation{T},
gridIndex::Int,
)::Matrix{T} where {T}
getConcentrations(simulation.grids[gridIndex]) getConcentrations(simulation.grids[gridIndex])
end end
@ -137,7 +166,11 @@ Sets the concentrations of a specific grid state.
# Returns # Returns
Nothing, but updates the concentration matrix of the specified grid. Nothing, but updates the concentration matrix of the specified grid.
""" """
function setConcentrations!(simulation::DynamicSimulation{T}, gridIndex::Int, concentrations::Matrix{T})::Nothing where {T} function setConcentrations!(
simulation::DynamicSimulation{T},
gridIndex::Int,
concentrations::Matrix{T},
)::Nothing where {T}
setConcentrations!(simulation.grids[gridIndex], concentrations) setConcentrations!(simulation.grids[gridIndex], concentrations)
end end
@ -154,7 +187,11 @@ Sets the alphaX matrix of a specific grid state.
# Returns # Returns
Nothing, but updates the alphaX matrix of the specified grid. Nothing, but updates the alphaX matrix of the specified grid.
""" """
function setAlphaX!(simulation::DynamicSimulation{T}, gridIndex::Int, alphaX::Matrix{T})::Nothing where {T} function setAlphaX!(
simulation::DynamicSimulation{T},
gridIndex::Int,
alphaX::Matrix{T},
)::Nothing where {T}
setAlphaX!(simulation.grids[gridIndex], alphaX) setAlphaX!(simulation.grids[gridIndex], alphaX)
end end
@ -171,6 +208,10 @@ Sets the alphaY matrix of a specific grid state.
# Returns # Returns
Nothing, but updates the alphaY matrix of the specified grid. Nothing, but updates the alphaY matrix of the specified grid.
""" """
function setAlphaY!(simulation::DynamicSimulation{T}, gridIndex::Int, alphaY::Matrix{T})::Nothing where {T} function setAlphaY!(
simulation::DynamicSimulation{T},
gridIndex::Int,
alphaY::Matrix{T},
)::Nothing where {T}
setAlphaY!(simulation.grids[gridIndex], alphaY) setAlphaY!(simulation.grids[gridIndex], alphaY)
end end

View File

@ -46,30 +46,99 @@ struct Grid{T}
throw(ArgumentError("Given grid length too small. Must be greater than 3.")) throw(ArgumentError("Given grid length too small. Must be greater than 3."))
end end
if size(alphaX, 1) != 1 || size(alphaX, 2) != length if size(alphaX, 1) != 1 || size(alphaX, 2) != length
throw(ArgumentError("Given matrix of alpha coefficients mismatch with Grid dimensions!")) throw(
ArgumentError(
"Given matrix of alpha coefficients mismatch with Grid dimensions!",
),
)
end end
alphaX_t = alphaX' alphaX_t = alphaX'
new{T}(length, 1, 1, T(length), 0, T(1), 0, Ref(fill(T(0), 1, length)), alphaX, nothing, alphaX_t, nothing) new{T}(
length,
1,
1,
T(length),
0,
T(1),
0,
Ref(fill(T(0), 1, length)),
alphaX,
nothing,
alphaX_t,
nothing,
)
end end
function Grid{T}(rows::Int, cols::Int, alphaX::Matrix{T}, alphaY::Matrix{T})::Grid{T} where {T} function Grid{T}(
rows::Int,
cols::Int,
alphaX::Matrix{T},
alphaY::Matrix{T},
)::Grid{T} where {T}
if rows <= 3 || cols <= 3 if rows <= 3 || cols <= 3
throw(ArgumentError("Given grid dimensions too small. Must each be greater than 3.")) throw(
ArgumentError(
"Given grid dimensions too small. Must each be greater than 3.",
),
)
end end
if size(alphaX) != (rows, cols) || size(alphaY) != (rows, cols) if size(alphaX) != (rows, cols) || size(alphaY) != (rows, cols)
throw(ArgumentError("Given matrices of alpha coefficients mismatch with Grid dimensions!")) throw(
ArgumentError(
"Given matrices of alpha coefficients mismatch with Grid dimensions!",
),
)
end end
alphaX_t = alphaX' alphaX_t = alphaX'
alphaY_t = alphaY' alphaY_t = alphaY'
new{T}(cols, rows, 2, T(cols), T(rows), T(1), T(1), Ref(fill(T(0), rows, cols)), alphaX, alphaY, alphaX_t, alphaY_t) new{T}(
cols,
rows,
2,
T(cols),
T(rows),
T(1),
T(1),
Ref(fill(T(0), rows, cols)),
alphaX,
alphaY,
alphaX_t,
alphaY_t,
)
end end
function Grid{T}(rows::Int, cols::Int, dim::Int, domainCol::T, domainRow::T, deltaCol::T, deltaRow::T, concentrations::Ref{Matrix{T}}, alphaX::Ref{Matrix{T}}, alphaY::Union{Ref{Matrix{T}},Nothing}, alphaX_t::Union{Ref{Matrix{T}},Nothing}, alphaY_t::Union{Ref{Matrix{T}},Nothing})::Grid{T} where {T} function Grid{T}(
new{T}(cols, rows, dim, domainCol, domainRow, deltaCol, deltaRow, concentrations, alphaX, alphaY, alphaX_t, alphaY_t) rows::Int,
cols::Int,
dim::Int,
domainCol::T,
domainRow::T,
deltaCol::T,
deltaRow::T,
concentrations::Ref{Matrix{T}},
alphaX::Ref{Matrix{T}},
alphaY::Union{Ref{Matrix{T}},Nothing},
alphaX_t::Union{Ref{Matrix{T}},Nothing},
alphaY_t::Union{Ref{Matrix{T}},Nothing},
)::Grid{T} where {T}
new{T}(
cols,
rows,
dim,
domainCol,
domainRow,
deltaCol,
deltaRow,
concentrations,
alphaX,
alphaY,
alphaX_t,
alphaY_t,
)
end end
end end
@ -87,9 +156,35 @@ A new `Grid{T}` object that is a deep copy of the input grid.
""" """
function clone(grid::Grid{T})::Grid{T} where {T} function clone(grid::Grid{T})::Grid{T} where {T}
if grid.dim == 1 if grid.dim == 1
return Grid{T}(1, grid.cols, grid.dim, grid.domainCol, grid.domainRow, grid.deltaCol, grid.deltaRow, Ref(copy(grid.concentrations[])), Ref(copy(grid.alphaX[])), nothing, Ref(copy(grid.alphaX_t[])), nothing) return Grid{T}(
1,
grid.cols,
grid.dim,
grid.domainCol,
grid.domainRow,
grid.deltaCol,
grid.deltaRow,
Ref(copy(grid.concentrations[])),
Ref(copy(grid.alphaX[])),
nothing,
Ref(copy(grid.alphaX_t[])),
nothing,
)
end end
Grid{T}(grid.rows, grid.cols, grid.dim, grid.domainCol, grid.domainRow, grid.deltaCol, grid.deltaRow, Ref(copy(grid.concentrations[])), Ref(copy(grid.alphaX[])), Ref(copy(grid.alphaY[])), Ref(copy(grid.alphaX_t[])), Ref(copy(grid.alphaY_t[]))) Grid{T}(
grid.rows,
grid.cols,
grid.dim,
grid.domainCol,
grid.domainRow,
grid.deltaCol,
grid.deltaRow,
Ref(copy(grid.concentrations[])),
Ref(copy(grid.alphaX[])),
Ref(copy(grid.alphaY[])),
Ref(copy(grid.alphaX_t[])),
Ref(copy(grid.alphaY_t[])),
)
end end
""" """
@ -267,7 +362,11 @@ Nothing, but modifies the alphaX matrix of the grid.
""" """
function setAlphaX!(grid::Grid{T}, new_alphaX::Matrix{T})::Nothing where {T} function setAlphaX!(grid::Grid{T}, new_alphaX::Matrix{T})::Nothing where {T}
if size(new_alphaX) != size(grid.alphaX[]) if size(new_alphaX) != size(grid.alphaX[])
throw(ArgumentError("Given matrix of alpha coefficients mismatch with Grid dimensions!")) throw(
ArgumentError(
"Given matrix of alpha coefficients mismatch with Grid dimensions!",
),
)
end end
grid.alphaX[] = new_alphaX grid.alphaX[] = new_alphaX
@ -293,7 +392,11 @@ function setAlphaY!(grid::Grid{T}, new_alphaY::Matrix{T})::Nothing where {T}
error("Grid is 1D, so there is no alphaY matrix!") error("Grid is 1D, so there is no alphaY matrix!")
end end
if size(new_alphaY) != size(grid.alphaY[]) if size(new_alphaY) != size(grid.alphaY[])
throw(ArgumentError("Given matrix of alpha coefficients mismatch with Grid dimensions!")) throw(
ArgumentError(
"Given matrix of alpha coefficients mismatch with Grid dimensions!",
),
)
end end
grid.alphaY[] = new_alphaY grid.alphaY[] = new_alphaY
@ -316,7 +419,9 @@ Nothing, but modifies the concentration matrix of the grid.
""" """
function setConcentrations!(grid::Grid{T}, new_concentrations::Matrix{T})::Nothing where {T} function setConcentrations!(grid::Grid{T}, new_concentrations::Matrix{T})::Nothing where {T}
if size(new_concentrations) != size(grid.concentrations[]) if size(new_concentrations) != size(grid.concentrations[])
throw(ArgumentError("Given matrix of concentrations mismatch with Grid dimensions!")) throw(
ArgumentError("Given matrix of concentrations mismatch with Grid dimensions!"),
)
end end
grid.concentrations[] = new_concentrations grid.concentrations[] = new_concentrations

View File

@ -34,8 +34,15 @@ struct Simulation{T} <: AbstractSimulation{T}
consoleOutput::CONSOLE_OUTPUT consoleOutput::CONSOLE_OUTPUT
csvOutput::CSV_OUTPUT csvOutput::CSV_OUTPUT
function Simulation(grid::Grid{T}, bc::Boundary{T}, approach::APPROACH=BTCS, iterations::Int=1, timestep::T=0.1, function Simulation(
consoleOutput::CONSOLE_OUTPUT=CONSOLE_OUTPUT_OFF, csvOutput::CSV_OUTPUT=CSV_OUTPUT_OFF)::Simulation{T} where {T} grid::Grid{T},
bc::Boundary{T},
approach::APPROACH = BTCS,
iterations::Int = 1,
timestep::T = 0.1,
consoleOutput::CONSOLE_OUTPUT = CONSOLE_OUTPUT_OFF,
csvOutput::CSV_OUTPUT = CSV_OUTPUT_OFF,
)::Simulation{T} where {T}
new{T}(grid, bc, approach, iterations, timestep, consoleOutput, csvOutput) new{T}(grid, bc, approach, iterations, timestep, consoleOutput, csvOutput)
end end
end end
@ -69,10 +76,28 @@ function run(simulation::Simulation{T})::Nothing where {T}
end end
if simulation.approach == BTCS if simulation.approach == BTCS
runBTCS(simulation.grid, simulation.bc, simulation.timestep, simulation.iterations, simulationStepCallback) runBTCS(
simulation.grid,
simulation.bc,
simulation.timestep,
simulation.iterations,
simulationStepCallback,
)
elseif simulation.approach == FTCS elseif simulation.approach == FTCS
timestep, iterations = adjustTimestep(simulation.grid, simulation.approach, simulation.timestep, simulation.iterations, simulation.consoleOutput >= CONSOLE_OUTPUT_VERBOSE) timestep, iterations = adjustTimestep(
runFTCS(simulation.grid, simulation.bc, timestep, iterations, simulationStepCallback) simulation.grid,
simulation.approach,
simulation.timestep,
simulation.iterations,
simulation.consoleOutput >= CONSOLE_OUTPUT_VERBOSE,
)
runFTCS(
simulation.grid,
simulation.bc,
timestep,
iterations,
simulationStepCallback,
)
else else
error("Undefined approach!") error("Undefined approach!")
end end
@ -104,7 +129,15 @@ Sets the number of iterations for the given simulation.
A new `Simulation` object with updated iterations. A new `Simulation` object with updated iterations.
""" """
function setIterations(simulation::Simulation{T}, iterations::Int)::Simulation{T} where {T} function setIterations(simulation::Simulation{T}, iterations::Int)::Simulation{T} where {T}
return Simulation(simulation.grid, simulation.bc, simulation.approach, iterations, simulation.timestep, simulation.consoleOutput, simulation.csvOutput) return Simulation(
simulation.grid,
simulation.bc,
simulation.approach,
iterations,
simulation.timestep,
simulation.consoleOutput,
simulation.csvOutput,
)
end end
""" """
@ -119,8 +152,19 @@ Sets the console output level for the simulation.
# Returns # Returns
A new `Simulation` object with updated console output setting. A new `Simulation` object with updated console output setting.
""" """
function setOutputConsole(simulation::Simulation{T}, consoleOutput::CONSOLE_OUTPUT)::Simulation{T} where {T} function setOutputConsole(
return Simulation(simulation.grid, simulation.bc, simulation.approach, simulation.iterations, simulation.timestep, consoleOutput, simulation.csvOutput) simulation::Simulation{T},
consoleOutput::CONSOLE_OUTPUT,
)::Simulation{T} where {T}
return Simulation(
simulation.grid,
simulation.bc,
simulation.approach,
simulation.iterations,
simulation.timestep,
consoleOutput,
simulation.csvOutput,
)
end end
""" """
@ -135,8 +179,19 @@ Sets the CSV output level for the simulation.
# Returns # Returns
A new `Simulation` object with updated CSV output setting. A new `Simulation` object with updated CSV output setting.
""" """
function setOutputCSV(simulation::Simulation{T}, csvOutput::CSV_OUTPUT)::Simulation{T} where {T} function setOutputCSV(
return Simulation(simulation.grid, simulation.bc, simulation.approach, simulation.iterations, simulation.timestep, simulation.consoleOutput, csvOutput) simulation::Simulation{T},
csvOutput::CSV_OUTPUT,
)::Simulation{T} where {T}
return Simulation(
simulation.grid,
simulation.bc,
simulation.approach,
simulation.iterations,
simulation.timestep,
simulation.consoleOutput,
csvOutput,
)
end end
""" """
@ -152,5 +207,13 @@ Sets the timestep for the simulation.
A new `Simulation` object with updated timestep. A new `Simulation` object with updated timestep.
""" """
function setTimestep(simulation::Simulation{T}, timestep::T)::Simulation{T} where {T} function setTimestep(simulation::Simulation{T}, timestep::T)::Simulation{T} where {T}
return Simulation(simulation.grid, simulation.bc, simulation.approach, simulation.iterations, timestep, simulation.consoleOutput, simulation.csvOutput) return Simulation(
simulation.grid,
simulation.bc,
simulation.approach,
simulation.iterations,
timestep,
simulation.consoleOutput,
simulation.csvOutput,
)
end end

View File

@ -3,16 +3,47 @@ module TUG
include("Grid.jl") include("Grid.jl")
export Grid export Grid
export clone, getAlphaX, getAlphaY, getAlphaX_t, getAlphaY_t, getConcentrations, setConcentrations!, setAlphaX!, setAlphaY!, getDomainCol, getDomainRow, getDeltaCol, getDeltaRow, getDim export clone,
getAlphaX,
getAlphaY,
getAlphaX_t,
getAlphaY_t,
getConcentrations,
setConcentrations!,
setAlphaX!,
setAlphaY!,
getDomainCol,
getDomainRow,
getDeltaCol,
getDeltaRow,
getDim
include("Boundary.jl") include("Boundary.jl")
export Boundary, BoundaryElement, TYPE, SIDE, BC_TYPE_CLOSED, BC_TYPE_CONSTANT, LEFT, RIGHT, TOP, BOTTOM export Boundary,
export getType, getValue, setBoundarySideClosed!, setBoundarySideConstant!, getBoundarySide, getBoundaryElementType, getBoundaryElementValue BoundaryElement, TYPE, SIDE, BC_TYPE_CLOSED, BC_TYPE_CONSTANT, LEFT, RIGHT, TOP, BOTTOM
export getType,
getValue,
setBoundarySideClosed!,
setBoundarySideConstant!,
getBoundarySide,
getBoundaryElementType,
getBoundaryElementValue
include("AbstractSimulation.jl") include("AbstractSimulation.jl")
export APPROACH, CONSOLE_OUTPUT, CSV_OUTPUT, BTCS, FTCS, CONSOLE_OUTPUT_OFF, CONSOLE_OUTPUT_ON, CONSOLE_OUTPUT_VERBOSE, CSV_OUTPUT_OFF, CSV_OUTPUT_ON, CSV_OUTPUT_VERBOSE, CSV_OUTPUT_XTREME export APPROACH,
CONSOLE_OUTPUT,
CSV_OUTPUT,
BTCS,
FTCS,
CONSOLE_OUTPUT_OFF,
CONSOLE_OUTPUT_ON,
CONSOLE_OUTPUT_VERBOSE,
CSV_OUTPUT_OFF,
CSV_OUTPUT_ON,
CSV_OUTPUT_VERBOSE,
CSV_OUTPUT_XTREME
include("Simulation.jl") include("Simulation.jl")
@ -22,7 +53,14 @@ export run, setTimestep, setIterations, setOutputConsole, setOutputCSV
include("DynamicSimulation.jl") include("DynamicSimulation.jl")
export DynamicSimulation export DynamicSimulation
export createGrid, next, printConcentrations, printConcentrationsCSV, getConcentrations, setConcentrations!, setAlphaX!, setAlphaY! export createGrid,
next,
printConcentrations,
printConcentrationsCSV,
getConcentrations,
setConcentrations!,
setAlphaX!,
setAlphaY!
include("Core/Utils.jl") include("Core/Utils.jl")
include("Core/BTCS.jl") include("Core/BTCS.jl")

View File

@ -33,11 +33,16 @@
boundary = TUG.Boundary(grid) boundary = TUG.Boundary(grid)
simulation = TUG.DynamicSimulation(grid, boundary, BTCS, 0.01) simulation = TUG.DynamicSimulation(grid, boundary, BTCS, 0.01)
TUG.createGrid(simulation) TUG.createGrid(simulation)
for _ in 1:20 for _ = 1:20
TUG.next(simulation) TUG.next(simulation)
end end
expected_concentrations = [1.281106278320615 3.5643693033301567 14.309048836698485 3.5643693033301598 1.281106278320616] expected_concentrations =
@test isapprox(TUG.getConcentrations(simulation, 1), expected_concentrations, atol=1e-6) [1.281106278320615 3.5643693033301567 14.309048836698485 3.5643693033301598 1.281106278320616]
@test isapprox(
TUG.getConcentrations(simulation, 1),
expected_concentrations,
atol = 1e-6,
)
grid = TUG.Grid{Float64}(5, ones(1, 5)) grid = TUG.Grid{Float64}(5, ones(1, 5))
TUG.setConcentrations!(grid, [1.0 1.0 20.0 1.0 1.0]) TUG.setConcentrations!(grid, [1.0 1.0 20.0 1.0 1.0])
@ -45,34 +50,77 @@
TUG.setBoundarySideConstant!(boundary, LEFT, 5.0) TUG.setBoundarySideConstant!(boundary, LEFT, 5.0)
simulation = TUG.DynamicSimulation(grid, boundary, BTCS, 0.01) simulation = TUG.DynamicSimulation(grid, boundary, BTCS, 0.01)
TUG.createGrid(simulation) TUG.createGrid(simulation)
for _ in 1:20 for _ = 1:20
TUG.next(simulation) TUG.next(simulation)
end end
expected_concentrations = [2.4416160635284823 3.6810808789967466 14.317333805802393 3.5648326408458035 1.2811288426376255] expected_concentrations =
@test isapprox(TUG.getConcentrations(simulation, 1), expected_concentrations, atol=1e-6) [2.4416160635284823 3.6810808789967466 14.317333805802393 3.5648326408458035 1.2811288426376255]
@test isapprox(
TUG.getConcentrations(simulation, 1),
expected_concentrations,
atol = 1e-6,
)
end end
@testset "2D-Run" begin @testset "2D-Run" begin
grid = TUG.Grid{Float64}(5, 5, ones(5, 5), ones(5, 5)) grid = TUG.Grid{Float64}(5, 5, ones(5, 5), ones(5, 5))
TUG.setConcentrations!(grid, [1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0]) TUG.setConcentrations!(
grid,
[
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
],
)
boundary = TUG.Boundary(grid) boundary = TUG.Boundary(grid)
simulation = TUG.DynamicSimulation(grid, boundary, BTCS, 0.01) simulation = TUG.DynamicSimulation(grid, boundary, BTCS, 0.01)
TUG.createGrid(simulation) TUG.createGrid(simulation)
for _ in 1:20 for _ = 1:20
TUG.next(simulation) TUG.next(simulation)
end end
expected_concentrations = [1.141904802011076 3.591390417498421 14.249599956958917 3.5913904174984217 1.1419048020110782; 1.1419048020110738 3.5913904174984173 14.2495999569589 3.5913904174984177 1.1419048020110767; 1.1419048020110725 3.591390417498413 14.249599956958875 3.5913904174984137 1.1419048020110751; 1.1419048020110738 3.5913904174984164 14.249599956958901 3.5913904174984173 1.141904802011077; 1.1419048020110774 3.5913904174984297 14.24959995695894 3.5913904174984297 1.1419048020110796] expected_concentrations = [
@test isapprox(TUG.getConcentrations(simulation, 1), expected_concentrations, atol=1e-6) 1.141904802011076 3.591390417498421 14.249599956958917 3.5913904174984217 1.1419048020110782
1.1419048020110738 3.5913904174984173 14.2495999569589 3.5913904174984177 1.1419048020110767
1.1419048020110725 3.591390417498413 14.249599956958875 3.5913904174984137 1.1419048020110751
1.1419048020110738 3.5913904174984164 14.249599956958901 3.5913904174984173 1.141904802011077
1.1419048020110774 3.5913904174984297 14.24959995695894 3.5913904174984297 1.1419048020110796
]
@test isapprox(
TUG.getConcentrations(simulation, 1),
expected_concentrations,
atol = 1e-6,
)
grid = TUG.Grid{Float64}(5, 5, ones(5, 5), ones(5, 5)) grid = TUG.Grid{Float64}(5, 5, ones(5, 5), ones(5, 5))
TUG.setConcentrations!(grid, [1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0]) TUG.setConcentrations!(
grid,
[
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
],
)
boundary = TUG.Boundary(grid) boundary = TUG.Boundary(grid)
TUG.setBoundarySideConstant!(boundary, LEFT, 5.0) TUG.setBoundarySideConstant!(boundary, LEFT, 5.0)
simulation = TUG.DynamicSimulation(grid, boundary, BTCS, 0.01) simulation = TUG.DynamicSimulation(grid, boundary, BTCS, 0.01)
TUG.createGrid(simulation) TUG.createGrid(simulation)
for _ in 1:20 for _ = 1:20
TUG.next(simulation) TUG.next(simulation)
end end
expected_concentrations = [1.9866377371338924 3.67421468453773 14.255058363518529 3.5916629034159486 1.1419105589005596; 1.98663773713389 3.674214684537723 14.255058363518497 3.5916629034159406 1.1419105589005576; 1.9866377371338884 3.6742146845377186 14.255058363518481 3.591662903415937 1.1419105589005565; 1.9866377371338895 3.674214684537725 14.255058363518502 3.5916629034159424 1.1419105589005574; 1.9866377371338952 3.6742146845377377 14.255058363518547 3.591662903415955 1.141910558900562] expected_concentrations = [
@test isapprox(TUG.getConcentrations(simulation, 1), expected_concentrations, atol=1e-6) 1.9866377371338924 3.67421468453773 14.255058363518529 3.5916629034159486 1.1419105589005596
1.98663773713389 3.674214684537723 14.255058363518497 3.5916629034159406 1.1419105589005576
1.9866377371338884 3.6742146845377186 14.255058363518481 3.591662903415937 1.1419105589005565
1.9866377371338895 3.674214684537725 14.255058363518502 3.5916629034159424 1.1419105589005574
1.9866377371338952 3.6742146845377377 14.255058363518547 3.591662903415955 1.141910558900562
]
@test isapprox(
TUG.getConcentrations(simulation, 1),
expected_concentrations,
atol = 1e-6,
)
end end
end end

View File

@ -13,7 +13,8 @@
grid = TUG.Grid{Float64}(5, ones(1, 5)) grid = TUG.Grid{Float64}(5, ones(1, 5))
boundary = TUG.Boundary(grid) boundary = TUG.Boundary(grid)
simulation = TUG.Simulation(grid, boundary, FTCS, 2, 0.2, CONSOLE_OUTPUT_ON, CSV_OUTPUT_ON) simulation =
TUG.Simulation(grid, boundary, FTCS, 2, 0.2, CONSOLE_OUTPUT_ON, CSV_OUTPUT_ON)
@test simulation.grid == grid @test simulation.grid == grid
@test simulation.bc == boundary @test simulation.bc == boundary
@test simulation.approach == FTCS @test simulation.approach == FTCS
@ -28,8 +29,9 @@
boundary = TUG.Boundary(grid) boundary = TUG.Boundary(grid)
simulation = TUG.Simulation(grid, boundary, BTCS, 20, 0.01) simulation = TUG.Simulation(grid, boundary, BTCS, 20, 0.01)
TUG.run(simulation) TUG.run(simulation)
expected_concentrations = [1.281106278320615 3.5643693033301567 14.309048836698485 3.5643693033301598 1.281106278320616] expected_concentrations =
@test isapprox(TUG.getConcentrations(grid), expected_concentrations, atol=1e-6) [1.281106278320615 3.5643693033301567 14.309048836698485 3.5643693033301598 1.281106278320616]
@test isapprox(TUG.getConcentrations(grid), expected_concentrations, atol = 1e-6)
grid = TUG.Grid{Float64}(5, ones(1, 5)) grid = TUG.Grid{Float64}(5, ones(1, 5))
TUG.setConcentrations!(grid, [1.0 1.0 20.0 1.0 1.0]) TUG.setConcentrations!(grid, [1.0 1.0 20.0 1.0 1.0])
@ -37,25 +39,56 @@
TUG.setBoundarySideConstant!(boundary, LEFT, 5.0) TUG.setBoundarySideConstant!(boundary, LEFT, 5.0)
simulation = TUG.Simulation(grid, boundary, BTCS, 20, 0.01) simulation = TUG.Simulation(grid, boundary, BTCS, 20, 0.01)
TUG.run(simulation) TUG.run(simulation)
expected_concentrations = [2.4416160635284823 3.6810808789967466 14.317333805802393 3.5648326408458035 1.2811288426376255] expected_concentrations =
@test isapprox(TUG.getConcentrations(grid), expected_concentrations, atol=1e-6) [2.4416160635284823 3.6810808789967466 14.317333805802393 3.5648326408458035 1.2811288426376255]
@test isapprox(TUG.getConcentrations(grid), expected_concentrations, atol = 1e-6)
end end
@testset "2D-Run" begin @testset "2D-Run" begin
grid = TUG.Grid{Float64}(5, 5, ones(5, 5), ones(5, 5)) grid = TUG.Grid{Float64}(5, 5, ones(5, 5), ones(5, 5))
TUG.setConcentrations!(grid, [1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0]) TUG.setConcentrations!(
grid,
[
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
],
)
boundary = TUG.Boundary(grid) boundary = TUG.Boundary(grid)
simulation = TUG.Simulation(grid, boundary, BTCS, 20, 0.01) simulation = TUG.Simulation(grid, boundary, BTCS, 20, 0.01)
TUG.run(simulation) TUG.run(simulation)
expected_concentrations = [1.141904802011076 3.591390417498421 14.249599956958917 3.5913904174984217 1.1419048020110782; 1.1419048020110738 3.5913904174984173 14.2495999569589 3.5913904174984177 1.1419048020110767; 1.1419048020110725 3.591390417498413 14.249599956958875 3.5913904174984137 1.1419048020110751; 1.1419048020110738 3.5913904174984164 14.249599956958901 3.5913904174984173 1.141904802011077; 1.1419048020110774 3.5913904174984297 14.24959995695894 3.5913904174984297 1.1419048020110796] expected_concentrations = [
@test isapprox(TUG.getConcentrations(grid), expected_concentrations, atol=1e-6) 1.141904802011076 3.591390417498421 14.249599956958917 3.5913904174984217 1.1419048020110782
1.1419048020110738 3.5913904174984173 14.2495999569589 3.5913904174984177 1.1419048020110767
1.1419048020110725 3.591390417498413 14.249599956958875 3.5913904174984137 1.1419048020110751
1.1419048020110738 3.5913904174984164 14.249599956958901 3.5913904174984173 1.141904802011077
1.1419048020110774 3.5913904174984297 14.24959995695894 3.5913904174984297 1.1419048020110796
]
@test isapprox(TUG.getConcentrations(grid), expected_concentrations, atol = 1e-6)
grid = TUG.Grid{Float64}(5, 5, ones(5, 5), ones(5, 5)) grid = TUG.Grid{Float64}(5, 5, ones(5, 5), ones(5, 5))
TUG.setConcentrations!(grid, [1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0; 1.0 1.0 20.0 1.0 1.0]) TUG.setConcentrations!(
grid,
[
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
1.0 1.0 20.0 1.0 1.0
],
)
boundary = TUG.Boundary(grid) boundary = TUG.Boundary(grid)
TUG.setBoundarySideConstant!(boundary, LEFT, 5.0) TUG.setBoundarySideConstant!(boundary, LEFT, 5.0)
simulation = TUG.Simulation(grid, boundary, BTCS, 20, 0.01) simulation = TUG.Simulation(grid, boundary, BTCS, 20, 0.01)
TUG.run(simulation) TUG.run(simulation)
expected_concentrations = [1.9866377371338924 3.67421468453773 14.255058363518529 3.5916629034159486 1.1419105589005596; 1.98663773713389 3.674214684537723 14.255058363518497 3.5916629034159406 1.1419105589005576; 1.9866377371338884 3.6742146845377186 14.255058363518481 3.591662903415937 1.1419105589005565; 1.9866377371338895 3.674214684537725 14.255058363518502 3.5916629034159424 1.1419105589005574; 1.9866377371338952 3.6742146845377377 14.255058363518547 3.591662903415955 1.141910558900562] expected_concentrations = [
@test isapprox(TUG.getConcentrations(grid), expected_concentrations, atol=1e-6) 1.9866377371338924 3.67421468453773 14.255058363518529 3.5916629034159486 1.1419105589005596
1.98663773713389 3.674214684537723 14.255058363518497 3.5916629034159406 1.1419105589005576
1.9866377371338884 3.6742146845377186 14.255058363518481 3.591662903415937 1.1419105589005565
1.9866377371338895 3.674214684537725 14.255058363518502 3.5916629034159424 1.1419105589005574
1.9866377371338952 3.6742146845377377 14.255058363518547 3.591662903415955 1.141910558900562
]
@test isapprox(TUG.getConcentrations(grid), expected_concentrations, atol = 1e-6)
end end
end end