refactor(src): update JuliaFEM.jl

src/JuliaFEM.jl | 821 +++++++++++++++++---------------------------------------  1 file changed, 248 insertions(+), 573 deletions(-)
This commit is contained in:
Jukka Aho
2026-05-09 16:30:28 +03:00
parent 6f50c73660
commit fa0b6b51ba
+238 -563
View File
@@ -1,652 +1,327 @@
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md
# SPDX-FileCopyrightText: 2015-2026 Jukka Aho
# SPDX-License-Identifier: MIT
"""
JuliaFEM.jl - Modern Finite Element Method Library for Julia
JuliaFEM
JuliaFEM is an open-source FEM library focused on **contact mechanics**, with a modern
architecture designed for GPU acceleration and educational transparency.
Open-source finite element framework written in Julia.
**Project Status:** Revived November 2025 (original: 2015-2019) with complete architectural overhaul.
The package is **0.x**; the repository is in the middle of a deliberate
architectural reset toward a **stable 1.0** with a type-stable, zero-allocation,
GPU-friendly assembly pipeline.
The authoritative current-architecture summary lives in `AGENTS.md` in
the repository root; the `docs/src/` tree contains a current-API quick
start and the auto-generated API reference.
# Key Features
- **Contact Mechanics Focus**: Primary differentiation from general-purpose FEM libraries
- **Nodal Assembly**: GPU-friendly architecture without atomic operations
- **Tensors.jl Integration**: Natural tensor notation for stress, strain, and stiffness
- **Type-Stable Fields**: NamedTuple-based fields for 100× performance vs Dict
- **Matrix-Free Solvers**: Krylov methods (GMRES) for large-scale problems
- **Backend Abstraction**: Identical user code runs on CPU or GPU
# Modern API (November 2025)
## Physics-Based Interface
```julia
using JuliaFEM
# Create physics problem
physics = Physics(Elasticity, "cantilever beam", 3)
# Add elements with type-stable fields
add_elements!(physics, body_elements)
# Apply boundary conditions
add_dirichlet!(physics, fixed_nodes, [1,2,3], 0.0) # Fix all DOFs
add_neumann!(physics, surface_elements, traction) # Surface load
# Solve (automatically selects backend)
solution = solve!(physics, backend=GPU()) # or backend=CPU()
```
## Element Creation (Immutable, Type-Stable)
```julia
# Modern approach: NamedTuple fields (type-stable!)
element = Element(Lagrange{Triangle,1}, (1,2,3),
fields=(E=210e3, ν=0.3, ρ=7850.0))
# Update immutably (returns new element)
element2 = update(element, :displacement => u_values)
# Access fields (compile-time type known!)
E = element.fields.E # Float64, no Dict lookup!
```
# Architecture Highlights
**Nodal Assembly** (GPU-friendly):
- Loop over nodes (not elements) → no atomic operations on GPU
- 3×3 stiffness blocks using Tensor{2,3} from Tensors.jl
- Matrix-free K*v without forming global matrix
**Separation of Concerns**:
- Topology: Reference element geometry (Triangle, Quadrilateral, Tetrahedron, etc.)
- Integration: Gauss quadrature rules (zero-allocation tuple-based)
- Basis: Shape functions (Lagrange, Serendipity)
- Materials: Stress computation (LinearElastic, NeoHookean, PerfectPlasticity)
**Contact Mechanics**:
- Mortar methods for interface coupling
- 2D and 3D contact with friction
- GPU-accelerated contact detection
# Documentation
Comprehensive guides in `docs/book/`:
- `element_architecture.md` - Element composition philosophy
- `nodal_assembly_concept.md` - GPU-friendly assembly
- `multigpu_nodal_assembly.md` - Multi-GPU architecture (in progress)
# Problem API
The `Problem` type provides element-based assembly:
```julia
problem = Problem(Elasticity, "body", 3)
add_elements!(problem, elements) # Still works
```
**Migration:** Gradually transitioning to `Physics` API for new code.
# More Information
Website: www.juliafem.org
GitHub: github.com/JuliaFEM/JuliaFEM.jl
Older functionality (`Problem` / `Assembly` / `Solver` / `Analysis`
hierarchy, Dict-based fields, the Abaqus mesh reader stack, ...) is
preserved in the optional `JuliaFEM.Legacy` submodule. Set the
environment variable `JULIAFEM_ENABLE_LEGACY=1` before `using JuliaFEM`
to load it.
Because the legacy gate is evaluated at module-load time, the precompile
cache encodes whichever mode was active when the cache was built.
Switching between modes requires re-precompilation: either run
`Pkg.precompile()` after changing the variable, or delete the cache
under `~/.julia/compiled/v\$VERSION/JuliaFEM/`.
"""
module JuliaFEM
# Import Base functions for extension
import Base: getindex, setindex!, convert, length, size, isapprox,
==, haskey, copy, read, append!
using SparseArrays, LinearAlgebra
using Logging # For mesh readers
using Tensors # For basis functions (Vec type)
using StaticArrays: SVector # Static coordinate storage for topology nodes
using Logging
using Tensors
using StaticArrays: SVector
# No-op timing macro
# No-op timing macro retained for compatibility with annotated hot paths.
macro timeit(args...)
return esc(args[end])
return esc(args[end])
end
# ============================================================================
# CORE API - Include FIRST (all abstract types and interfaces)
# Public API surface
#
# All `export` statements live in a single, grouped, deduplicated file. They
# are reservations of names; the symbols themselves are defined by the
# `include`s below.
# ============================================================================
include("exports.jl")
# This is the Julia equivalent of C/C++ header files.
# All abstract types and lightweight structs are defined here.
# This MUST be included before any concrete implementations.
include("api.jl") # Documentation-only (no type definitions)
# Continuum domain abstract types
# ============================================================================
# Level 1 - Field, formulation, material, mesh, physics, topology API tags
# ============================================================================
include("domains/continuum/abstract.jl")
# Continuum domain concrete types
include("domains/continuum/types.jl")
# Formulation domain API (discretization strategies)
include("domains/continuum/formulations.jl")
export AbstractFormulation, ContinuumFormulation
export AbstractContinuumTheory, FullThreeD, PlaneStress, PlaneStrain, Axisymmetric
# Field domain API (field variable types and DOF counting)
include("fields/api.jl")
export AbstractField, Displacement, Temperature, DisplacementRotation
export dofs_per_node, get_dof_mapping!, get_field
# Local field evaluation (field quantities at a point)
include("fields/local_field.jl")
export LocalField
# Material domain API
include("materials/api.jl")
export AbstractMaterial, AbstractElasticMaterial, AbstractPlasticMaterial
export AbstractMaterialState, EmptyState
export compute_stress, elasticity_tensor
# Material behavior traits (for generic integration)
export MaterialBehavior, StatelessConstantTangent, StatelessStrainDependent, StatefulStrainDependent
export material_behavior, needs_deformation, needs_state
# Mesh domain API
include("mesh/api.jl")
export AbstractMesh, AbstractRefineStrategy
export nnodes_total, nelements, get_node, connectivity_matrix
export get_elements_for_node, get_element_set, get_node_set
export refine
# Subdomain API files (define their own abstractions and formulations)
include("domains/beams/api.jl") # AbstractBeamTheory, BeamFormulation{Theory}, EulerBernoulli, Timoshenko
export AbstractBeamTheory, BeamFormulation, EulerBernoulli, Timoshenko
include("domains/shells/api.jl") # AbstractShellTheory, ShellFormulation{Theory}, ReissnerMindlin, KirchhoffLove
export AbstractShellTheory, ShellFormulation, ReissnerMindlin, KirchhoffLove
include("domains/trusses/api.jl") # AbstractTrussTheory, TrussFormulation{Theory}, SimpleTruss
export AbstractTrussTheory, TrussFormulation, SimpleTruss
# Plate formulations
include("domains/plates/api.jl")
export AbstractPlateFormulation, DKTFormulation, PlateDisplacement
export constitutive_matrix_plate, get_thickness
# Note: domains/plates/dkt.jl is included later after Mesh is defined (line ~430)
# Physics domain API (abstract type, interface functions, and concrete implementations)
include("physics/abstract.jl") # AbstractPhysics abstract type
include("physics/api.jl") # Interface functions (assemble!, solve!, etc.)
include("physics/types.jl") # Physics category types (Elasticity, Thermal, etc.)
# include("physics/boundary_conditions.jl") # BC method implementations (for old Physics struct - not needed)
export AbstractPhysics, assemble!, solve!, add_dirichlet!, add_neumann!
export Elasticity, Thermal, required_field_type
# Physics utilities (strain extraction from displacement gradients)
include("physics/abstract.jl")
include("physics/api.jl")
include("physics/types.jl")
include("physics/strain.jl")
export extract_strain, extract_strain_rate
export AbstractTopology
# import FEMSparse # Consolidated into src/sparse/
# import FEMQuad # Consolidated into src/quadrature.jl
# Note: Consolidating FEMBase and FEMBasis into JuliaFEM
# Previously: @reexport using FEMBase
# Now: Include files directly below
# ============================================================================
# TOPOLOGY: Reference element geometries (NEW - separation of concerns)
# Level 2 - Topology shape types
# ============================================================================
# Topology domain API (abstract type and interface)
include("topology/api.jl")
export AbstractTopology, nnodes, dim, reference_coordinates, edges, faces
# Export topological entity types
export TopologicalEntity, Vertex, Edge, Face, Cell
export entities, nentities, vertices, cells
export nvertices, nedges, nfaces
# Consolidated topology files (one per shape family)
include("topology/segments.jl") # Segment (1D)
include("topology/triangles.jl") # Triangle (2D simplex)
include("topology/quadrilaterals.jl") # Quadrilateral (2D quad)
include("topology/tetrahedra.jl") # Tetrahedron (3D simplex)
include("topology/hexahedra.jl") # Hexahedron (3D hex)
include("topology/pyramids.jl") # Pyramid (3D)
include("topology/wedges.jl") # Wedge (3D prism)
# Export topology types (shape names, NOT node counts!)
export AbstractTopology, dim, reference_coordinates, edges, faces
export Segment # 1D line
export Triangle # 2D simplex
export Quadrilateral # 2D quad
export Tetrahedron # 3D simplex
export Hexahedron # 3D hex
export Pyramid # 3D pyramid
export Wedge # 3D prism
# Export aliases. These resolve to topology types, NOT separate types!
export Seg2, Seg3 # → Segment
export Tri3, Tri6, Tri7 # → Triangle
export Quad4, Quad8, Quad9 # → Quadrilateral
export Tet4, Tet10 # → Tetrahedron
export Hex8, Hex20, Hex27 # → Hexahedron
export Pyr5 # → Pyramid
export Wedge6, Wedge15 # → Wedge
# Note: Node count is NO LONGER in topology name! It comes from basis:
# Examples:
# Triangle + Lagrange{Triangle, 1} → 3 nodes (Tri3 → Triangle)
# Triangle + Lagrange{Triangle, 2} → 6 nodes (Tri6 → Triangle)
# Quadrilateral + Lagrange{Quadrilateral, 1} → 4 nodes (Quad4 → Quadrilateral)
# Quadrilateral + Serendipity{Quadrilateral, 2} → 8 nodes (Quad8 → Quadrilateral)
# Quadrilateral + Lagrange{Quadrilateral, 2} → 9 nodes (Quad9 → Quadrilateral)
include("topology/segments.jl")
include("topology/triangles.jl")
include("topology/quadrilaterals.jl")
include("topology/tetrahedra.jl")
include("topology/hexahedra.jl")
include("topology/pyramids.jl")
include("topology/wedges.jl")
# ============================================================================
# QUADRATURE: Integration schemes and quadrature rules
# Level 3 - Quadrature, geometry, basis functions
# ============================================================================
include("quadrature/api.jl") # Core API types and interfaces (NEW)
# integration.jl removed - OLD AbstractIntegration API no longer needed
include("quadrature/api.jl")
include("quadrature/quaddata.jl")
include("quadrature/gl_tetrahedra.jl")
include("quadrature/gl_triangles.jl")
include("quadrature/gl_wedges.jl")
include("quadrature/gl_pyramids.jl")
include("quadrature/gl_tensor_product.jl")
include("quadrature/gauss.jl")
# Gauss-Legendre quadrature point tables (must be loaded before gauss.jl)
include("quadrature/quaddata.jl") # Quadrature data constants
include("quadrature/gl_tetrahedra.jl") # Tetrahedron quadrature points
include("quadrature/gl_triangles.jl") # Triangle quadrature points
include("quadrature/gl_wedges.jl") # Wedge quadrature points
include("quadrature/gl_pyramids.jl") # Pyramid quadrature points
include("quadrature/gl_tensor_product.jl") # Segment, Quadrilateral, Hexahedron quadrature points
include("quadrature/gauss.jl") # Gauss-Legendre quadrature
# gauss_points.jl removed - OLD compile-time integration point API no longer needed
export IntegrationPoint, integration_points, npoints
export get_quadrature_points # Export quadrature point tables
# New quadrature API
export AbstractQuadratureRule, GaussLegendre, GaussLobatto, QuadraturePoint
export default_quadrature
# ============================================================================
# GEOMETRY: Jacobian computation and coordinate transformations
# ============================================================================
include("geometry/jacobian.jl")
export compute_jacobian, physical_derivatives
include("geometry/piola.jl")
include("geometry/strain.jl")
export compute_strain
# ============================================================================
# BASIS: Interpolation schemes (consolidated from FEMBasis.jl)
# ============================================================================
include("basis/api.jl")
include("basis/subs.jl") # Symbolic substitution (includes minimal simplify from SymDiff.jl)
include("basis/vandermonde.jl")
# Lagrange basis functions - auto-generated file contains all basis types
# Now generates methods for parametric Lagrange{T,P} type with BOTH old and new APIs
include("basis/basis_generator.jl")
include("basis/basis_generated.jl") # Auto-generated by: julia --project=. src/basis/basis_generator.jl
# Plate element basis functions (DKT, DST, etc.)
include("domains/plates/dkt_basis.jl") # AbstractPlateBasis, DKT
# Export basis types and functions
export AbstractBasis, Lagrange, Serendipity
export eval_basis!, eval_dbasis!
export ndofs
export get_basis_functions, get_basis_derivatives
export get_basis_function, get_basis_derivative
include("basis/nurbs.jl")
# OLD NURBS basis files - commented out during AbstractBasis refactoring
# These use AbstractBasis{dim} syntax which conflicts with new non-parametric AbstractBasis
# include("basis/nurbs_segment.jl") # NSeg <: AbstractBasis{1}
# include("basis/nurbs_surface.jl") # NSurf <: AbstractBasis{2}
# include("basis/nurbs_solid.jl") # NSolid <: AbstractBasis{3}
# TODO: Rewrite for new AbstractBasis (non-parametric)
# include("basis/math.jl") # Uses AbstractBasis{dim} throughout (jacobian, grad, interpolate, etc.)
# TODO: Rewrite math functions for new AbstractBasis
include("quadrature/integration_basis.jl")
# basis_generated.jl is auto-generated. The generator
# (`src/basis/basis_generator.jl`) is a standalone script — do not
# `include` it from the package; it carries `__precompile__(false)` and
# would disable the entire module's precompile cache. Regenerate with:
# julia --project=. src/basis/basis_generator.jl
include("basis/basis_generated.jl")
include("basis/nedelec_reference.jl")
include("basis/rt0_reference.jl")
# ============================================================================
# DOF SYSTEM: Unified field specification system
# Level 4 - DOF system, sparse scratch, element template, materials
# ============================================================================
include("dofs/dofs.jl")
# Modern unified field system (multi-field is fundamental!)
export AbstractDOF, DOFSet, @DOFSet
export element_id, n_element_dofs, element_dofs, basis_type, dof_type # Element accessors
export local_dof_count, global_dof_indices, local_to_global_map, field_dof_range # Coupled assembly
export field_ndofs, field_names, field_count, is_single_field
export quantity_type, entity_type, single_field
export ndofs, dof_size # dof_size needed by fields.jl
export extract_element_dofs, extract_element_dofs_structured # DOF extraction from global vector
export interpolate_fields, interpolate_field, interpolate_field_value # Field interpolation at quadrature points
export interpolate_local_fields # LocalField interpolation with rates
include("sparse/sparse.jl")
# DOF manager and element creation
export DOFManager, get_element_ids, create_elements!
export get_node_dofs, allocate_dofs!
export register_fields!, count_field_dofs, count_entities # NEW: Multi-field registration
export ElementDescription
include("elements/elements.jl")
include("elements/extract_element_dofs.jl")
include("elements/interpolate.jl")
# DOF connectivity (inverse mapping for DOF-based assembly)
export DOFElementConnection, DOFConnectivity, DOFConnectivityGPU
export build_dof_connectivity, build_dof_connectivity_gpu
export connection_count, is_empty
export elem_id, local_dof_idx
# Legacy DOF type (DOF type for field variables)
export DOF # Old entity-based DOF{Quantity, Entity}
# Consolidate FEMBase.jl into src/ (Phase 1 continued)
# Order matters: fields → types → sparse → elements → integrate → problems → assembly
include("fields/fields.jl") # LEGACY field system (DCTI, DVTI - to be removed)
include("legacy/core_types.jl") # Node, IP, IntegrationPoint (LEGACY - Dict-based)
# Compatibility shim: Create FEMBase module for vendor packages EARLY
# NOTE: The compatibility shim file was removed to avoid a missing-file
# include during package load. If a full FEMBase compatibility layer is
# required later, add a proper shim file and include it here.
include("sparse/sparse.jl") # SparseMatrixCOO, SparseVectorCOO
include("elements/elements.jl") # Element type and interface
include("elements/extract_element_dofs.jl") # DOF extraction from global vector
include("elements/interpolate.jl") # Field interpolation at quadrature points
include("elements/elements_lagrange.jl") # OLD - uses AbstractBasis{0} (Poi1)
include("legacy/assembly_problems.jl") # Problem types
include("solvers/solvers_base.jl") # Base solver types
include("legacy/analysis.jl") # Analysis and AbstractResultsWriter
include("legacy/deprecated_fembase.jl") # Deprecated/legacy methods from FEMBase
# GPU Physics (new architecture - pure GPU, all BCs in device code)
# Note: CUDA is loaded by the demo script, not here
# The gpu_physics_elasticity.jl module should be included directly by demos
# Mesh readers (consolidated readers/ → io/)
# AbaqusReader - ABAQUS .inp file format
include("io/keyword_register.jl")
include("io/parse_mesh.jl")
include("io/parse_model.jl")
include("io/create_surface_elements.jl")
include("io/abaqus_download.jl")
# AsterReader - Code Aster .med file format (requires HDF5)
# include("io/read_aster_mesh.jl")
# include("io/read_aster_results.jl")
# Graph algorithms (RCM bandwidth minimization from GraphOrdering.jl)
include("mesh/graph_ordering.jl")
# TODO: Consolidate these vendor packages later
# using AbaqusReader # Consolidated into src/readers.jl
# using AsterReader # Consolidated into src/readers.jl
# Problem types (OLD - all reference old basis types like Seg2, Tri3, Poi1, etc.)
# include("problems_heat.jl")
# export Heat, PlaneHeat
# include("problems_truss.jl")
# export Truss
# include("problems_elasticity.jl")
# export Elasticity
# include("materials_plasticity.jl") # Requires ForwardDiff for automatic differentiation
# export plastic_von_mises
include("legacy/problems_dirichlet.jl")
export Dirichlet
export assemble!, postprocess!
# TODO: Consolidate vendor packages (FEMBeam, Mortar) later
# Structural elements: beams
# @reexport using FEMBeam
### Mortar methods ###
# @reexport using MortarContact2D
# @reexport using MortarContact2DAD
# include("problems_mortar.jl")
# include("problems_mortar_3d.jl")
# export calculate_normals, calculate_normals!, project_from_slave_to_master,
# project_from_master_to_slave, Mortar, get_slave_elements,
# get_polygon_clip, calculate_polygon_area
# include("io.jl") # Requires HDF5 and LightXML - skip for minimal deps
# export Xdmf, h5file, xmffile, xdmf_filter, new_dataitem, update_xdmf!, save!
# Note: Physics API now defined in api.jl (included at top of file)
# physics_api.jl is deprecated and will be removed
# Material models
include("materials/abstract_material.jl")
# Note: abstract_material.jl redefines AbstractMaterial (already in api.jl)
# TODO: Remove duplicate from abstract_material.jl
# Material state variables and traits (new compositional design)
include("materials/state_variables.jl")
export AbstractStateVariable
export PlasticStrain, Backstress, EquivalentPlasticStrain, DamageVariable
export state_variable_type, default_symbol
include("materials/traits.jl")
include("materials/field_traits.jl")
export supported_physics, required_field_types, required_state_variables
export required_material_fields, material_field_type, create_zero_field
export get_state_variable_types, get_state_variable_symbols, is_stateful
# Material cache for state variable storage (global, compositional)
include("materials/material_cache.jl")
export GlobalMaterialCache
export create_global_material_cache
export get_state, get_old_state, set_state!
export update_cache!, reset_cache!
export get_state_variable, set_state_variable
include("materials/global_material_cache.jl")
include("materials/continuum_kinematics.jl")
include("materials/symmetric_fourth_identity.jl")
include("materials/linear_elastic.jl")
export LinearElastic
include("materials/orthotropic_linear_elastic.jl")
include("materials/neo_hookean.jl")
export NeoHookean
include("materials/hyperelastic_models.jl")
include("materials/perfect_plasticity.jl")
export PerfectPlasticity
# NOTE: state_bridge.jl removed - materials now use compositional NamedTuple directly
# No more conversion between monolithic structs and compositional states needed!
include("materials/j2_isotropic_plasticity.jl")
include("materials/stvenant_kirchhoff_j2.jl")
include("materials/scalar_damage.jl")
include("materials/chaboche_j2.jl")
include("materials/norton_creep.jl")
include("materials/eigenstrain_elastic.jl")
include("materials/heat_conductivity.jl")
include("materials/moisture_diffusivity.jl")
include("materials/hydraulic_conductivity.jl")
include("materials/element_wise_scalar_diffusion.jl")
# ============================================================================
# LEVEL 4: ASSEMBLY FRAMEWORK (Generic assembly strategies)
# Level 5 - Assembly framework
# ============================================================================
#
# Old files: element_structures.jl, nodal_structures.jl, framework.jl
# These were NOT used anywhere in the codebase
# Generic assemblers (domain-agnostic)
include("assemblers/abstract.jl")
export AbstractAssembler, AbstractAssemblerCache, AbstractKernel
export ElementBasedAssembler
export COOAssembler, CSCAssembler
include("assemblers/element_cache.jl")
export ElementCache
export create_element_cache
# Per-element scratch (geometry / element / material) plus the global COO
# scratch shared by every assembler.
include("assemblers/caches/element_cache.jl")
include("assemblers/caches/geometry_cache.jl")
include("assemblers/caches/material_cache.jl")
include("assemblers/caches/coo_cache.jl")
include("assemblers/geometry_cache.jl")
export GeometryCache, ImmutableGeometryCache
# Element-based assembler (COO) and its scatter routines.
include("assemblers/element_based/element_based_coo.jl")
include("assemblers/material_cache.jl")
export AssemblyMaterialWorkspace, ImmutableMaterialStateCache
export create_material_cache, create_assembly_workspace
export get_stress, get_tangent, get_field, set_fields!
export get_tangent_vector, get_stress_vector # Zero-allocation field extraction
include("assemblers/caches.jl")
export COOCache, CSCCache
export reset!, extract_system, build_sparsity_pattern
include("assemblers/kernel_interface.jl")
export compute_element_stiffness!, dofs_per_node, get_dof_mapping!
export compute_b_matrix, compute_jacobian, validate_kernel
include("assemblers/element_based_coo.jl")
export assemble!, create_cache
include("assemblers/element_based_csc.jl")
# assemble!, create_cache already exported
# Microkernel architecture for multi-field DOF-by-DOF assembly
# (Included after assemblers since it depends on AbstractKernel, GeometryCache, AssemblyMaterialWorkspace)
include("physics/microkernels.jl") # evaluate() interface, traits
include("physics/formulations.jl") # Helper utilities for Element{K,P,S}
export evaluate, requires_basis_values, requires_basis_gradients, requires_basis_second_derivatives
export field_type_for_dispatch, ThermoelasticityFields
# Microkernel contract for the DOF-based / matrix-free path. Implementations
# live in `domains/<physics>/kernel.jl`.
include("assemblers/microkernel.jl")
# ============================================================================
# LEVEL 5: PHYSICAL DOMAINS (Domain-specific assembly kernels)
# Level 6 - Physical domains (assembly kernels per discipline)
# ============================================================================
# ============================================================================
# COMMON DOMAIN UTILITIES (Shared across all domain types)
# ============================================================================
# Boundary conditions (generic - work with any kernel/domain)
# include("domains/common/boundary_conditions.jl") # Uses old Physics struct - not needed for now
# export apply_neumann_bcs!, apply_dirichlet_bcs! # Explicit BC application
# ============================================================================
# CONTINUUM MECHANICS DOMAIN
# ============================================================================
# Continuum mechanics kernel (weak form only)
include("domains/continuum/kernel.jl")
export ContinuumKernel
export compute_block_at_point # Weak form (atomic operation)
# Continuum cache update functions (three-phase API)
include("domains/continuum/update_geometry_cache.jl")
include("domains/continuum/update_element_cache.jl")
include("domains/continuum/update_material_cache.jl")
export compute_block, compute_block! # Integration API (compute_block! deprecated)
export update_geometry_cache!, update_element_cache!, update_material_cache! # Cache update functions
include("domains/continuum/mixed_up_kernel.jl")
include("domains/continuum/stokes_mixed_kernel.jl")
include("domains/continuum/hellinger_reissner_kernel.jl")
include("domains/continuum/hu_washizu_kernel.jl")
# Continuum assembly (uses generic assemblers)
export compute_element_stiffness # For testing and advanced use
include("domains/heat/kernel.jl")
include("domains/darcy/potential.jl")
include("domains/darcy/mixed_rt0.jl")
include("domains/darcy/mixed_rt0_hex.jl")
# Backend abstraction (CPU/GPU selection)
# TODO: These need to be updated to work with new Physics API
# Temporarily commented out until backend dispatch is updated
# include("backend/abstract.jl")
# export solve!, Auto, GPU, CPU
# export ElasticitySolution
include("domains/thermo_elastic/kernel.jl")
# CPU backend (fallback for now)
# include("backend/cpu.jl")
# GPU backend is now loaded via extension (ext/JuliaFEMCUDAExt.jl)
# Extension automatically loads when user does 'using CUDA'
# No need to manually include anymore!
include("legacy/solvers.jl")
export AbstractSolver, Solver, Nonlinear, NonlinearSolver, Linear, LinearSolver,
get_unknown_field_name, get_formulation_type, get_problems,
get_field_problems, get_boundary_problems,
get_field_assembly, get_boundary_assembly,
initialize!, create_projection, eliminate_interior_dofs,
is_field_problem, is_boundary_problem
# include("solvers_modal.jl") # Requires Arpack for eigenvalue problems
# export Modal
# Re-export Analysis and related types from FEMBase (needed by tests)
export Analysis, AbstractAnalysis, add_problems!, run!
# Commented out during Element{K,P,S} redesign (uses old Element API)
# include("legacy/problems_contact.jl")
# include("legacy/problems_contact_3d.jl")
#include("legacy/problems_contact_3d_autodiff.jl")
# export Contact
module Preprocess
end
using SparseArrays, LinearAlgebra
# NEW: Include modern parametric Mesh{T<:AbstractTopology} infrastructure
# ============================================================================
# Level 7 - Concrete mesh + DOFHandler + DOF-based assembler + matrix-free
# ============================================================================
include("mesh/mesh.jl")
export Mesh, topology_type, nnodes_per_element, nelements, nnodes_total
include("mesh/hex8_facet_maps.jl")
include("mesh/tet4_facet_maps.jl")
include("mesh/wedge6_facet_maps.jl")
include("mesh/pyr5_facet_maps.jl")
# DOF manager requires Mesh type - include after Mesh is defined
include("dofs/dof_manager.jl")
# DOF connectivity (inverse mapping: DOF → Elements) - needs Element and DOFManager
# Connectivity value types must be available before DOFHandler so the
# handler can store `Union{Nothing, DOFConnectivity}` instead of `Any`.
# The builders still live after DOFHandler because they reference it.
include("dofs/dof_connectivity_types.jl")
include("dofs/dof_handler.jl")
include("domains/continuum/facet_mass_kernel.jl")
include("domains/continuum/edge_mass_kernel.jl")
include("dofs/dof_connectivity.jl")
# DOF-based assembler (needs DOF connectivity)
include("assemblers/dof_based_coo.jl")
export DOFBasedCOOAssembler, DOFBasedCOOCache
include("interface/interface_mesh.jl")
include("interface/interface_dof_handler.jl")
# Now that Mesh is defined, include plate elements that depend on it
# include("domains/plates/dkt.jl") # Uses old Physics struct - experimental, not in main test suite
export get_elements_for_node, connectivity_matrix, get_node
export find_nearest_nodes, find_nearest_node
export get_element_set, get_elements_in_set
export get_node_set, get_nodes_in_set, create_node_set_from_element_set!
export extract_surface, validate, info
export set_node_id!, get_node_by_id, set_element_id!, get_element_by_id
export set_node_color!, get_node_color, set_element_color!, get_element_color, get_elements_with_color
export mark_ghost_node!, is_ghost_node, mark_ghost_element!, is_ghost_element
export get_local_nodes, get_local_elements
export apply_node_permutation!, apply_element_permutation!
# DOF-based assembler — CPU plus the backend-agnostic KernelAbstractions
# port (CPU(), CUDABackend(), MetalBackend(), AMDGPUBackend(), oneAPIBackend();
# locally validated against CPU()).
include("assemblers/dof_based/dof_based_coo.jl")
include("assemblers/dof_based/dof_based_coo_ka.jl")
# Mesh refinement strategies
# Partition metadata + multiply-buffer layouts (MPI/GPU hooks; default is
# single-process identity).
include("assemblers/partitioning.jl")
include("assemblers/halo_exchange.jl")
include("assemblers/packed_layout.jl")
include("assemblers/partitioned_matvec.jl")
# Matrix-free path: declarative Dirichlet / MPC constraints, declarative
# Neumann loads, matrix-free preconditioners and the generalized eigensolver.
# All operate on `DOFBasedCOOCache` + `apply_K!` / `apply_M!` and share the
# `apply_constraint_*` hook protocol so they compose freely.
include("assemblers/matrix_free/dirichlet.jl")
include("assemblers/matrix_free/mpc.jl")
include("assemblers/matrix_free/operator.jl")
include("assemblers/matrix_free/preconditioners.jl")
include("assemblers/matrix_free/eigensolve.jl")
include("assemblers/matrix_free/loads.jl")
# ============================================================================
# Level 8 - Mesh utilities and I/O
# ============================================================================
include("mesh/refine.jl")
export AbstractRefineStrategy, LongestEdgeBisection, refine
# Structured mesh generation utilities
include("mesh/structured.jl")
export create_structured_box_mesh, create_unit_cube_mesh
export create_cantilever_mesh, create_thin_plate_mesh
# Polar/circular mesh utilities
include("mesh/circular.jl")
export create_circular_plate_mesh
include("domains/continuum/material_element_lab.jl")
# OLD: Comment out Dict-based Mesh (conflicts with new Mesh{T})
# include("preprocess.jl")
# export create_elements, Mesh, add_node!, add_nodes!,
# add_element_to_element_set!, add_node_to_node_set!,
# find_nearest_nodes, find_nearest_node, reorder_element_connectivity!,
# create_node_set_from_element_set!, filter_by_element_set
# Self-contained Gmsh mesh reader (defines its own `JuliaFEM.GmshReader`
# submodule with `read_gmsh_mesh` / `GmshMesh`).
include("io/gmsh_reader.jl")
# IO submodule for mesh readers and result writers
include("io/io.jl")
include("io/gmsh_reader.jl") # GMSH reader (moved from root)
using .IO
export abaqus_read_mesh, create_surface_elements, create_nodal_elements
export aster_read_mesh # Requires HDF5 - add when optional deps are set up
# Postprocess module
module Postprocess
# ============================================================================
# Optional older API surface (Problem / Assembly / Solver / Analysis,
# Dict-based fields, Abaqus reader, ...). Loaded only when the user opts in
# via `JULIAFEM_ENABLE_LEGACY=1`. Names are accessible as
# `JuliaFEM.Legacy.<name>` and are not re-exported at the top level.
# ============================================================================
const ENABLE_LEGACY = get(ENV, "JULIAFEM_ENABLE_LEGACY", "0") == "1"
if ENABLE_LEGACY
include("legacy/Legacy.jl")
end
# Postprocess utilities (moved to trash - needs refactoring)
# include("postprocess_utils.jl")
# export calc_nodal_values!, get_nodal_vector, get_nodal_dict, copy_field!,
# calculate_area, calculate_center_of_mass, calculate_second_moment_of_mass,
# extract
"""
exchange_matvec_halos_mpi!(recv_vals, send_vals, packed, layout, exchange, comm; mpi_requests = nothing)
include("legacy/deprecations.jl")
Pack halo sends from `packed`, complete non-blocking MPI exchanges into `recv_vals`, then
return. Requires `using MPI` after `JuliaFEM` (loads the `JuliaFEMMPIExt` weak dependency).
export SparseMatrixCOO, SparseVectorCOO, optimize!, resize_sparse
export DCTI, DVTI, DCTV, DVTV, CCTI, CVTI, CCTV, CVTV, Increment
export FieldProblem, BoundaryProblem, Problem, Node, Element, Assembly
export Poi1, Seg2, Seg3, Tri3, Tri6, Tri7, Quad4, Quad8, Quad9,
Tet4, Tet10, Pyr5, Wedge6, Wedge15, Hex8, Hex20, Hex27
export update!, update, add_element!, add_elements!, get_unknown_field_name, add!,
is_field_problem, is_boundary_problem, get_gdofs,
initialize!, get_integration_points, group_by_element_type,
get_unknown_field_dimension, get_connectivity
export get_nonzero_rows, get_local_coordinates, inside, IP, get_element_type,
get_elements, AbstractProblem, IntegrationPoint, filter_by_element_type,
get_element_id, get_nonzero_columns, resize_sparse, resize_sparsevec
Posts all [`MPI.Irecv!`](@ref) before [`MPI.Isend`](@ref); tags encode the directed partition
pair `(sender_part, receiver_part)`. Expects `MPI.Comm_rank(comm) + 1 == exchange.part`.
end
Keyword `mpi_requests`: optional persistent [`Vector{MPI.Request}`](@ref) from
[`allocate_exchange_matvec_halo_mpi_requests`](@ref), length
[`matvec_halo_mpi_request_count`](@ref)`(exchange)`. When `nothing`, a fresh vector is allocated each
call (fine for setup; Krylov inner loops should reuse a buffer).
Typical sequence (full trial workspace): [`gather_owned_from_global_to_packed!`](@ref), this function,
[`unpack_halo_recv_to_packed!`](@ref), [`expand_packed_to_global!`](@ref),
[`apply_K_owned_rows!`](@ref). Lean owned-only path: [`copy_owned_subset_to_packed_owned_prefix!`](@ref),
this function, [`unpack_halo_recv_to_packed!`](@ref), [`apply_K_owned_rows_from_packed!`](@ref).
"""
function exchange_matvec_halos_mpi! end
"""
allocate_exchange_matvec_halo_mpi_requests(exchange::RankHaloExchange)
Preallocate storage for [`exchange_matvec_halos_mpi!`](@ref)`(; mpi_requests=…)`.
Requires `using MPI`. Length equals [`matvec_halo_mpi_request_count`](@ref)`(exchange)`.
"""
function allocate_exchange_matvec_halo_mpi_requests end
"""
mpi_owned_dot_global(a, b, layout, comm) -> Float64
Parallel inner product `a'b` counting each global DOF once via [`owned_dot_global_vecs`](@ref)
on the local partition, summed with [`MPI.Allreduce`](@ref). Requires `using MPI` after
`JuliaFEM`.
"""
function mpi_owned_dot_global end
"""
mpi_partitioned_operator_matvec!(
Ap, p, packed, work, recv_vals, send_vals,
layout, exchange, cache, assembler, kernel, mesh, comm;
dirichlet = nothing, mpi_requests = nothing,
)
Replicated-global matrix-free product including optional [`PenaltyDirichlet`](@ref) post-hook.
Loads `JuliaFEMMPIExt` when both `JuliaFEM` and `MPI` are imported.
Keyword `mpi_requests` is forwarded to [`exchange_matvec_halos_mpi!`](@ref).
"""
function mpi_partitioned_operator_matvec! end
"""
mpi_owned_dot_local(a_owned, b_owned, comm) -> Float64
Local dot `sum_k a_owned[k]*b_owned[k]` reduced with [`MPI.Allreduce`](@ref)`(SUM)` — global inner
product when each global DOF is owned on exactly one rank and `a_owned`/`b_owned` hold owned
entries only (aligned with [`copy_owned_subset_to_packed_owned_prefix!`](@ref)).
"""
function mpi_owned_dot_local end
"""
mpi_partitioned_operator_matvec_owned!(
Ap_owned, p_owned, packed, recv_vals, send_vals,
layout, exchange, cache, assembler, kernel, mesh, comm;
dirichlet = nothing, mpi_requests = nothing,
)
Lean MPI matvec: [`copy_owned_subset_to_packed_owned_prefix!`](@ref), halo exchange,
[`apply_K_owned_rows_from_packed!`](@ref), optional [`apply_penalty_dirichlet_post_ap_owned!`](@ref).
No `ndofs_global`-length trial workspace — trial DOFs stay in `packed`. **No** full-vector
[`MPI.Allreduce!`](@ref) on `Ap`.
Keyword `mpi_requests` is forwarded to [`exchange_matvec_halos_mpi!`](@ref).
Supports [`PenaltyDirichlet`](@ref) only on this path.
"""
function mpi_partitioned_operator_matvec_owned! end
end # module JuliaFEM