Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions julia/MOLE.jl/docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,31 @@ Once you have built the documentation (either from the REPL or the command line)

## Functions

### Grids

The `Grids` module provides the grid data structures. A grid stores dimensionality, topology, spacing, coordinates, and boundary metadata in one object.

Example of usage:

```julia
using MOLE.Grids

grid = makeGrid(m=64, n=64, dx=1/64, dy=1/64)

grid.dim
grid.topology
grid.nodes
grid.faces
grid.centers
```

```@docs
MOLE.Grids.makeGrid
MOLE.Grids.validateGrid
MOLE.Grids.Grid
MOLE.Grids.BoundaryMetadata
```

### Operators

```@docs
Expand Down
11 changes: 11 additions & 0 deletions julia/MOLE.jl/src/Grids/Grids.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Grids

export AbstractGrid, Grid, BoundaryMetadata
export makeGrid, validateGrid

include("topologies.jl")
include("coordinates.jl")
include("validate_grid.jl")
include("make_grid.jl")

end # module Grids
120 changes: 120 additions & 0 deletions julia/MOLE.jl/src/Grids/coordinates.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#=
SPDX-License-Identifier: GPL-3.0-or-later
© 2008-2024 San Diego State University Research Foundation (SDSURF).
See LICENSE file or https://www.gnu.org/licenses/gpl-3.0.html for details.
=#

function _coordinates_1d(m::Int, dx)
x_node = collect(0:m) .* dx
x_center = vcat(0.0, collect(0.5:1:(m - 0.5)) .* dx, m * dx)
x_face = x_node

nodes = (; X = x_node)
faces = (; X = x_face)
centers = (; X = x_center)

return nodes, faces, centers
end

function _coordinates_2d(m::Int, n::Int, dx, dy)
xn = collect(0:m) .* dx
yn = collect(0:n) .* dy

xc = vcat(0.0, collect(0.5:1:(m - 0.5)) .* dx, m * dx)
yc = vcat(0.0, collect(0.5:1:(n - 0.5)) .* dy, n * dy)

xu = xn
yu = collect(0.5:1:(n - 0.5)) .* dy

xv = collect(0.5:1:(m - 0.5)) .* dx
yv = yn

nodes = _ndgrid2_named(xn, yn)
centers = _ndgrid2_named(xc, yc)

faces = (
u = _ndgrid2_named(xu, yu),
v = _ndgrid2_named(xv, yv),
)

return nodes, faces, centers
end

function _coordinates_3d(m::Int, n::Int, o::Int, dx, dy, dz)
xn = collect(0:m) .* dx
yn = collect(0:n) .* dy
zn = collect(0:o) .* dz

xc = vcat(0.0, collect(0.5:1:(m - 0.5)) .* dx, m * dx)
yc = vcat(0.0, collect(0.5:1:(n - 0.5)) .* dy, n * dy)
zc = vcat(0.0, collect(0.5:1:(o - 0.5)) .* dz, o * dz)

nodes = _ndgrid3_named(xn, yn, zn)
centers = _ndgrid3_named(xc, yc, zc)

faces = (
u = _ndgrid3_named(
xn,
collect(0.5:1:(n - 0.5)) .* dy,
collect(0.5:1:(o - 0.5)) .* dz,
),
v = _ndgrid3_named(
collect(0.5:1:(m - 0.5)) .* dx,
yn,
collect(0.5:1:(o - 0.5)) .* dz,
),
w = _ndgrid3_named(
collect(0.5:1:(m - 0.5)) .* dx,
collect(0.5:1:(n - 0.5)) .* dy,
zn,
),
)

return nodes, faces, centers
end

function _coordinates_curvilinear_2d(nodes)
NX = nodes.X
NY = nodes.Y

faces = (
u = (
X = 0.5 .* (NX[:, 1:(end - 1)] .+ NX[:, 2:end]),
Y = 0.5 .* (NY[:, 1:(end - 1)] .+ NY[:, 2:end]),
),
v = (
X = 0.5 .* (NX[1:(end - 1), :] .+ NX[2:end, :]),
Y = 0.5 .* (NY[1:(end - 1), :] .+ NY[2:end, :]),
),
)

centers = (
X = 0.25 .* (
NX[1:(end - 1), 1:(end - 1)] .+
NX[2:end, 1:(end - 1)] .+
NX[1:(end - 1), 2:end] .+
NX[2:end, 2:end]
),
Y = 0.25 .* (
NY[1:(end - 1), 1:(end - 1)] .+
NY[2:end, 1:(end - 1)] .+
NY[1:(end - 1), 2:end] .+
NY[2:end, 2:end]
),
)

return faces, centers
end

function _ndgrid2_named(x, y)
X = repeat(reshape(x, :, 1), 1, length(y))
Y = repeat(reshape(y, 1, :), length(x), 1)
return (; X, Y)
end

function _ndgrid3_named(x, y, z)
X = repeat(reshape(x, :, 1, 1), 1, length(y), length(z))
Y = repeat(reshape(y, 1, :, 1), length(x), 1, length(z))
Z = repeat(reshape(z, 1, 1, :), length(x), length(y), 1)
return (; X, Y, Z)
end
83 changes: 83 additions & 0 deletions julia/MOLE.jl/src/Grids/make_grid.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#=
SPDX-License-Identifier: GPL-3.0-or-later
© 2008-2024 San Diego State University Research Foundation (SDSURF).
See LICENSE file or https://www.gnu.org/licenses/gpl-3.0.html for details.
=#

"""
makeGrid(grid::Grid; allowPartial::Bool = true)
makeGrid(; allowPartial::Bool = true, kwargs...)

Construct and validate a computational grid.

`makeGrid` is the primary constructor for `Grid` objects. It accepts either an
existing `Grid` instance or keyword arguments describing the computational
domain. The resulting grid is validated, normalized, and enriched with derived
metadata such as the spatial dimension, topology, coordinate arrays, and
boundary-condition information.

# Arguments

- `grid::Grid`: An existing grid to validate and normalize.
- `allowPartial::Bool=true`: If `true`, allows partially specified grids to be
created without requiring all fields. This is primarily intended for
incremental grid construction or internal use.

When called with keyword arguments, commonly used parameters include:

- `m`, `n`, `o`: Number of cells in each spatial direction.
- `dx`, `dy`, `dz`: Grid spacing in each spatial direction.
- `topology`: Grid topology (e.g. `:uniform`, `:periodic`, `:curvilinear`).
- `nodes`: User-supplied nodal coordinates for curvilinear grids.
- `bc`: Boundary-condition metadata.

# Returns

A validated [`Grid`](@ref) object.

# Examples

Construct a one-dimensional uniform grid:

```julia
grid = makeGrid(
m = 100,
dx = 0.01,
)
```

Construct a two-dimensional uniform grid:

```julia
grid = makeGrid(
m = 64,
n = 64,
dx = 1/64,
dy = 1/64,
)
```

Construct a curvilinear grid from user-defined nodal coordinates:

```julia
grid = makeGrid(
m = m,
n = n,
topology = :curvilinear,
nodes = (X = X, Y = Y),
)
```

# Notes

`makeGrid` delegates the validation and normalization of all inputs to
[`validateGrid`](@ref).
"""
function makeGrid(grid::Grid; allowPartial::Bool = true)
return validateGrid(grid; allowPartial = allowPartial)
end

function makeGrid(; allowPartial::Bool = true, kwargs...)
raw = Dict{Symbol, Any}(kwargs)
return validateGrid(raw; allowPartial = allowPartial)
end
114 changes: 114 additions & 0 deletions julia/MOLE.jl/src/Grids/topologies.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#=
SPDX-License-Identifier: GPL-3.0-or-later
© 2008-2024 San Diego State University Research Foundation (SDSURF).
See LICENSE file or https://www.gnu.org/licenses/gpl-3.0.html for details.
=#

abstract type AbstractGrid end

"""
BoundaryMetadata{T}

Stores the boundary-condition metadata associated with a computational grid.

`BoundaryMetadata` is used by [`Grid`](@ref) and contains the coefficients
required to define scalar boundary conditions, together with flags indicating
whether each coordinate direction is periodic.

# Fields

- `dc::Vector{T}`: Dirichlet coefficients for each boundary.
- `nc::Vector{T}`: Neumann coefficients for each boundary.
- `isPeriodic::Vector{Bool}`: Periodicity flags for each coordinate direction.
- `hasData::Bool`: Indicates whether boundary-condition information has been
explicitly provided.

The expected lengths of `dc` and `nc` depend on the grid dimension:

| Dimension | Length |
|:----------|:------:|
| 1D | 2 |
| 2D | 4 |
| 3D | 6 |

The length of `isPeriodic` is equal to the number of spatial dimensions.

# Examples

```julia
bc = BoundaryMetadata(
dc = [1.0, 1.0],
nc = [0.0, 0.0],
isPeriodic = [false],
hasData = true,
)
```

A periodic one-dimensional grid can be represented by zero Dirichlet and
Neumann coefficients:

```julia
bc = BoundaryMetadata(
dc = [0.0, 0.0],
nc = [0.0, 0.0],
isPeriodic = [true],
hasData = true,
)
```
"""
Base.@kwdef struct BoundaryMetadata{T}
dc::Vector{T} = T[]
nc::Vector{T} = T[]
isPeriodic::Vector{Bool} = Bool[]
hasData::Bool = false
end

"""
Grid{T} <: AbstractGrid

Stores the geometric and boundary-condition metadata for a computational grid.

A `Grid` is the central data object used by the MOLE 2.0 grid API. It records
the grid dimension, topology, cell counts, grid spacings, coordinate arrays,
and boundary-condition metadata. Operators should treat `Grid` objects as
read-only inputs.

# Fields

- `dim::Int`: Spatial dimension of the grid.
- `topology::Symbol`: Grid topology, such as `:uniform`, `:periodic`, or `:curvilinear`.
- `m`, `n`, `o`: Number of cells in the x-, y-, and z-directions.
- `dx`, `dy`, `dz`: Grid spacing in the x-, y-, and z-directions.
- `nodes::NamedTuple`: Nodal coordinate arrays.
- `faces::NamedTuple`: Face coordinate arrays.
- `centers::NamedTuple`: Cell-center coordinate arrays.
- `bc::BoundaryMetadata{T}`: Boundary-condition metadata.

# Examples

```julia
grid = makeGrid(m = 64, dx = 1/64)

grid.dim
grid.topology
grid.nodes
```
"""
Base.@kwdef struct Grid{T} <: AbstractGrid
dim::Int
topology::Symbol

m::Union{Nothing, Int} = nothing
n::Union{Nothing, Int} = nothing
o::Union{Nothing, Int} = nothing

dx::Union{Nothing, T} = nothing
dy::Union{Nothing, T} = nothing
dz::Union{Nothing, T} = nothing

nodes::NamedTuple = NamedTuple()
faces::NamedTuple = NamedTuple()
centers::NamedTuple = NamedTuple()

bc::BoundaryMetadata{T} = BoundaryMetadata{T}()
end
Loading
Loading