From 6a3c6754cbacb61ed661d53e2a8c7b03c1a24d4b Mon Sep 17 00:00:00 2001 From: Jukka Aho Date: Sat, 9 May 2026 18:15:34 +0300 Subject: [PATCH] docs(physics): trim api.jl to assembler-era stubs Replace the long `Physics{...}` narrative with short placeholders that explain how `assemble!`/`solve!`/BC hooks are extended by assemblers or Legacy only. - Document the kernel + assembler workflow as the active surface. - Point Dirichlet/Neumann reservations at matrix-free BC and load value types. - Keep generic function declarations for Legacy method attachment. --- src/physics/api.jl | 256 ++++++--------------------------------------- 1 file changed, 32 insertions(+), 224 deletions(-) diff --git a/src/physics/api.jl b/src/physics/api.jl index 883f896..6c08572 100644 --- a/src/physics/api.jl +++ b/src/physics/api.jl @@ -2,250 +2,58 @@ # License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md """ -Physics API definitions. +Physics-level interface stubs. -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`. +Older JuliaFEM versions had a `Physics{Formulation, Field, Mesh, Material}` struct +that owned `assemble!` / `solve!` / `add_dirichlet!` / `add_neumann!` as the +top-level user surface. The current architectural reset replaced that high-level surface with +the `AbstractKernel` + assembler + matrix-free hooks design that lives under +`src/assemblers/`. The four function names below are kept here only as +top-level placeholders so that: -Must be included after core api.jl, fields/api.jl, materials/api.jl, and formulations. + - the `JuliaFEM.Legacy` submodule (when loaded via `JULIAFEM_ENABLE_LEGACY=1`) + can hang its method definitions on the same generic functions; + - the assemblers (`src/assemblers/element_based/element_based_coo.jl`, + `src/assemblers/dof_based/dof_based_coo.jl`) can extend `assemble!` with + methods that match the current cache-based workflow. + +There is no `Physics(...)` constructor in the active build. The current +end-to-end flow is documented in `AGENTS.md` and exercised by +`test/runtests.jl`. """ -# ============================================================================ -# PHYSICS INTERFACE FUNCTIONS -# ============================================================================ - """ - assemble!(physics::AbstractPhysics) -> (K, f) + assemble!(...) -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 +Generic assembly entry point. Concrete methods are added by the element-based +and DOF-based assemblers under `src/assemblers/`. """ function assemble! end """ - solve!(physics::AbstractPhysics) -> solution + solve!(...) -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 +Reserved name. The default 0.x build does not provide a top-level `solve!` method; +solvers are composed externally via `MatrixFreeOperator` + Krylov methods or +via direct factorisation of the assembled matrix. Methods on this name only +exist inside `JuliaFEM.Legacy`. """ function solve! end """ - add_dirichlet!(physics::AbstractPhysics, node_ids, components, values) + add_dirichlet!(...) -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 +Reserved name. In the default 0.x build, Dirichlet conditions are expressed as +`PenaltyDirichlet` / `EliminatedDirichlet` value objects passed to the +matrix-free operator. Methods on this name only exist inside `JuliaFEM.Legacy`. """ function add_dirichlet! end """ - add_neumann!(physics::AbstractPhysics, surface_ids, values) + add_neumann!(...) -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 +Reserved name. In the default 0.x build, Neumann loads are expressed as +`NodalForce` / `UniformBodyForce` / `SurfaceLoad` value objects applied via +`apply_load!`. Methods on this name only exist inside `JuliaFEM.Legacy`. """ function add_neumann! end