Files
JuliaFEM.jl/src/physics/api.jl
T
Jukka Aho 8479b06cac refactor(physics): Define clean Physics API interface
- Remove duplicate AbstractPhysics definition (now in abstract.jl)
- Define interface functions: assemble!, solve!, add_dirichlet!, add_neumann!
- Document dispatch strategies for formulation × field combinations
- Add implementation method documentation (elimination, penalty, Lagrange)
- Include comprehensive usage examples for each interface function
- Specify must-include-after dependencies in header comments
- 246 lines of interface documentation
2025-11-18 16:08:35 +02:00

252 lines
6.4 KiB
Julia
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
"""
Physics API definitions.
This file defines the interface functions for physics problems.
Abstract type `AbstractPhysics` is defined in `src/physics/abstract.jl`.
Concrete implementations are in `src/physics/types.jl` and `src/physics/boundary_conditions.jl`.
Must be included after core api.jl, fields/api.jl, materials/api.jl, and formulations.
"""
# ============================================================================
# PHYSICS INTERFACE FUNCTIONS
# ============================================================================
"""
assemble!(physics::AbstractPhysics) -> (K, f)
Assemble global system matrices for a physics problem.
This is the core FEM operation that builds:
- `K`: Global stiffness/tangent matrix (sparse or matrix-free operator)
- `f`: Global force/residual vector
# Arguments
- `physics`: Physics problem with mesh, material, field, formulation
# Returns
- `K`: Global stiffness matrix (sparse or operator)
- `f`: Global force vector
# Implementation Strategy
**Dispatch on formulation × field combination:**
```julia
# 3D solid mechanics with displacement field
function assemble!(physics::Physics{ContinuumFormulation{FullThreeD}, Displacement{3}, M, Mat})
# Standard displacement-based elasticity
end
# Beam with displacement + rotation field
function assemble!(physics::Physics{BeamFormulation{Timoshenko}, DisplacementRotation{3}, M, Mat})
# Beam-specific assembly (6 DOFs per node)
end
# Generic fallback
function assemble!(physics::Physics{Fm, F, M, Mat}) where {Fm, F, M, Mat}
error("No assembly method for formulation \$Fm with field \$F")
end
```
# Examples
```julia
physics = Physics(
name = "cantilever",
mesh = mesh,
element_set = :all,
field = Displacement{3}(),
formulation = ContinuumFormulation{FullThreeD}(),
material = steel
)
# Assemble system
K, f = assemble!(physics)
# K is sparse matrix (for small problems) or matrix-free operator (for large)
# f is residual vector (nonlinear) or force vector (linear)
```
# See Also
- [`solve!`](@ref) - Solve after assembly
- Matrix-free assembly for large problems
- Nodal assembly for GPU acceleration
"""
function assemble! end
"""
solve!(physics::AbstractPhysics) -> solution
Solve a physics problem.
Automatically selects appropriate solver based on problem type:
- Linear problems: Direct solver or CG/GMRES
- Nonlinear problems: Newton-Raphson with line search
- Dynamic problems: Time integration (Newmark, HHT-α)
# Arguments
- `physics`: Physics problem (must have BCs applied)
# Returns
- `solution`: Solution vector or solution object with field values
# Solver Selection Logic
```julia
function solve!(physics::Physics)
if is_linear(physics.material)
# Linear solver
K, f = assemble!(physics)
u = K \\ f
else
# Nonlinear solver (Newton-Raphson)
u = newton_solve(physics)
end
return u
end
```
# Examples
```julia
# Apply boundary conditions first
add_dirichlet!(physics, fixed_nodes, [1,2,3], 0.0)
add_neumann!(physics, loaded_surface, traction)
# Solve
solution = solve!(physics)
# Access results
u = solution.displacement # or solution.temperature, etc.
```
# See Also
- [`assemble!`](@ref) - System assembly
- [`add_dirichlet!`](@ref) - Essential BCs
- [`add_neumann!`](@ref) - Natural BCs
"""
function solve! end
"""
add_dirichlet!(physics::AbstractPhysics, node_ids, components, values)
Apply essential (Dirichlet) boundary conditions.
Essential BCs prescribe field values at specific nodes:
- Fixed displacements (u = 0)
- Prescribed temperatures (T = 100°C)
- Prescribed rotations (θ = 0)
# Arguments
- `physics`: Physics problem
- `node_ids::Vector{Int}`: Node IDs where BC applies
- `components::Vector{Int}`: Which DOF components (e.g., [1,2,3] for all, [3] for z-direction)
- `values::Float64` or `Vector{Float64}`: Prescribed values
# Implementation Methods
**Elimination method** (modify K, f):
```julia
# Remove rows/columns for constrained DOFs
K_reduced, f_reduced = eliminate_constraints(K, f, bc_nodes, bc_values)
u_free = K_reduced \\ f_reduced
u_full = insert_constrained_values(u_free, bc_nodes, bc_values)
```
**Penalty method** (add large stiffness):
```julia
# Add penalty terms to K
for (node, component, value) in constraints
dof = get_dof(node, component)
K[dof, dof] += penalty # Large number (e.g., 1e10 * max(K))
f[dof] = penalty * value
end
```
**Lagrange multipliers** (augmented system):
```julia
# Solve [K G^T] [u] [f]
# [G 0 ] [λ] = [g]
```
# Examples
```julia
# Fix all DOFs at nodes 1, 2, 3
add_dirichlet!(physics, [1,2,3], [1,2,3], 0.0)
# Fix only z-displacement at node 10
add_dirichlet!(physics, [10], [3], 0.0)
# Prescribe x-displacement at node 20
add_dirichlet!(physics, [20], [1], 0.1)
# Fix temperature at boundary nodes
add_dirichlet!(physics_thermal, boundary_nodes, [1], 273.15)
```
# See Also
- [`add_neumann!`](@ref) - Natural boundary conditions
- [`solve!`](@ref) - Solve with BCs applied
"""
function add_dirichlet! end
"""
add_neumann!(physics::AbstractPhysics, surface_ids, values)
Apply natural (Neumann) boundary conditions.
Natural BCs apply forces, tractions, or fluxes:
- Surface tractions (solid mechanics)
- Heat flux (thermal)
- Pressure loads
- Body forces
# Arguments
- `physics`: Physics problem
- `surface_ids::Vector{Int}`: Surface/edge element IDs where BC applies
- `values`: Traction vectors (Vec{3}), scalars (pressure), or functions
# Implementation
Natural BCs contribute to force vector:
```julia
# For each surface element
for surf_elem in surface_elements
# Integrate traction over surface
f_surf = ∫(N^T * t * dS) # N = shape functions, t = traction
# Add to global force vector
f[surf_dofs] += f_surf
end
```
# Examples
```julia
# Apply traction to surface
traction = Vec{3}(0.0, -1000.0, 0.0) # 1000 N/m² downward
add_neumann!(physics, surface_elements, traction)
# Apply pressure (always normal to surface)
pressure = -100e3 # 100 kPa (negative = compression)
add_neumann!(physics, surface_elements, pressure)
# Heat flux (thermal problem)
heat_flux = 5000.0 # W/m²
add_neumann!(physics_thermal, surface_elements, heat_flux)
```
# See Also
- [`add_dirichlet!`](@ref) - Essential boundary conditions
- [`solve!`](@ref) - Solve with BCs applied
"""
function add_neumann! end