Skip to content

Simple boundary conditions#41

Merged
kylebeggs merged 25 commits intomainfrom
simple_boundary_conditions
Jan 3, 2026
Merged

Simple boundary conditions#41
kylebeggs merged 25 commits intomainfrom
simple_boundary_conditions

Conversation

@Davide-Miotti
Copy link
Copy Markdown
Member

The goal is to make boundary conditions simple to understand and implement for any type of problem. Everything is still to be tested and of course a lot of code optimization still to do

@Davide-Miotti Davide-Miotti marked this pull request as draft November 16, 2025 21:03
Copy link
Copy Markdown
Member

@kylebeggs kylebeggs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall good start. I think what we really need here for the is the Holy traits system (named after a programmer/prof Tim Holy). an example being that adiabatic has the 'trait" of being a dirichlet bc. we can then use this trait to dispatch cleanly to make_bc. read up on this and lets discuss. I think you were starting to get to this design pattern already without knowing it! i am a big fan of it.

Comment thread src/boundary_conditions/boundary_conditions.jl Outdated
Comment thread src/boundary_conditions/energy.jl
Comment thread src/boundary_conditions/energy.jl
Comment thread src/boundary_conditions/energy.jl
Comment thread src/boundary_conditions/fluids.jl
Comment thread src/boundary_conditions/energy.jl Outdated
Comment thread src/boundary_conditions/energy.jl Outdated
Comment thread src/boundary_conditions/boundary_conditions.jl Outdated
Comment thread src/boundary_conditions/boundary_conditions.jl Outdated
Copy link
Copy Markdown
Member

@kylebeggs kylebeggs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall a good step forward, but i had some thoughts and used Claude to help me write them down in a readable manner form my bullet point thoughts. I then had it implement it. I'll make a PR if you like it:

The Problem

The original BC system had separate types for each physics domain:

struct Temperature{T} <: Dirichlet ... end      # energy
struct Adiabatic <: Neumann ... end             # energy
struct VelocityInlet{T} <: Dirichlet ... end    # fluids

This creates two issues:

  1. Code duplication: An adiabatic wall (dT/dn = 0) and a zero-gradient velocity outlet (dv/dn = 0) are mathematically identical Neumann conditions. Both need the same write_bc_neumann! treatment, but we'd need separate types and potentially duplicate code paths.

  2. No physics validation: Nothing prevents using Temperature with IncompressibleNavierStokes. The code silently accepts it.

The Solution: Two Orthogonal Dimensions

We separate two concerns that were conflated:

Dimension Purpose Examples
Mathematical type How the BC modifies the linear system Dirichlet, Neumann, Robin
Physics domain Which models this BC applies to Energy, Fluids, Walls

Mathematical Hierarchy (Existing)

This was already correct and unchanged:

AbstractBoundaryCondition
├── Dirichlet           → write_bc_dirichlet!
└── DerivativeBoundaryCondition
    ├── Neumann         → write_bc_neumann!
    └── Robin           → write_bc_robin!

Physics Domain (New)

Added as a type parameter:

struct FixedValue{P <: PhysicsDomain, T} <: Dirichlet
    value::T
end

struct ZeroGradient{P <: PhysicsDomain} <: Neumann end

Now ZeroGradient{EnergyPhysics} and ZeroGradient{FluidPhysics} share the same implementation but are distinguishable for validation.

Why Type Aliases, Not Separate Types?

We use const aliases to preserve user-friendly names:

const Temperature{T} = FixedValue{EnergyPhysics, T}
const Adiabatic = ZeroGradient{EnergyPhysics}
const VelocityOutlet = ZeroGradient{FluidPhysics}

Benefits:

  • Temperature(100.0) still works (unchanged API)
  • bc isa Temperature still works (type checking)
  • bc isa FixedValue also works (generic checks)
  • Single implementation for mathematically equivalent BCs

Why Runtime Validation, Not Compile-Time?

We considered parametric constraints on Domain{P}, but:

  1. Domain stores BCs in a Dict (heterogeneous collection)
  2. Models are stored as AbstractModel vector
  3. Full compile-time enforcement would require complex type gymnastics

Runtime validation in the Domain constructor is simpler and gives better error messages:

# In Domain constructor:
for (surf_name, bc) in boundaries
    if !is_compatible(physics_domain(typeof(bc)), physics_domain(typeof(model)))
        throw(ArgumentError("BC ... incompatible with model ..."))
    end
end

The Physics Trait System

Uses Holy traits pattern (zero runtime cost):

abstract type PhysicsDomain end
struct EnergyPhysics <: PhysicsDomain end
struct FluidPhysics <: PhysicsDomain end
struct WallPhysics <: PhysicsDomain end    # Compatible with both
struct GenericPhysics <: PhysicsDomain end # Default, skips validation

# Trait accessor
physics_domain(::Type{<:Temperature}) = EnergyPhysics()
physics_domain(::Type{<:SolidEnergy}) = EnergyPhysics()

# Compatibility
is_compatible(::EnergyPhysics, ::EnergyPhysics) = true
is_compatible(::WallPhysics, ::FluidPhysics) = true  # Walls work with fluids
is_compatible(::EnergyPhysics, ::FluidPhysics) = false

What About Physics-Specific BCs?

Some BCs have semantic meaning beyond their math:

  • Convection has h, k, T_inf (heat transfer coefficient, conductivity, ambient temp)
  • PressureOutlet targets the pressure field specifically, not velocity

These remain as standalone types with physics_domain traits:

struct Convection{H, K, T} <: Robin
    h::H   # semantic field names
    k::K
    T_inf::T
end
physics_domain(::Type{<:Convection}) = EnergyPhysics()

Summary

Before After
Separate types per physics Parametric types BC{PhysicsDomain}
No validation Runtime validation in Domain
Duplicate math implementations Shared via type parameters
N/A New VelocityOutlet for fluids

The key insight: separate what varies (physics domain) from what's shared (mathematical treatment).

Comment thread src/boundary_conditions/boundary_derivatives.jl Outdated
Comment thread src/boundary_conditions/boundary_derivatives.jl Outdated
Comment thread src/boundary_conditions/boundary_derivatives.jl Outdated
Comment thread src/boundary_conditions/boundary_derivatives.jl Outdated
Comment thread src/boundary_conditions/boundary_derivatives.jl Outdated
Comment thread src/boundary_conditions/energy.jl Outdated
Comment thread src/boundary_conditions/energy.jl Outdated
@Davide-Miotti
Copy link
Copy Markdown
Member Author

I have fixed the issues with the normals and made boundary condition enforcement faster by avoiding large allocations, did not implement your suggestions on the specification of the physical model yet, and also still need to implement the interface for the time-varying boundary conditions

Comment thread src/boundary_conditions/core/generic_types.jl Outdated
Comment thread src/unsused_utils.jl Outdated
Comment thread src/unsused_utils.jl Outdated
is_compatible(::T, ::T) where {T<:PhysicsDomain} = true
is_compatible(::WallPhysics, ::FluidPhysics) = true
is_compatible(::WallPhysics, ::EnergyPhysics) = true
is_compatible(::PhysicsDomain, ::PhysicsDomain) = false
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess this is just the fallback that if not defined, we make it false?

Copy link
Copy Markdown
Member Author

@Davide-Miotti Davide-Miotti Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it true with a warning:

#same domain
is_compatible(::T, ::T) where {T <: PhysicsDomain} = true

#different models with WallPhysics
is_compatible(::WallPhysics, ::FluidPhysics) = true
is_compatible(::WallPhysics, ::EnergyPhysics) = true

#Fallback rule: different domains are compatible but give warning
function is_compatible(bc::PhysicsDomain, model::PhysicsDomain)
    @warn """
    UNDEFINED PHYSICS DOMAIN COMPATIBILITY:
    BC domain: $(typeof(bc))
    Model domain: $(typeof(model))

    There is no compatibility rule defined for these domains.
        This BC will be allowed, but consider defining explicit compatibility rules in `physics_traits.jl`.
        """
    return true
end

Comment thread src/boundary_conditions/numerical/derivatives.jl
@Davide-Miotti
Copy link
Copy Markdown
Member Author

Davide-Miotti commented Jan 2, 2026

I finished addressing your observations and wrote a first test for solution of 2d heat equation with method of manufactured solutions. Now we just need to think about the unsteady case and then we are done with BCs I think

@Davide-Miotti Davide-Miotti marked this pull request as ready for review January 2, 2026 19:31
Copy link
Copy Markdown
Member

@kylebeggs kylebeggs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generally looks good to me, i think once tests are passing we can merge. Julia 1.10 tests are not passing currently

Comment thread src/boundary_conditions/numerical/derivatives.jl Outdated
@kylebeggs
Copy link
Copy Markdown
Member

@Davide-Miotti there are issues with the new WHatsThePoint, etc. honestly since this is still an un-regstered and provate repo, Im going to just merge and then when we get WhatsThePoint merged we can come back to this. It will just be easier. The tests pass locally.

@kylebeggs kylebeggs merged commit d0ca33b into main Jan 3, 2026
0 of 4 checks passed
@Davide-Miotti Davide-Miotti deleted the simple_boundary_conditions branch January 3, 2026 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants