mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-10-03 22:57:57 +00:00
refactor(physics): Create consolidated AbstractPhysics definition
- Define AbstractPhysics abstract type in dedicated file - Consolidate documentation from previous duplicate definitions - Document type as coupling of Mesh, Material, Field, and Formulation - Add comprehensive examples for 3D solid, heat, and beam physics - Include multiphysics pattern documentation - Remove duplicate AbstractPhysics definitions across codebase - 109 lines of documentation and abstract type definition
This commit is contained in:
+84
-113
@@ -4,135 +4,106 @@
|
||||
"""
|
||||
AbstractPhysics
|
||||
|
||||
Base type for all physics implementations in JuliaFEM.
|
||||
Abstract type for all physics problems in JuliaFEM.
|
||||
|
||||
Physics objects serve as:
|
||||
1. **Dispatch tags** - Select correct assembly method via multiple dispatch
|
||||
2. **Configuration holders** - Store physics-specific options
|
||||
3. **Field name providers** - Define primary field ("displacement", "temperature", etc.)
|
||||
Physics is the **coupling** of four components:
|
||||
- **Mesh**: Topology/geometry (where)
|
||||
- **Material**: Constitutive law (what material)
|
||||
- **Field**: Solution variables (what we solve for)
|
||||
- **Formulation**: Discretization strategy (how we discretize)
|
||||
|
||||
# Interface Requirements
|
||||
|
||||
All physics types must support:
|
||||
- `assemble!(physics)` - Assemble global system matrices/operators
|
||||
- `solve!(physics)` - Solve the physics problem
|
||||
- `add_dirichlet!(physics, ...)` - Apply essential boundary conditions
|
||||
- `add_neumann!(physics, ...)` - Apply natural boundary conditions
|
||||
|
||||
# Concrete Types
|
||||
|
||||
- `Physics{Formulation, Field, Mesh, Material}` - Standard FEM physics problem
|
||||
|
||||
# Design Philosophy
|
||||
|
||||
Each physics type represents a specific set of governing equations:
|
||||
- `ElasticityPhysics` → ∇⋅σ = ρü + b
|
||||
- `HeatPhysics` → ∇⋅(k∇T) = ρcₚ∂T/∂t + Q
|
||||
- `ContactPhysics` → Contact constraints and friction
|
||||
- etc.
|
||||
**Physics references Mesh (does not own it)**:
|
||||
- Multiple physics can share one mesh (multiphysics coupling)
|
||||
- No mesh duplication (memory efficient)
|
||||
- Mesh is the topology owner
|
||||
- Physics is the problem owner
|
||||
|
||||
# Multi-Physics Coupling (Future)
|
||||
**Type parameters enable dispatch specialization**:
|
||||
```julia
|
||||
# Specialize assembly for formulation × field combinations
|
||||
assemble!(::Physics{ContinuumFormulation{FullThreeD}, Displacement{3}, M, Mat})
|
||||
assemble!(::Physics{BeamFormulation{Timoshenko}, DisplacementRotation{3}, M, Mat})
|
||||
|
||||
The design supports coupled physics via composition:
|
||||
# Generic fallback
|
||||
assemble!(::Physics{Fm, F, M, Mat}) where {Fm, F, M, Mat}
|
||||
```
|
||||
|
||||
# Examples
|
||||
|
||||
```julia
|
||||
# Future: Thermo-mechanical coupling
|
||||
coupled = CoupledPhysics(
|
||||
ElasticityPhysics(...),
|
||||
HeatPhysics(...)
|
||||
# 3D solid mechanics
|
||||
physics = Physics(
|
||||
name = "cantilever",
|
||||
mesh = mesh,
|
||||
element_set = :all,
|
||||
field = Displacement{3}(),
|
||||
formulation = ContinuumFormulation{FullThreeD}(),
|
||||
material = LinearElastic(E=210e9, ν=0.3)
|
||||
)
|
||||
|
||||
# Solver handles coupling automatically
|
||||
assemble!(assembly, coupled, elements, time)
|
||||
# Heat transfer
|
||||
physics_thermal = Physics(
|
||||
name = "heat_conduction",
|
||||
mesh = mesh,
|
||||
element_set = :solid,
|
||||
field = Temperature(),
|
||||
formulation = ContinuumFormulation{FullThreeD}(),
|
||||
material = ThermalMaterial(k=50.0, ρ=7850.0, c=450.0)
|
||||
)
|
||||
|
||||
# 3D beam
|
||||
physics_beam = Physics(
|
||||
name = "beam",
|
||||
mesh = beam_mesh,
|
||||
element_set = :all,
|
||||
field = DisplacementRotation{3}(),
|
||||
formulation = BeamFormulation{Timoshenko}(),
|
||||
material = steel
|
||||
)
|
||||
```
|
||||
|
||||
This enables:
|
||||
- Sequential coupling (operator splitting)
|
||||
- Monolithic coupling (solve simultaneously)
|
||||
- Staggered schemes (iterative coupling)
|
||||
# Multiphysics Example
|
||||
|
||||
# GPU Compatibility
|
||||
```julia
|
||||
# Share one mesh between structural and thermal physics
|
||||
mesh = Mesh{Hex8}(nodes, connectivity)
|
||||
|
||||
All physics implementations must be GPU-friendly:
|
||||
- ✅ Type-stable (no Dict lookups)
|
||||
- ✅ Zero allocation in hot paths
|
||||
- ✅ Kernel-compatible functions
|
||||
- ✅ Minimal host-device transfers
|
||||
physics_structural = Physics(
|
||||
name = "structure",
|
||||
mesh = mesh, # Reference, not copy!
|
||||
field = Displacement{3}(),
|
||||
formulation = ContinuumFormulation{FullThreeD}(),
|
||||
material = steel
|
||||
)
|
||||
|
||||
Iterations run entirely on GPU. Only after convergence do we transfer results
|
||||
to host for postprocessing.
|
||||
physics_thermal = Physics(
|
||||
name = "thermal",
|
||||
mesh = mesh, # Same mesh reference!
|
||||
field = Temperature(),
|
||||
formulation = ContinuumFormulation{FullThreeD}(),
|
||||
material = thermal_steel
|
||||
)
|
||||
```
|
||||
|
||||
# See Also
|
||||
|
||||
- `docs/user/system_architecture.md` - Design rationale
|
||||
- `docs/book/elasticity_refactoring_plan.md` - Implementation details
|
||||
- [`assemble!`](@ref) - System assembly
|
||||
- [`solve!`](@ref) - Solve physics problem
|
||||
- [`add_dirichlet!`](@ref) - Essential BCs
|
||||
- [`add_neumann!`](@ref) - Natural BCs
|
||||
- Concrete type: `Physics` in `src/physics/types.jl`
|
||||
"""
|
||||
abstract type AbstractPhysics end
|
||||
|
||||
"""
|
||||
get_unknown_field_name(physics::AbstractPhysics) -> String
|
||||
|
||||
Return the name of the primary unknown field for this physics.
|
||||
|
||||
# Examples
|
||||
|
||||
```julia
|
||||
get_unknown_field_name(ElasticityPhysics()) # "displacement"
|
||||
get_unknown_field_name(HeatPhysics()) # "temperature"
|
||||
get_unknown_field_name(FluidPhysics()) # "velocity"
|
||||
```
|
||||
"""
|
||||
function get_unknown_field_name(physics::AbstractPhysics)
|
||||
error("get_unknown_field_name not implemented for $(typeof(physics))")
|
||||
end
|
||||
|
||||
"""
|
||||
get_formulation_type(physics::AbstractPhysics) -> Symbol
|
||||
|
||||
Return the formulation type: `:incremental`, `:total`, or `:rate`.
|
||||
|
||||
- `:incremental` - Solve for Δu, update u ← u + Δu (elasticity)
|
||||
- `:total` - Solve for u directly (Poisson equation)
|
||||
- `:rate` - Solve for ∂u/∂t (transient heat, fluid dynamics)
|
||||
"""
|
||||
function get_formulation_type(physics::AbstractPhysics)
|
||||
error("get_formulation_type not implemented for $(typeof(physics))")
|
||||
end
|
||||
|
||||
"""
|
||||
get_unknown_field_dimension(physics::AbstractPhysics) -> Int
|
||||
|
||||
Return the dimension of the unknown field (DOFs per node).
|
||||
|
||||
# Examples
|
||||
|
||||
```julia
|
||||
get_unknown_field_dimension(ElasticityPhysics()) # 3 (3D displacement)
|
||||
get_unknown_field_dimension(HeatPhysics()) # 1 (scalar temperature)
|
||||
get_unknown_field_dimension(FluidPhysics()) # 4 (velocity + pressure)
|
||||
```
|
||||
"""
|
||||
function get_unknown_field_dimension(physics::AbstractPhysics)
|
||||
error("get_unknown_field_dimension not implemented for $(typeof(physics))")
|
||||
end
|
||||
|
||||
"""
|
||||
assemble!(assembly::Assembly, physics::AbstractPhysics, elements, time)
|
||||
|
||||
Assemble global system for given physics.
|
||||
|
||||
This is the main dispatch point for physics-specific assembly. Each physics
|
||||
type implements its own method.
|
||||
|
||||
# GPU-Friendly Design
|
||||
|
||||
The assembly loop must be GPU-compatible:
|
||||
|
||||
```julia
|
||||
# CPU version (reference)
|
||||
for element in elements
|
||||
Kₑ, fₑ = assemble_element(physics, element, time)
|
||||
add_to_global!(assembly, Kₑ, fₑ, element.gdofs)
|
||||
end
|
||||
|
||||
# GPU version (future)
|
||||
@cuda threads=256 assemble_kernel!(assembly, physics, elements, time)
|
||||
```
|
||||
|
||||
Key principles:
|
||||
- No heap allocations inside element loop
|
||||
- All buffers pre-allocated
|
||||
- Type-stable throughout
|
||||
- Deterministic execution order (for GPU atomics)
|
||||
"""
|
||||
function assemble!(assembly, physics::AbstractPhysics, elements, time)
|
||||
error("assemble! not implemented for $(typeof(physics))")
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user