From fd51534b6ba939ffbe3cb91339356848e3f3dbf6 Mon Sep 17 00:00:00 2001 From: Jukka Aho Date: Mon, 15 Dec 2025 06:18:44 +0200 Subject: [PATCH] feat(physics): add helper utilities for multi-field microkernel assembly New 88-line formulation utilities: - field_type_for_dispatch(): extract field type from Element's S parameter - Helper functions for multi-field Element{K,P,S} system - Works with NamedTuple-based field specifications - Supports thermoelasticity and other multi-physics couplings - Already integrated in JuliaFEM.jl (line 500) Provides utilities for multi-field microkernel assembly with Element{K,P,S} system. --- src/physics/formulations.jl | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/physics/formulations.jl diff --git a/src/physics/formulations.jl b/src/physics/formulations.jl new file mode 100644 index 0000000..be647e4 --- /dev/null +++ b/src/physics/formulations.jl @@ -0,0 +1,87 @@ +# This file is a part of JuliaFEM. +# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md + +""" +Helper utilities for multi-field microkernel assembly. + +Works with existing Element{K,P,S} system where S is a NamedTuple specifying fields. + +# Philosophy + +Element{K,P,S} encodes everything: +- K: Topology (Triangle, Tetrahedron, etc.) +- P: Basis (Lagrange{1}, Lagrange{2}, etc.) +- S: NamedTuple of fields with types and entity locations + +# Example + +```julia +# Thermoelasticity using Element{K,P,S} directly: +S = @DOFSet{T::DOF{Temperature,Vertex}, u::DOF{Displacement{3},Vertex}} +elem = Element{Tet4, Lagrange{1}, S}(id, dof_indices) + +# Extract field info (compile-time!): +field_names = fieldnames(S) # (:T, :u) +range_T = field_dof_range(elem, :T) # Compile-time range +``` +""" + +using ..JuliaFEM: AbstractField, Displacement, Temperature + +# ============================================================================ +# FIELD TYPE EXTRACTION FROM S (Element{K,P,S}) +# ============================================================================ + +""" + field_type_for_dispatch(S, field_name::Symbol) + +Extract field type from Element's S parameter for dispatch. + +Works at runtime with NamedTuple-based field specifications. + +# Example +```julia +S = @DOFSet{T::DOF{Temperature,Vertex}, u::DOF{Displacement{3},Vertex}} +field_type_for_dispatch(S, :T) # Temperature() +field_type_for_dispatch(S, :u) # Displacement{3}() +``` +""" +function field_type_for_dispatch(::Type{S}, field_name::Symbol) where S<:DOFSet + # Get field names at runtime + names = fieldnames(S) + idx = findfirst(==(field_name), names) + isnothing(idx) && error("Field $field_name not found in $S") + + # Get the type of that field + field_tuple_type = fieldtype(S, idx) + + # field_tuple_type should be DOF{FieldType, EntityType} + # Extract the FieldType (first element) + FieldType = field_tuple_type.parameters[1] + + # FieldType must be a field type (AbstractField) + if FieldType <: AbstractField + # Create an instance of the field type + return FieldType() + else + error("Expected field type (AbstractField) in DOF, got $FieldType. Use format: DOF{FieldType, EntityType} where FieldType <: AbstractField") + end +end + +# ============================================================================ +# CONVENIENCE TYPE ALIASES (for documentation/examples) +# ============================================================================ + +""" + ThermoelasticityFields + +Type alias for common thermoelasticity field specification. +Use as Element{K, P, ThermoelasticityFields} type parameter. + +# Example +```julia +const ThermoelasticityFields = @DOFSet{T::DOF{Temperature,Vertex}, u::DOF{Displacement{3},Vertex}} +elem = Element{Tet4, Lagrange{1}, ThermoelasticityFields}(id, dofs) +``` +""" +const ThermoelasticityFields = @DOFSet{T::DOF{Temperature,Vertex}, u::DOF{Displacement{3},Vertex}}