Skip to content
Snippets Groups Projects
Commit 749d7b5c authored by Brian Groenke's avatar Brian Groenke
Browse files

Rename CompoundProcess -> CoupledProcesses

parent bdb877eb
No related branches found
No related tags found
1 merge request!57Add support for per-layer callbacks
......@@ -11,7 +11,7 @@ using Reexport
# Common types and methods
export Layer, SubSurface, Top, Bottom
export Process, SubSurfaceProcess, BoundaryProcess, CompoundProcess, Coupled
export Process, SubSurfaceProcess, BoundaryProcess, CoupledProcesses, Coupled
export BoundaryStyle, Dirichlet, Neumann
export Callback, CallbackStyle
include("types.jl")
......
......@@ -3,7 +3,7 @@ Module containing types and functions for enabling time-integration of a CryoGri
"""
module Drivers
using CryoGrid: Land, SubSurface, CompoundProcess, Callback, CallbackStyle, Discrete, Continuous
using CryoGrid: Land, SubSurface, CoupledProcesses, Callback, CallbackStyle, Discrete, Continuous
using CryoGrid.InputOutput
using CryoGrid.Numerics
using CryoGrid.Physics: Heat
......@@ -40,7 +40,7 @@ JacobianStyle(::Type{<:Tile}) = DefaultJac()
# Auto-detect Jacobian sparsity for problems with one or more heat-only layers.
# Note: This assumes that the processes/forcings on the boundary layers do not violate the tridiagonal structure!
# Unfortunately, the Stratigraphy type signature is a bit nasty to work with :(
const HeatOnlyTile = Tile{<:Stratigraphy{N,<:Tuple{TTop,Vararg{<:Union{<:StratComponent{<:SubSurface, <:CompoundProcess{<:Tuple{<:Heat}}},TBot}}}}} where {N,TTop,TBot}
const HeatOnlyTile = Tile{<:Stratigraphy{N,<:Tuple{TTop,Vararg{<:Union{<:StratComponent{<:SubSurface, <:CoupledProcesses{<:Tuple{<:Heat}}},TBot}}}}} where {N,TTop,TBot}
JacobianStyle(::Type{<:HeatOnlyTile}) = TridiagJac()
# DiffEq/SciML driver
......
module Land
import CryoGrid: Layer, Top, Bottom, SubSurface, Process, SubSurfaceProcess, BoundaryProcess, CompoundProcess
import CryoGrid: Layer, Top, Bottom, SubSurface, Process, SubSurfaceProcess, BoundaryProcess, CoupledProcesses
import CryoGrid: variables, initialcondition!, prognosticstep!, diagnosticstep!, interact!, observe
using CryoGrid.Layers
......
......@@ -6,7 +6,7 @@ Represents a single component (layer + processes) in the stratigraphy.
struct StratComponent{TLayer,TProcess,name}
layer::TLayer
process::TProcess
StratComponent(name::Symbol, layer::TLayer, process::TProcess) where {TLayer<:Layer,TProcess<:CompoundProcess} =
StratComponent(name::Symbol, layer::TLayer, process::TProcess) where {TLayer<:Layer,TProcess<:CoupledProcesses} =
new{TLayer,TProcess,name}(layer,process)
end
ConstructionBase.constructorof(::Type{StratComponent{TLayer,TProcess,name}}) where {TLayer,TProcess,name} = (layer,process) -> StratComponent(name, layer, process)
......@@ -19,9 +19,9 @@ componentname(::Type{<:StratComponent{L,P,name}}) where {L,P,name} = name
Base.show(io::IO, node::StratComponent{L,P,name}) where {L,P,name} = print(io, "$name($L,$P)")
# Constructors for stratigraphy nodes
top(bcs::BoundaryProcess...) = StratComponent(:top, Top(), CompoundProcess(bcs...))
bottom(bcs::BoundaryProcess...) = StratComponent(:bottom, Bottom(), CompoundProcess(bcs...))
subsurface(name::Symbol, layer::SubSurface, processes::SubSurfaceProcess...) = StratComponent(name, layer, CompoundProcess(processes...))
top(bcs::BoundaryProcess...) = StratComponent(:top, Top(), CoupledProcesses(bcs...))
bottom(bcs::BoundaryProcess...) = StratComponent(:bottom, Bottom(), CoupledProcesses(bcs...))
subsurface(name::Symbol, layer::SubSurface, processes::SubSurfaceProcess...) = StratComponent(name, layer, CoupledProcesses(processes...))
"""
Stratigraphy{N,TComponents,Q}
......
module Physics
import CryoGrid: Process, CompoundProcess, Coupled, Layer, Top, Bottom, SubSurface
import CryoGrid: Process, CoupledProcesses, Coupled, Layer, Top, Bottom, SubSurface
import CryoGrid: diagnosticstep!, initialcondition!, interact!, prognosticstep!, variables, callbacks, observe
using CryoGrid.Layers
......
# Default empty implementations of diagnostic_step! and prognostic_step! for boundary layers
diagnosticstep!(::Top, ::CompoundProcess, state) = nothing
prognosticstep!(::Top, ::CompoundProcess, state) = nothing
diagnosticstep!(::Bottom, ::CompoundProcess, state) = nothing
prognosticstep!(::Bottom, ::CompoundProcess, state) = nothing
variables(layer::Layer, ps::CompoundProcess) = tuplejoin((variables(layer,p) for p in ps.processes)...)
callbacks(layer::Layer, ps::CompoundProcess) = tuplejoin((callbacks(layer,p) for p in ps.processes)...)
diagnosticstep!(::Top, ::CoupledProcesses, state) = nothing
prognosticstep!(::Top, ::CoupledProcesses, state) = nothing
diagnosticstep!(::Bottom, ::CoupledProcesses, state) = nothing
prognosticstep!(::Bottom, ::CoupledProcesses, state) = nothing
variables(layer::Layer, ps::CoupledProcesses) = tuplejoin((variables(layer,p) for p in ps.processes)...)
callbacks(layer::Layer, ps::CoupledProcesses) = tuplejoin((callbacks(layer,p) for p in ps.processes)...)
"""
interact!(l1::Layer, ps1::CompoundProcess{P1}, l2::Layer, ps2::CompoundProcess{P2}, s1, s2) where {P1,P2}
interact!(l1::Layer, ps1::CoupledProcesses{P1}, l2::Layer, ps2::CoupledProcesses{P2}, s1, s2) where {P1,P2}
Default implementation of `interact!` for multi-process (CompoundProcess) types. Generates a specialized implementation that calls
Default implementation of `interact!` for multi-process (CoupledProcesses) types. Generates a specialized implementation that calls
`interact!` on all pairs of processes between the two layers. Since it is a generated function, the process matching
occurs at compile-time and the emitted code will simply be a sequence of `interact!` calls. Pairs of processes which
lack a definition of `interact!` should be automatically omitted by the compiler.
"""
@generated function interact!(l1::Layer, ps1::CompoundProcess{P1}, l2::Layer, ps2::CompoundProcess{P2}, s1, s2) where {P1,P2}
@generated function interact!(l1::Layer, ps1::CoupledProcesses{P1}, l2::Layer, ps2::CoupledProcesses{P2}, s1, s2) where {P1,P2}
p1types = Tuple(P1.parameters)
p2types = Tuple(P2.parameters)
crossprocesses = [(i,j) for (i,p1) in enumerate(p1types) for (j,p2) in enumerate(p2types)]
......@@ -26,11 +26,11 @@ lack a definition of `interact!` should be automatically omitted by the compiler
return expr
end
"""
diagnosticstep!(l::Layer, ps::CompoundProcess{P}, state) where {P}
diagnosticstep!(l::Layer, ps::CoupledProcesses{P}, state) where {P}
Default implementation of `diagnosticstep!` for multi-process types. Calls each process in sequence.
"""
@generated function diagnosticstep!(l::Layer, ps::CompoundProcess{P}, state) where {P}
@generated function diagnosticstep!(l::Layer, ps::CoupledProcesses{P}, state) where {P}
expr = Expr(:block)
for i in 1:length(P.parameters)
@>> quote
......@@ -40,11 +40,11 @@ Default implementation of `diagnosticstep!` for multi-process types. Calls each
return expr
end
"""
prognosticstep!(l::Layer, ps::CompoundProcess{P}, state) where {P}
prognosticstep!(l::Layer, ps::CoupledProcesses{P}, state) where {P}
Default implementation of `prognosticstep!` for multi-process types. Calls each process in sequence.
"""
@generated function prognosticstep!(l::Layer, ps::CompoundProcess{P}, state) where {P}
@generated function prognosticstep!(l::Layer, ps::CoupledProcesses{P}, state) where {P}
expr = Expr(:block)
for i in 1:length(P.parameters)
@>> quote
......@@ -54,11 +54,11 @@ Default implementation of `prognosticstep!` for multi-process types. Calls each
return expr
end
"""
initialcondition!(l::Layer, ps::CompoundProcess{P}, state) where {P}
initialcondition!(l::Layer, ps::CoupledProcesses{P}, state) where {P}
Default implementation of `initialcondition!` for multi-process types. Calls each process in sequence.
"""
@generated function initialcondition!(l::Layer, ps::CompoundProcess{P}, state) where {P}
@generated function initialcondition!(l::Layer, ps::CoupledProcesses{P}, state) where {P}
expr = Expr(:block)
for i in 1:length(P.parameters)
@>> quote
......@@ -68,11 +68,11 @@ Default implementation of `initialcondition!` for multi-process types. Calls eac
return expr
end
"""
initialcondition!(l::Layer, ps::CompoundProcess{P}, state) where {P}
initialcondition!(l::Layer, ps::CoupledProcesses{P}, state) where {P}
Default implementation of `initialcondition!` for multi-process types. Calls each process in sequence.
"""
@generated function initialcondition!(l1::Layer, ps1::CompoundProcess{P1}, l2::Layer, ps2::CompoundProcess{P2}, s1, s2) where {P1,P2}
@generated function initialcondition!(l1::Layer, ps1::CoupledProcesses{P1}, l2::Layer, ps2::CoupledProcesses{P2}, s1, s2) where {P1,P2}
p1types = Tuple(P1.parameters)
p2types = Tuple(P2.parameters)
crossprocesses = [(i,j) for (i,p1) in enumerate(p1types) for (j,p2) in enumerate(p2types)]
......@@ -85,11 +85,11 @@ Default implementation of `initialcondition!` for multi-process types. Calls eac
return expr
end
"""
observe(::Val{name}, l::Layer, ps::CompoundProcess{P}, state) where {P}
observe(::Val{name}, l::Layer, ps::CoupledProcesses{P}, state) where {P}
Default implementation of `observe` for multi-process types. Calls each process in sequence.
"""
@generated function observe(val::Val{name}, l::Layer, ps::CompoundProcess{P}, state) where {name,P}
@generated function observe(val::Val{name}, l::Layer, ps::CoupledProcesses{P}, state) where {name,P}
expr = Expr(:block)
for i in 1:length(P.parameters)
@>> quote
......
......@@ -43,35 +43,35 @@ but may include its own diagnostic (or even prognostic) variables, if necessary.
"""
abstract type BoundaryProcess <: Process end
"""
CompoundProcess{TProcs} <: Process
CoupledProcesses{TProcs} <: Process
Represents an explicitly or implicitly coupled system of processes. `TProcs` is always a `Tuple`
of other processes.
"""
struct CompoundProcess{TProcs} <: Process
struct CoupledProcesses{TProcs} <: Process
processes::TProcs
CompoundProcess(processes::Tuple{Vararg{Process}}) = new{typeof(processes)}(processes)
CompoundProcess(processes::SubSurfaceProcess...) = new{typeof(processes)}(processes)
CompoundProcess(processes::BoundaryProcess...) = new{typeof(processes)}(processes)
CoupledProcesses(processes::Tuple{Vararg{Process}}) = new{typeof(processes)}(processes)
CoupledProcesses(processes::SubSurfaceProcess...) = new{typeof(processes)}(processes)
CoupledProcesses(processes::BoundaryProcess...) = new{typeof(processes)}(processes)
end
Base.iterate(cp::CompoundProcess) = Base.iterate(cp.processes)
Base.iterate(cp::CompoundProcess, state) = Base.iterate(cp.processes, state)
Base.iterate(cp::CoupledProcesses) = Base.iterate(cp.processes)
Base.iterate(cp::CoupledProcesses, state) = Base.iterate(cp.processes, state)
"""
Coupled{P1,P2} = CompoundProcess{Tuple{T1,T2}} where {T1,T2}
Coupled{P1,P2} = CoupledProcesses{Tuple{T1,T2}} where {T1,T2}
Represents an explicitly coupled pair processes. Alias for `CompoundProcess{Tuple{P1,P2}}`.
Represents an explicitly coupled pair processes. Alias for `CoupledProcesses{Tuple{P1,P2}}`.
`Coupled` provides a simple mechanism for defining new behaviors on multi-processes systems.
"""
const Coupled{P1,P2} = CompoundProcess{Tuple{T1,T2}} where {T1,T2}
const Coupled{P1,P2} = CoupledProcesses{Tuple{T1,T2}} where {T1,T2}
"""
Coupled(p1,p2)
Alias for `CompoundProcess(p1,p2)`.
Alias for `CoupledProcesses(p1,p2)`.
"""
Coupled(p1::P1, p2::P2) where {P1<:Process,P2<:Process} = CompoundProcess(p1,p2)
Coupled(p1::P1, p2::P2) where {P1<:Process,P2<:Process} = CoupledProcesses(p1,p2)
# Base methods
Base.show(io::IO, ps::CompoundProcess{T}) where T = print(io, "$T")
@propagate_inbounds @inline Base.getindex(ps::CompoundProcess, i) = ps.processes[i]
Base.show(io::IO, ps::CoupledProcesses{T}) where T = print(io, "$T")
@propagate_inbounds @inline Base.getindex(ps::CoupledProcesses, i) = ps.processes[i]
# allow broadcasting of Process types
Base.Broadcast.broadcastable(p::Process) = Ref(p)
......
......@@ -18,15 +18,15 @@ include("../types.jl")
if i == 1
@test CryoGrid.componentname(component) == :top
@test typeof(component.layer) <: Top
@test typeof(component.process) <: CompoundProcess{Tuple{TestBoundary}}
@test typeof(component.process) <: CoupledProcesses{Tuple{TestBoundary}}
elseif i == 2
@test CryoGrid.componentname(component) == :testground
@test typeof(component.layer) <: TestGroundLayer
@test typeof(component.process) <: CompoundProcess{Tuple{TestGroundProcess}}
@test typeof(component.process) <: CoupledProcesses{Tuple{TestGroundProcess}}
elseif i == 3
@test CryoGrid.componentname(component) == :bottom
@test typeof(component.layer) <: Bottom
@test typeof(component.process) <: CompoundProcess{Tuple{TestBoundary}}
@test typeof(component.process) <: CoupledProcesses{Tuple{TestBoundary}}
end
end
end
......@@ -46,19 +46,19 @@ include("../types.jl")
if i == 1
@test CryoGrid.componentname(component) == :top
@test typeof(component.layer) <: Top
@test typeof(component.process) <: CompoundProcess{Tuple{TestBoundary}}
@test typeof(component.process) <: CoupledProcesses{Tuple{TestBoundary}}
elseif i == 2
@test CryoGrid.componentname(component) == :testground1
@test typeof(component.layer) <: TestGroundLayer
@test typeof(component.process) <: CompoundProcess{Tuple{TestGroundProcess}}
@test typeof(component.process) <: CoupledProcesses{Tuple{TestGroundProcess}}
elseif i == 3
@test CryoGrid.componentname(component) == :testground2
@test typeof(component.layer) <: TestGroundLayer
@test typeof(component.process) <: CompoundProcess{Tuple{TestGroundProcess}}
@test typeof(component.process) <: CoupledProcesses{Tuple{TestGroundProcess}}
elseif i == 4
@test CryoGrid.componentname(component) == :bottom
@test typeof(component.layer) <: Bottom
@test typeof(component.process) <: CompoundProcess{Tuple{TestBoundary}}
@test typeof(component.process) <: CoupledProcesses{Tuple{TestBoundary}}
end
end
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment