Compare commits
10 Commits
bd01c0ee74
...
f69d58e070
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f69d58e070 | ||
|
|
539c6f9544 | ||
|
|
6a98a23439 | ||
|
|
65a16cac1c | ||
|
|
deb71df259 | ||
|
|
5c6ac062cc | ||
|
|
8233d868b2 | ||
|
|
e431af68ca | ||
|
|
bd288e00e1 | ||
|
|
da65b6fa14 |
88
julia/TUG/README.md
Normal file
88
julia/TUG/README.md
Normal file
@ -0,0 +1,88 @@
|
||||
# TUG: Transport on Uniform Grids for Julia
|
||||
|
||||
## Overview
|
||||
|
||||
The TUG Julia package is a port of the same-named C++ library.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before installing TUG, ensure you have Julia installed on your system. Julia can be downloaded and installed from [the official Julia website](https://julialang.org/downloads/).
|
||||
|
||||
## Installation
|
||||
|
||||
To install the TUG package locally, follow these steps in the Julia REPL (Read-Eval-Print Loop):
|
||||
|
||||
1. **Open Julia REPL**: You can start it by executing `julia` in your command line.
|
||||
2. **Enter Pkg mode**: Press `]` to enter Pkg mode, which is Julia's package manager.
|
||||
3. **Develop the Package Locally**:
|
||||
```julia
|
||||
(v1.x) pkg> develop path/to/tug/julia/TUG # Replace with the actual path to your TUG directory
|
||||
```
|
||||
4. **Exit Pkg mode**: Press `backspace` to exit Pkg mode.
|
||||
5. **Use the Package**:
|
||||
```julia
|
||||
julia> using TUG
|
||||
```
|
||||
|
||||
## Building the Documentation
|
||||
|
||||
To build the documentation for TUG:
|
||||
|
||||
1. **Navigate to the `docs` Directory**:
|
||||
```shell
|
||||
cd path/to/tug/julia/TUG/docs
|
||||
```
|
||||
2. **Build the Documentation**:
|
||||
```shell
|
||||
julia make.jl
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
To run the tests for TUG, follow these steps:
|
||||
|
||||
1. **Navigate to the TUG Package Directory**:
|
||||
```shell
|
||||
cd path/to/tug/julia/TUG
|
||||
```
|
||||
2. **Enter Pkg mode and run the tests**:
|
||||
```julia
|
||||
(v1.x) pkg> test TUG
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get started with TUG:
|
||||
|
||||
### Creating a Simulation
|
||||
|
||||
```julia
|
||||
# Import the TUG package
|
||||
using TUG
|
||||
|
||||
# Create a grid
|
||||
grid = TUG.Grid{Float64}(5, ones(1, 5))
|
||||
|
||||
# Define boundary conditions
|
||||
boundary = TUG.Boundary{Float64}(grid)
|
||||
|
||||
# Initialize a simulation
|
||||
simulation = TUG.Simulation{Float64}(grid, boundary)
|
||||
```
|
||||
|
||||
### Running the Simulation
|
||||
|
||||
```julia
|
||||
# Set initial concentrations
|
||||
TUG.setConcentrations!(grid, [1.0, 1.0, 20.0, 1.0, 1.0])
|
||||
|
||||
# Run the simulation
|
||||
TUG.run(simulation)
|
||||
|
||||
# Retrieve the concentrations
|
||||
concentrations = TUG.getConcentrations(grid)
|
||||
```
|
||||
|
||||
## More Information
|
||||
|
||||
For a detailed reference of all functionalities and more comprehensive examples, please refer to the documentation in this repository.
|
||||
13
julia/TUG/docs/make.jl
Normal file
13
julia/TUG/docs/make.jl
Normal file
@ -0,0 +1,13 @@
|
||||
using Pkg
|
||||
using Documenter
|
||||
|
||||
pkg_path = abspath(joinpath(@__DIR__, ".."))
|
||||
Pkg.develop(path = pkg_path)
|
||||
using TUG
|
||||
|
||||
makedocs(
|
||||
sitename = "TUG Documentation",
|
||||
modules = [TUG],
|
||||
format = Documenter.HTML(),
|
||||
remotes = nothing,
|
||||
)
|
||||
97
julia/TUG/docs/src/index.md
Normal file
97
julia/TUG/docs/src/index.md
Normal file
@ -0,0 +1,97 @@
|
||||
# TUG Documentation
|
||||
|
||||
TUG is a Julia package that provides a framework for solving transport problems, notably diffusion, on uniform grids. It implements different numerical approaches, including implicit BTCS (Backward Time, Central Space) Euler and parallel 2D ADI (Alternating Direction Implicit).
|
||||
|
||||
```@contents
|
||||
```
|
||||
|
||||
## Introduction
|
||||
|
||||
TUG, originally developed as a C++ library, is now available as a Julia package. It aims to offer a comprehensive toolkit for solving transport problems, such as diffusion and advection, on uniform grids.
|
||||
|
||||
## Installation
|
||||
|
||||
If TUG is locally cloned on your machine, you can install it by pointing to the local path. Open Julia REPL and follow these steps:
|
||||
|
||||
```julia
|
||||
using Pkg
|
||||
Pkg.develop(path="path/to/tug/julia/TUG") # Replace with the actual path to the TUG directory
|
||||
using TUG
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
Below are some basic examples of using TUG. For more detailed information, see the API section. For more advanced examples, see the test files in the `test` directory.
|
||||
|
||||
### Creating a Simulation
|
||||
|
||||
To create a simulation with TUG, you first need to set up a grid and boundary conditions. Here is an example of setting up a basic simulation:
|
||||
|
||||
```julia
|
||||
using TUG
|
||||
|
||||
# Create a 1D grid
|
||||
grid = TUG.Grid{Float64}(5, ones(1, 5))
|
||||
|
||||
# Define boundary conditions
|
||||
boundary = TUG.Boundary{Float64}(grid)
|
||||
|
||||
# Initialize a simulation with default parameters
|
||||
simulation = TUG.Simulation{Float64}(grid, boundary)
|
||||
```
|
||||
|
||||
### Running a Simulation
|
||||
|
||||
After setting up the simulation, you can run it and analyze the results:
|
||||
|
||||
```julia
|
||||
# Set initial concentrations
|
||||
TUG.setConcentrations!(grid, [1.0, 1.0, 20.0, 1.0, 1.0])
|
||||
|
||||
# Run the simulation
|
||||
TUG.run(simulation)
|
||||
|
||||
# Retrieve the concentrations after simulation
|
||||
concentrations = TUG.getConcentrations(grid)
|
||||
```
|
||||
|
||||
### Advanced Setup
|
||||
|
||||
You can also customize your simulation with different parameters:
|
||||
|
||||
```julia
|
||||
# Create a simulation with custom parameters
|
||||
simulation = TUG.Simulation{Float64}(
|
||||
grid,
|
||||
boundary;
|
||||
approach = TUG.FTCS,
|
||||
iterations = 2,
|
||||
timestep = 0.2,
|
||||
consoleOutput = TUG.CONSOLE_OUTPUT_ON,
|
||||
csvOutput = TUG.CSV_OUTPUT_ON
|
||||
)
|
||||
```
|
||||
|
||||
### Dynamic Simulation
|
||||
|
||||
For dynamic simulations where the concentration is manipulated externally during runtime:
|
||||
|
||||
```julia
|
||||
# Initialize a dynamic simulation
|
||||
dynamicSimulation = TUG.DynamicSimulation{Float64}(grid, boundary; timestep = 0.1)
|
||||
|
||||
# Create and update the grid over iterations
|
||||
TUG.createGrid(dynamicSimulation)
|
||||
for _ = 1:20
|
||||
TUG.next(dynamicSimulation)
|
||||
# Update the concentration
|
||||
end
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
For a detailed reference of all functionalities, see the API section:
|
||||
|
||||
```@autodocs
|
||||
Modules = [TUG]
|
||||
```
|
||||
@ -46,10 +46,7 @@ struct BoundaryElement{T}
|
||||
end
|
||||
|
||||
function BoundaryElement{T}(value::T)::BoundaryElement{T} where {T}
|
||||
if value < 0
|
||||
throw(ArgumentError("No negative concentration allowed."))
|
||||
end
|
||||
new{T}(CONSTANT, value)
|
||||
new{T}(TUG.CONSTANT, value)
|
||||
end
|
||||
end
|
||||
|
||||
@ -114,14 +111,14 @@ It includes the dimension of the grid and boundary elements for each side.
|
||||
"""
|
||||
struct Boundary{T}
|
||||
dim::UInt8
|
||||
cols::UInt32
|
||||
rows::UInt32
|
||||
cols::UInt32
|
||||
boundaries::Vector{Vector{BoundaryElement{T}}}
|
||||
|
||||
function Boundary{T}(grid::Grid{T})::Boundary{T} where {T}
|
||||
dim = grid.dim
|
||||
cols = grid.cols
|
||||
rows = grid.rows
|
||||
cols = grid.cols
|
||||
boundaries = Vector{Vector{BoundaryElement{T}}}(undef, 4)
|
||||
|
||||
if dim == 1
|
||||
@ -136,7 +133,7 @@ struct Boundary{T}
|
||||
throw(ArgumentError("Only 1- and 2-dimensional grids are defined!"))
|
||||
end
|
||||
|
||||
new{T}(dim, cols, rows, boundaries)
|
||||
new{T}(dim, rows, cols, boundaries)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -68,12 +68,9 @@ function calcExplicitConcentrationsBoundaryConstant(
|
||||
sy::T,
|
||||
)::T where {T}
|
||||
alpha_center_neighbor = calcAlphaIntercell(alpha_center, alpha_neighbor)
|
||||
alpha_center_center =
|
||||
alpha_center == alpha_neighbor ? alpha_center_neighbor :
|
||||
calcAlphaIntercell(alpha_center, alpha_center)
|
||||
|
||||
return sy * alpha_center_neighbor * conc_center +
|
||||
(1 - sy * (alpha_center_center + 2 * alpha_center)) * conc_center +
|
||||
(1 - sy * (alpha_center_neighbor + alpha_center)) * conc_center +
|
||||
sy * alpha_center * conc_bc
|
||||
end
|
||||
|
||||
@ -269,7 +266,7 @@ function BTCS_2D(
|
||||
|
||||
# Swap alphas, boundary conditions and sx/sy for column-wise calculation
|
||||
Threads.@threads for i = 1:cols
|
||||
localB = zeros(T, cols)
|
||||
localB = zeros(T, rows)
|
||||
A::Tridiagonal{T} = createCoeffMatrix(
|
||||
view(alphaY_t, i, :),
|
||||
view(alphaY_t_left, i, :),
|
||||
|
||||
@ -12,11 +12,11 @@ Represents a computational grid with concentration values and alpha coefficients
|
||||
It can be either 1D or 2D and includes dimensions, domain sizes, delta values, and matrices for concentrations and alpha coefficients.
|
||||
|
||||
# Fields
|
||||
- `cols::Int`: Number of columns in the grid.
|
||||
- `rows::Int`: Number of rows in the grid.
|
||||
- `cols::Int`: Number of columns in the grid.
|
||||
- `dim::Int`: Dimension of the grid (1 for 1D, 2 for 2D).
|
||||
- `domainCol::T`, `domainRow::T`: Size of the grid's domain in column and row direction.
|
||||
- `deltaCol::T`, `deltaRow::T`: Delta values for columns and rows.
|
||||
- `domainRow::T`, `domainCol::T`: Size of the grid's domain in column and row direction.
|
||||
- `deltaRow::T`, `deltaCol::T`: Delta values for columns and rows.
|
||||
- `concentrations::Ref{Matrix{T}}`: Reference to the matrix holding concentration values.
|
||||
- `alphaX::Ref{Matrix{T}}`: Reference to the matrix of alpha coefficients in the X direction.
|
||||
- `alphaY::Union{Ref{Matrix{T}},Nothing}`: Reference to the matrix of alpha coefficients in the Y direction (if applicable).
|
||||
@ -25,23 +25,31 @@ It can be either 1D or 2D and includes dimensions, domain sizes, delta values, a
|
||||
# Constructors
|
||||
- `Grid(length, alphaX)` creates a 1D grid with the given length and alphaX matrix.
|
||||
- `Grid(rows, cols, alphaX, alphaY)` creates a 2D grid with the given rows, columns, and alphaX and alphaY matrices.
|
||||
- `Grid(rows, cols, dim, domainCol, domainRow, deltaCol, deltaRow, concentrations, alphaX, alphaY, alphaX_t, alphaY_t)` creates a grid with the given parameters.
|
||||
- `Grid(rows, cols, dim, domainRow, domainCol, deltaRow, deltaCol, concentrations, alphaX, alphaY, alphaX_t, alphaY_t)` creates a grid with the given parameters.
|
||||
"""
|
||||
struct Grid{T}
|
||||
cols::Int
|
||||
rows::Int
|
||||
cols::Int
|
||||
dim::Int
|
||||
domainCol::T
|
||||
domainRow::T
|
||||
deltaCol::T
|
||||
domainCol::T
|
||||
deltaRow::T
|
||||
deltaCol::T
|
||||
concentrations::Matrix{T}
|
||||
alphaX::Matrix{T}
|
||||
alphaY::Union{Matrix{T},Nothing}
|
||||
alphaX_t::Matrix{T}
|
||||
alphaY_t::Union{Matrix{T},Nothing}
|
||||
|
||||
function Grid{T}(length::Int, alphaX::Matrix{T})::Grid{T} where {T}
|
||||
function Grid{T}(
|
||||
length::Int,
|
||||
alphaX::Matrix{T};
|
||||
domainLength::T = T(-1),
|
||||
)::Grid{T} where {T}
|
||||
if domainLength < 0
|
||||
domainLength = T(length)
|
||||
end
|
||||
|
||||
if length <= 3
|
||||
throw(ArgumentError("Given grid length too small. Must be greater than 3."))
|
||||
end
|
||||
@ -56,13 +64,13 @@ struct Grid{T}
|
||||
alphaX_t = alphaX'
|
||||
|
||||
new{T}(
|
||||
1,
|
||||
length,
|
||||
1,
|
||||
1,
|
||||
T(length),
|
||||
0,
|
||||
T(1),
|
||||
T(domainLength),
|
||||
0,
|
||||
T(domainLength / length),
|
||||
fill(T(0), 1, length),
|
||||
alphaX,
|
||||
nothing,
|
||||
@ -75,8 +83,17 @@ struct Grid{T}
|
||||
rows::Int,
|
||||
cols::Int,
|
||||
alphaX::Matrix{T},
|
||||
alphaY::Matrix{T},
|
||||
alphaY::Matrix{T};
|
||||
domainRow::T = T(-1),
|
||||
domainCol::T = T(-1),
|
||||
)::Grid{T} where {T}
|
||||
if domainRow < 0
|
||||
domainRow = T(rows)
|
||||
end
|
||||
if domainCol < 0
|
||||
domainCol = T(cols)
|
||||
end
|
||||
|
||||
if rows <= 3 || cols <= 3
|
||||
throw(
|
||||
ArgumentError(
|
||||
@ -96,13 +113,13 @@ struct Grid{T}
|
||||
alphaY_t = alphaY'
|
||||
|
||||
new{T}(
|
||||
cols,
|
||||
rows,
|
||||
cols,
|
||||
2,
|
||||
T(cols),
|
||||
T(rows),
|
||||
T(1),
|
||||
T(1),
|
||||
T(domainRow),
|
||||
T(domainCol),
|
||||
T(domainRow / rows),
|
||||
T(domainCol / cols),
|
||||
fill(T(0), rows, cols),
|
||||
alphaX,
|
||||
alphaY,
|
||||
@ -115,10 +132,10 @@ struct Grid{T}
|
||||
rows::Int,
|
||||
cols::Int,
|
||||
dim::Int,
|
||||
domainCol::T,
|
||||
domainRow::T,
|
||||
deltaCol::T,
|
||||
domainCol::T,
|
||||
deltaRow::T,
|
||||
deltaCol::T,
|
||||
concentrations::Matrix{T},
|
||||
alphaX::Matrix{T},
|
||||
alphaY::Union{Matrix{T},Nothing},
|
||||
@ -126,13 +143,13 @@ struct Grid{T}
|
||||
alphaY_t::Union{Matrix{T},Nothing},
|
||||
)::Grid{T} where {T}
|
||||
new{T}(
|
||||
cols,
|
||||
rows,
|
||||
cols,
|
||||
dim,
|
||||
domainCol,
|
||||
domainRow,
|
||||
deltaCol,
|
||||
domainCol,
|
||||
deltaRow,
|
||||
deltaCol,
|
||||
concentrations,
|
||||
alphaX,
|
||||
alphaY,
|
||||
@ -160,10 +177,10 @@ function clone(grid::Grid{T})::Grid{T} where {T}
|
||||
1,
|
||||
grid.cols,
|
||||
grid.dim,
|
||||
grid.domainCol,
|
||||
grid.domainRow,
|
||||
grid.deltaCol,
|
||||
grid.domainCol,
|
||||
grid.deltaRow,
|
||||
grid.deltaCol,
|
||||
copy(grid.concentrations),
|
||||
copy(grid.alphaX),
|
||||
nothing,
|
||||
@ -175,10 +192,10 @@ function clone(grid::Grid{T})::Grid{T} where {T}
|
||||
grid.rows,
|
||||
grid.cols,
|
||||
grid.dim,
|
||||
grid.domainCol,
|
||||
grid.domainRow,
|
||||
grid.deltaCol,
|
||||
grid.domainCol,
|
||||
grid.deltaRow,
|
||||
grid.deltaCol,
|
||||
copy(grid.concentrations),
|
||||
copy(grid.alphaX),
|
||||
copy(grid.alphaY),
|
||||
|
||||
@ -9,14 +9,14 @@ export clone,
|
||||
getAlphaX_t,
|
||||
getAlphaY_t,
|
||||
getConcentrations,
|
||||
setConcentrations!,
|
||||
setAlphaX!,
|
||||
setAlphaY!,
|
||||
getDomainCol,
|
||||
getDomainRow,
|
||||
getDeltaCol,
|
||||
getDeltaRow,
|
||||
getDim
|
||||
getDim,
|
||||
setAlphaX!,
|
||||
setAlphaY!,
|
||||
setConcentrations!
|
||||
|
||||
include("Boundary.jl")
|
||||
|
||||
|
||||
@ -8,8 +8,6 @@
|
||||
@test TUG.getType(be) == TUG.CONSTANT
|
||||
@test TUG.getValue(be) == 1.0
|
||||
@test TUG.getValue([be]) == [1.0]
|
||||
|
||||
@test_throws ArgumentError TUG.BoundaryElement{Float64}(-1.0)
|
||||
end
|
||||
|
||||
@testset "Boundary" begin
|
||||
@ -25,7 +23,6 @@
|
||||
@test TUG.getBoundaryElementType(boundary, TUG.TOP, 1) == TUG.CLOSED
|
||||
@test TUG.getBoundaryElementType(boundary, TUG.BOTTOM, 1) == TUG.CLOSED
|
||||
|
||||
@test_throws ArgumentError TUG.getBoundaryElementType(boundary, TUG.LEFT, -1)
|
||||
@test_throws ArgumentError TUG.getBoundaryElementType(boundary, TUG.RIGHT, 26)
|
||||
|
||||
@test TUG.getBoundaryElementValue(boundary, TUG.LEFT, 1) == -1.0
|
||||
@ -33,7 +30,6 @@
|
||||
@test TUG.getBoundaryElementValue(boundary, TUG.TOP, 1) == -1.0
|
||||
@test TUG.getBoundaryElementValue(boundary, TUG.BOTTOM, 1) == -1.0
|
||||
|
||||
@test_throws ArgumentError TUG.getBoundaryElementValue(boundary, TUG.BOTTOM, -1)
|
||||
@test_throws ArgumentError TUG.getBoundaryElementValue(boundary, TUG.TOP, 21)
|
||||
|
||||
TUG.setBoundarySideClosed!(boundary, TUG.LEFT)
|
||||
|
||||
@ -113,11 +113,11 @@
|
||||
TUG.next(simulation)
|
||||
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
|
||||
2.116922560959072 3.6843335107065727 14.255652775906785 3.5916901126508205 1.141911092414447
|
||||
2.1169225609590687 3.684333510706568 14.255652775906759 3.5916901126508134 1.1419110924144453
|
||||
2.1169225609590674 3.6843335107065607 14.255652775906748 3.591690112650811 1.1419110924144442
|
||||
2.1169225609590687 3.684333510706565 14.255652775906766 3.5916901126508147 1.1419110924144449
|
||||
2.116922560959073 3.684333510706576 14.25565277590681 3.5916901126508267 1.141911092414448
|
||||
]
|
||||
@test isapprox(
|
||||
TUG.getConcentrations(simulation, 1),
|
||||
|
||||
@ -114,11 +114,11 @@
|
||||
)
|
||||
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
|
||||
2.116922560959072 3.6843335107065727 14.255652775906785 3.5916901126508205 1.141911092414447
|
||||
2.1169225609590687 3.684333510706568 14.255652775906759 3.5916901126508134 1.1419110924144453
|
||||
2.1169225609590674 3.6843335107065607 14.255652775906748 3.591690112650811 1.1419110924144442
|
||||
2.1169225609590687 3.684333510706565 14.255652775906766 3.5916901126508147 1.1419110924144449
|
||||
2.116922560959073 3.684333510706576 14.25565277590681 3.5916901126508267 1.141911092414448
|
||||
]
|
||||
@test isapprox(TUG.getConcentrations(grid), expected_concentrations, atol = 1e-6)
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user