/** * StructuralSolver — Linear elastic FEM with tetrahedral elements. * * ## Mathematical Formulation * * **Governing equation** (static linear elasticity): * * ∇·σ + b = 0 (equilibrium) * σ = C:ε (Hooke's law) * ε = ½(∇u + ∇uᵀ) (small strain) * * where: * σ = Cauchy stress tensor [Pa] * ε = infinitesimal strain tensor [-] * u = displacement field [m] * b = body force density [N/m³] * C = 4th-order elasticity tensor (isotropic: parameterized by E, ν) * * **Weak form** (principle of virtual work): * ∫_Ω ε(δu):C:ε(u) dΩ = ∫_Ω δu·b dΩ + ∫_Γ δu·t dΓ * * ## Element Formulation * * **Element type**: 4-node linear tetrahedron (TET4, constant strain). * **Shape functions**: N_i = a_i + b_i·x + c_i·y + d_i·z (linear). * **Strain-displacement matrix B**: Constant within each element (3 per node, 12 DOFs per tet). * **Element stiffness**: Kₑ = V · Bᵀ · D · B (single-point integration, exact for constant strain). * * **Material matrix D** (3D isotropic, Voigt notation): * D = E/((1+ν)(1-2ν)) * [1-ν, ν, ν, 0, 0, 0; ν, 1-ν, ν, 0, 0, 0; ...] * * ## Assembly & Solution * * **Assembly**: Matrix-free approach. Element stiffness matrices are stored * and the global matrix-vector product K*x is computed by summing element * contributions (avoids assembling sparse K explicitly). * * **Solver**: Preconditioned Conjugate Gradient (PCG). * - Preconditioner: Jacobi (diagonal of K) * - Convergence: relative residual tolerance with absolute floor * * **Constraints**: 'fixed' and 'pinned' both constrain all 3 translational DOFs. * Note: Linear tetrahedra have no rotational DOFs, so pinned = fixed. * * ## Stress Recovery * * **Von Mises stress** (element-wise): * σ_VM = √(½[(σ₁-σ₂)² + (σ₂-σ₃)² + (σ₃-σ₁)²]) * * **Safety factor**: F_s = σ_yield / σ_VM (per element) * * ## Convergence Characteristics * * - Linear tets: O(h) for displacements, O(1) for stresses (constant strain) * - Mesh locking possible for near-incompressible materials (ν → 0.5) * * ## Known Limitations * * - Linear elasticity only (no plasticity, no geometric nonlinearity) * - No contact mechanics * - No dynamics (static equilibrium only) * - No beam/shell elements (solid tets only) * - Constant-strain elements underperform quadratic tets for bending * * ## References * * - Bathe, K.J., "Finite Element Procedures", Prentice Hall, 1996 * - Hughes, T.J.R., "The Finite Element Method", Dover, 2000 * - Zienkiewicz & Taylor, "The Finite Element Method", Vol. 1, 7th ed. * * @see ConvergenceControl — CG solver with Jacobi preconditioning * @see MaterialDatabase — E, ν, σ_yield lookup */ import { type ConvergenceResult } from './ConvergenceControl'; import { type StructuralMaterial } from './MaterialDatabase'; import { type CSRMatrix } from '../gpu/SparseLinearSolver'; import { type Force, type Pressure, type Acceleration } from './units/PhysicalQuantity'; /** * For linear tetrahedral elements (which lack rotational degrees of freedom), * a 'pinned' constraint is mathematically identical to a 'fixed' constraint. * Both prevent all translational motion at the specified nodes. */ export type ConstraintType = 'fixed' | 'pinned' | 'roller'; export interface StructuralConstraint { id: string; type: ConstraintType; /** Node indices that are constrained */ nodes: number[]; /** * For 'roller' type: which translational DOF axes to constrain. * 0 = U_x, 1 = U_y, 2 = U_z. * Omit (or pass all three) to behave like 'fixed'. */ dofs?: (0 | 1 | 2)[]; } export type LoadType = 'gravity' | 'point' | 'distributed'; export interface StructuralLoad { id: string; type: LoadType; /** Force vector [fx, fy, fz] in N */ force?: [Force, Force, Force]; /** Acceleration [ax, ay, az] for gravity loads */ acceleration?: [Acceleration, Acceleration, Acceleration]; /** Node index for point loads */ nodeIndex?: number; /** * Tetrahedron element indices for distributed pressure loads (legacy). * The boundary face of each element (shared by only one tet) is used. * For explicit face control prefer surfaceFaces. */ surfaceElements?: number[]; /** * Explicit face references for distributed pressure loads (preferred). * localFace follows the TET4 convention: * 0 → opposite n3 → {n0, n1, n2} * 1 → opposite n2 → {n0, n1, n3} * 2 → opposite n1 → {n0, n2, n3} * 3 → opposite n0 → {n1, n2, n3} */ surfaceFaces?: Array<{ elementIndex: number; localFace: 0 | 1 | 2 | 3; }>; /** Pressure in Pa for distributed loads */ pressure?: Pressure; } export interface StructuralConfig { /** Vertex positions: flat [x0,y0,z0, x1,y1,z1, ...] */ vertices: Float32Array; /** Tetrahedral element connectivity: flat [n0,n1,n2,n3, ...] 4 per tet */ tetrahedra: Uint32Array; /** Material name or direct properties */ material: string | StructuralMaterial; constraints: StructuralConstraint[]; loads: StructuralLoad[]; /** Max CG iterations (default 1000) */ maxIterations?: number; /** CG convergence tolerance (default 1e-8) */ tolerance?: number; /** Use explicit CSR assembly + WebGPU CG when solveAsync() is called. */ useGPU?: boolean; } export interface StructuralStats { nodeCount: number; elementCount: number; maxVonMises: number; minSafetyFactor: number; solveResult: ConvergenceResult | null; solveTimeMs: number; dofCount?: number; nnz?: number; useGPU?: boolean; } export declare class StructuralSolver { readonly fieldNames: readonly ["von_mises_stress", "safety_factor", "displacements", "cauchy_stress"]; private config; private material; private nodeCount; private elementCount; private dofCount; private displacements; private forces; private vonMisesStress; private cauchyStress; private safetyFactors; private constrainedDofs; private useGPU; private elementStiffness; private csrRowPtr; private csrColInd; private csrVal; private dofToCSR; private gpuDisplacementBuffer; private gpuSolver; private solveResult; private solveTimeMs; constructor(config: StructuralConfig); /** * Solve the static equilibrium Ku = f. */ solve(): ConvergenceResult; solveAsync(): Promise; private solveGPUCG; private assembleCSRStiffness; private applyConstraintsToCSR; /** * Assemble element stiffness matrices using linear tetrahedral elements. * Ke = V * Bᵀ * D * B where B is the strain-displacement matrix. */ private assembleStiffness; /** * Assemble the global force vector from loads. */ private assembleForces; /** * Recover Von Mises stress from displacements. * σ = D * B * u → Von Mises = √(σxx²+σyy²+σzz²-σxx·σyy-σyy·σzz-σzz·σxx+3(τxy²+τyz²+τxz²)) */ private recoverStress; getVonMisesStress(): Float32Array; /** Per-element Cauchy stress tensor: [sxx, syy, szz, txy, tyz, txz] × elementCount */ getCauchyStress(): Float32Array; getSafetyFactor(): Float32Array; getDisplacements(): Float32Array; /** Standard SimSolver field surface used by contract/CAEL state digests. */ getField(name: string): Float32Array | null; getCSRMatrix(): CSRMatrix; getDisplacementBuffer(): GPUBuffer | null; readbackOutput(): Promise; /** Update a load and re-solve */ updateLoad(id: string, force: [Force, Force, Force]): void; getStats(): StructuralStats; dispose(): void; } //# sourceMappingURL=StructuralSolver.d.ts.map