- Add `ndofs(::AbstractBasis)` / `ndofs(::Type{<:AbstractBasis})` with docstring and examples
- Default implementation: `ndofs == nnodes` for standard Lagrange bases
- Export `ndofs` alongside `Lagrange` and `nnodes`
This provides a stable API for callers to preallocate element-local buffers and supports plate elements that have multiple DOFs per node.
- Insert blank lines around headings and list items for better rendering
- Clarify pattern notes: zero-duplication, domain ownership, minimal core
- Improve example spacing so code fences render correctly in generated docs
No code changes; only formatting and readability improvements to the API documentation.
- Replace `include("formulations/api.jl")` with `include("domains/continuum/formulations.jl")`
- Move domain API includes under `domains/*` (beams, shells, trusses, plates)
- Add plate formulations and plate basis includes (DKT, plate elements)
- Rework quadrature includes to load tables from `quadrature/*` and export `get_quadrature_points`
- Consolidate legacy modules under `legacy/` and adjust includes accordingly
- Consolidate mesh readers under `readers/*` and move GMSH reader into `io/gmsh_reader.jl`
- Replace older assembly includes with `assembly/framework.jl` and `assembly/*` structures
- Export new API symbols and add compatibility re-exports where needed
This change reorganizes the package file structure and wiring to make the new modular architecture (domains, quadrature tables, plate elements, and legacy shims) loadable from the top-level `src/JuliaFEM.jl`.
- Added: `LinearOperators` to the `deps` list for the `JuliaFEM` project entry
Reason: The project requires linear-operator abstractions for matrix-free and operator-based solvers/benchmarks. Pinning here documents the dependency and helps maintain reproducible builds.
- Added: `.env` to avoid committing local environment variables
- Added: `.vscode/` to ignore editor workspace settings and launch configs
- Added: `trash` to ignore developer temporary files
These entries reduce noisy diffs and help prevent accidental leakage of local secrets or editor-specific files.
Create src/api.jl as pure documentation (196 lines, NO type definitions):
- Documents the complete modular API architecture
- Lists all 9 domain api.jl files in dependency order
- Explains design philosophy: zero duplication, domain ownership, minimal core
- Shows type hierarchy across all domains
- Demonstrates assembly dispatch pattern (formulation × field)
- Lists 7 advantages of modular architecture
This file is the architectural guide - all actual type definitions live in
domain-specific api.jl files:
- formulations/api.jl (AbstractFormulation, continuum theories)
- fields/api.jl (Displacement, Temperature, DisplacementRotation)
- materials/api.jl (AbstractMaterial, elastic/plastic)
- mesh/api.jl (AbstractMesh, node-to-elements mapping)
- beams/shells/trusses/api.jl (structural formulations)
- topology/api.jl (AbstractTopology{N}, 17 element types)
Completes systematic modular API refactoring - every domain owns its
abstractions, core is documentation-only.
Refactor src/topology/topology.jl from 173 to 12 lines:
- Remove all AbstractTopology{N} interface definitions (161 lines removed)
- Remove nnodes(), dim(), reference_coordinates(), edges(), faces() stubs
- Interface now defined in src/topology/api.jl (included first)
- Keep file as placeholder for future helper functions
- Add note referencing topology/api.jl for interface
This completes separation of interface (api.jl) from implementations.
Topology/topology.jl previously mixed interface and helpers - now
clean separation following systematic modular architecture pattern.
Part of systematic modular API refactoring.
Create src/physics/api.jl defining physics problem abstractions:
- AbstractPhysics base type for all physics problems
- assemble!() interface for building global system (K, f)
- solve!() interface for solving physics problems
- add_dirichlet!() for essential BCs (prescribed displacements/temperatures)
- add_neumann!() for natural BCs (surface tractions/heat flux)
Physics couples four components: Mesh (where), Material (constitutive law),
Field (what we solve), Formulation (how we discretize). Physics references
Mesh (does not own it) enabling multiphysics: multiple Physics can share
one Mesh for memory efficiency and coupling.
Dispatch specialization via formulation × field type parameters:
assemble!(::Physics{ContinuumFormulation{FullThreeD}, Displacement{3}, M, Mat})
assemble!(::Physics{BeamFormulation{Timoshenko}, DisplacementRotation{3}, M, Mat})
Comprehensive documentation with multiphysics examples, dispatch patterns,
and interface contracts. Assembly implementations in src/assembly/.
Part of systematic modular API architecture.
Create src/formulations/api.jl defining discretization strategy abstractions:
- AbstractFormulation base type for all formulation strategies
- AbstractContinuumTheory for continuum mechanics theory variants
- ContinuumFormulation{Theory} parameterized formulation struct
- Four concrete theories:
* FullThreeD - Full 3D (6 stress components, no simplifications)
* PlaneStress - Thin plates (σ_zz=0, thickness << length)
* PlaneStrain - Thick sections (ε_zz=0, no z-variation)
* Axisymmetric - Rotationally symmetric (σ_rr, σ_θθ, σ_zz, σ_rz)
Formulation defines HOW to discretize (math strategy), while Field defines
WHAT to solve (physical quantity). Formulation × Field determines assembly
dispatch: ContinuumFormulation{FullThreeD} + Displacement{3} dispatches to
3D solid mechanics assembly in src/assembly/continuum_3d.jl.
Comprehensive documentation with theory selection guidelines and examples.
Part of systematic modular API architecture.
Create src/mesh/api.jl defining mesh-specific abstractions:
- AbstractMesh base type for all mesh structures
- nnodes_total(), nelements() for mesh sizing
- get_node(node_id) returns Vec{Dim} coordinates
- connectivity_matrix() returns element-to-nodes mapping
- get_elements_for_node(node_id) returns node-to-elements mapping (critical for nodal assembly)
- get_element_set(name), get_node_set(name) for named sets (BCs, materials, postprocessing)
- AbstractRefineStrategy, refine() for adaptive mesh refinement
Meshes own topology (coordinates, connectivity). Multiple Physics can
share one Mesh for multiphysics coupling. Node-to-elements mapping
enables nodal assembly pattern (see docs/book/multigpu_nodal_assembly.md).
Part of systematic modular API architecture.
Create src/fields/api.jl defining field-specific abstractions:
- AbstractField base type for all field variables
- Displacement{Dim} for solid mechanics (Dim DOFs per node: ux, uy, uz)
- Temperature for heat transfer (1 DOF per node: T)
- DisplacementRotation{Dim} for beams/shells (2*Dim DOFs: displacement + rotation)
- dofs_per_node() interface for DOF counting
Field type determines solution vector structure, boundary condition
interpretation, and assembly dispatch. Examples:
- Displacement{3} with ContinuumFormulation{FullThreeD} → 3D elasticity
- Temperature with ContinuumFormulation{FullThreeD} → heat transfer
- DisplacementRotation{3} with BeamFormulation → 6 DOFs (3 trans + 3 rot)
Part of systematic modular API architecture.
Create src/materials/api.jl defining material-specific abstractions:
- AbstractMaterial base type for all material models
- AbstractElasticMaterial for stateless materials (no history)
- AbstractPlasticMaterial for stateful materials (history-dependent)
- compute_stress() interface (strain → stress + tangent + updated state)
- elasticity_tensor() for elastic constitutive relations
Material models use Tensors.jl (no Voigt notation). Elastic materials
are stateless (LinearElastic, NeoHookean). Plastic materials have internal
state (plastic strain εᵖ, backstress α, hardening κ, damage).
Interface returns (σ, 𝔻, state_new) where 𝔻 is the material tangent ∂σ/∂ε.
Part of systematic modular API architecture.
Create src/shells/api.jl defining shell-specific abstractions:
- AbstractShellTheory base type for shell theories
- ReissnerMindlin concrete theory (thick shells, includes shear, h/L > 1/20, 5 DOFs)
- KirchhoffLove concrete theory (thin shells, no shear, h/L < 1/20, 3 DOFs)
- ShellFormulation{Theory} parameterized formulation struct
Reissner-Mindlin has 5 DOFs per node (ux, uy, uz, θx, θy) with explicit
rotations. Kirchhoff-Love has 3 DOFs (ux, uy, uz) with rotations computed
from displacement gradients (normals remain perpendicular).
Part of systematic modular API architecture.
Create src/beams/api.jl defining beam-specific abstractions:
- AbstractBeamTheory base type for beam theories
- EulerBernoulli concrete theory (classical, no shear deformation, L/h > 10)
- Timoshenko concrete theory (includes shear, thick beams)
- BeamFormulation{Theory} parameterized formulation struct
Beam elements have 6 DOFs per node (ux, uy, uz, θx, θy, θz) and work
with DisplacementRotation{3} field. Euler-Bernoulli assumes plane sections
remain perpendicular to neutral axis, while Timoshenko allows shear deformation.
Part of systematic modular API architecture.
Create src/trusses/api.jl defining truss-specific abstractions:
- AbstractTrussTheory base type for truss theories
- SimpleTruss concrete theory (axial force only, pin-jointed)
- TrussFormulation{Theory} parameterized formulation struct
SimpleTruss supports 2D/3D displacement fields with 2 or 3 DOFs per node.
Documented for future extension with CableTruss and PretensionedTruss.
Part of systematic modular API architecture where each structural
element type owns its formulation abstractions.
Major reorganization of main module file to support new architecture.
Changes - Include Order:
- Include api.jl FIRST (all abstract types and interfaces)
- Include physics.jl after api.jl (concrete Physics implementation)
- Material models after physics (LinearElastic, NeoHookean)
- New Mesh{T} infrastructure (mesh.jl, refine.jl, structured.jl)
Changes - Exports:
- Export core API types: AbstractMesh, AbstractTopology, AbstractMaterial, etc.
- Export physics types: AbstractField, AbstractFormulation, Physics, Constraint
- Export boundary conditions: DirichletBC, NeumannBC
- Export mesh operations: Mesh, topology_type, get_elements_for_node, etc.
- Export refinement: AbstractRefineStrategy, LongestEdgeBisection, refine
- Export structured mesh: create_structured_box_mesh, create_cantilever_mesh, etc.
Changes - Removals:
- Remove temporary jacobian() function (now in elements/elements.jl)
- Comment out backend files (need API updates)
- Comment out old Dict-based Mesh (conflicts with new Mesh{T})
Changes - Additions:
- Include assembly/continuum_3d.jl and continuum_3d_v2.jl
- Export compute_element_stiffness for testing
This establishes the foundation for the new type-parametric architecture.
Migrate element basis evaluation functions to use new topology-aware API.
Changes:
- Add _create_topology_instance() helper to construct topology from Lagrange{T,P}
- Update get_basis() to call get_basis_functions(topology, basis, xi)
- Update get_dbasis() to call get_basis_derivatives(topology, basis, xi)
- Add jacobian() function with embedding support (1D element in 2D/3D space)
- Constraint: B <: Lagrange added to method signatures
Migration from OLD API:
- eval_basis!(B, T, xi) → get_basis_functions(topology, basis, xi)
- eval_dbasis!(B, xi) → get_basis_derivatives(topology, basis, xi)
Maintains compatibility: still returns matrices/vectors for old code interface.
Fix method ambiguity by explicitly qualifying Base.isempty calls.
Changes:
- function isempty(assembly::Assembly) → function Base.isempty(assembly::Assembly)
- All internal isempty() calls qualified with Base.isempty()
- Avoids method ambiguity warnings
This is a standard Julia pattern for extending Base methods on custom types.
Add helper to get recommended integration schemes for topology types.
Changes:
- New function: default_integration(::Type{<:AbstractTopology{N}})
- Returns appropriate Gauss{order}() for common topologies
- Rules: linear elements use minimal exact integration, quadratic use higher order
- Implementations for: Tet4/10, Hex8/20/27, Tri3/6, Quad4/8/9
Examples:
- default_integration(Hexahedron{8}) → Gauss{2}() (2×2×2 = 8 points)
- default_integration(Tetrahedron{4}) → Gauss{1}() (1 point)
- default_integration(Hexahedron{27}) → Gauss{3}() (3×3×3 = 27 points)
Simplifies user code: no need to memorize integration order for each element.
Update Wedge to use node count type parameter per ADR-002.
Changes:
- struct Wedge → struct Wedge{N} <: AbstractTopology{N}
- Aliases: Wedge6 = Wedge{6}, Wedge15 = Wedge{15}
- Simplified implementation following same pattern
- Remove old design documentation
Implements ADR-002 (November 13, 2025): node count from mesh, not basis.
Old files removed: wedge6.jl, wedge15.jl
New file: Single wedges.jl handles all variants via {N}
Update Pyramid to use node count type parameter per ADR-002.
Changes:
- struct Pyramid → struct Pyramid{N} <: AbstractTopology{N}
- Alias: Pyr5 = Pyramid{5}
- Simplified implementation following same pattern
- Remove old design documentation
Implements ADR-002 (November 13, 2025): node count from mesh, not basis.
Old file removed: pyr5.jl
New file: Single pyramids.jl handles all variants via {N}
Update Tetrahedron to use node count type parameter per ADR-002.
Changes:
- struct Tetrahedron → struct Tetrahedron{N} <: AbstractTopology{N}
- Aliases: Tet4 = Tetrahedron{4}, Tet10 = Tetrahedron{10}
- Simplified implementation following same pattern
- Remove old design documentation
Implements ADR-002 (November 13, 2025): node count from mesh, not basis.
Old files removed: tet4.jl, tet10.jl
New file: Single tetrahedra.jl handles all variants via {N}