Summary
HigherOrderInterfaceBoundary is exported by PDEBase and is part of the boundary type hierarchy, but it sits in a branch (AbstractInterfaceBoundary) that is sibling to AbstractLowerBoundary/AbstractUpperBoundary — not a subtype of either. Downstream packages (e.g. MethodOfLines.jl) that implement boundary-related functions dispatching on AbstractLowerBoundary/AbstractUpperBoundary silently miss HigherOrderInterfaceBoundary, causing MethodError at runtime.
Type hierarchy
AbstractBoundary
└─ AbstractTruncatingBoundary
├─ AbstractInterfaceBoundary ← HigherOrderInterfaceBoundary lives here
│ ├─ InterfaceBoundary{IsUpper_u, IsUpper_u2}
│ └─ HigherOrderInterfaceBoundary ← NOT <: AbstractLowerBoundary or AbstractUpperBoundary
├─ AbstractLowerBoundary ← offset(::AbstractLowerBoundary, i, len) = i
│ └─ LowerBoundary
└─ AbstractUpperBoundary ← offset(::AbstractUpperBoundary, i, len) = len - i + 1
└─ UpperBoundary
MWE
using PDEBase
# HigherOrderInterfaceBoundary is constructed during BC parsing
# when a PDE system has interface boundaries with derivative BCs.
#
# In MethodOfLines.jl, `offset` is defined for AbstractLowerBoundary and
# AbstractUpperBoundary but NOT for HigherOrderInterfaceBoundary:
#
# offset(::AbstractLowerBoundary, i, len) = i
# offset(::AbstractUpperBoundary, i, len) = len - i + 1
#
# When generate_array_bc_eqs.jl:144 calls offset(boundary, ...) on a
# HigherOrderInterfaceBoundary, it hits MethodError.
# PDEBase already defines:
PDEBase.isupper(::PDEBase.HigherOrderInterfaceBoundary) # returns true
# But there's no guidance or default implementation for offset()
# Downstream packages don't know they need to handle this type separately
Error (from MethodOfLines.jl MOL_Interface2 test):
MethodError: no method matching offset(::HigherOrderInterfaceBoundary, ::Int64, ::Int64)
Suggested fix
Since isupper(::HigherOrderInterfaceBoundary) = true is already defined in PDEBase (line 122 of parse_boundaries.jl), one of these approaches would help:
Option A: Add offset to PDEBase interface
Define offset in PDEBase with default implementations based on the existing isupper dispatch:
offset(::AbstractLowerBoundary, i, len) = i
offset(::AbstractUpperBoundary, i, len) = len - i + 1
offset(b::AbstractInterfaceBoundary, i, len) = isupper(b) ? len - i + 1 : i
This would cover HigherOrderInterfaceBoundary automatically and prevent future dispatch gaps for any new AbstractInterfaceBoundary subtypes.
Option B: Document the interface contract
If offset is intentionally left to downstream packages, document which functions must be implemented for each boundary subtype. Currently HigherOrderInterfaceBoundary has isupper, idx, and ordering but no offset, and this isn't documented anywhere.
Impact
Blocks 1 test in MethodOfLines.jl (MOL_Interface2 — "Nonlinlap with flux interface boundary condition"). The workaround is adding offset(::HigherOrderInterfaceBoundary, i, len) = len - i + 1 in MOL, but this is fragile — any new boundary type added to PDEBase could have the same gap.
Environment
- PDEBase v0.3.x
- MethodOfLines.jl stencils branch (commit a5519fbe)
Summary
HigherOrderInterfaceBoundaryis exported by PDEBase and is part of the boundary type hierarchy, but it sits in a branch (AbstractInterfaceBoundary) that is sibling toAbstractLowerBoundary/AbstractUpperBoundary— not a subtype of either. Downstream packages (e.g. MethodOfLines.jl) that implement boundary-related functions dispatching onAbstractLowerBoundary/AbstractUpperBoundarysilently missHigherOrderInterfaceBoundary, causingMethodErrorat runtime.Type hierarchy
MWE
Error (from MethodOfLines.jl MOL_Interface2 test):
Suggested fix
Since
isupper(::HigherOrderInterfaceBoundary) = trueis already defined in PDEBase (line 122 ofparse_boundaries.jl), one of these approaches would help:Option A: Add
offsetto PDEBase interfaceDefine
offsetin PDEBase with default implementations based on the existingisupperdispatch:This would cover
HigherOrderInterfaceBoundaryautomatically and prevent future dispatch gaps for any newAbstractInterfaceBoundarysubtypes.Option B: Document the interface contract
If
offsetis intentionally left to downstream packages, document which functions must be implemented for each boundary subtype. CurrentlyHigherOrderInterfaceBoundaryhasisupper,idx, andorderingbut nooffset, and this isn't documented anywhere.Impact
Blocks 1 test in MethodOfLines.jl (MOL_Interface2 — "Nonlinlap with flux interface boundary condition"). The workaround is adding
offset(::HigherOrderInterfaceBoundary, i, len) = len - i + 1in MOL, but this is fragile — any new boundary type added to PDEBase could have the same gap.Environment