# FESA Solver Architecture ## 목표 FESA는 C++17/MSVC 기반 유한요소 구조해석 솔버다. 초기 구현은 MITC4 4절점 shell element의 선형정적 해석이며, 이후 비선형 정적해석, 비선형 동적해석, 열전달 및 thermal-stress coupling, 1D/3D 요소로 확장한다. 초기 구현은 정확도와 테스트 가능성을 우선한다. 단, 대규모 모델을 목표로 하므로 자유도 관리, 희소 행렬 조립, 선형 솔버, 병렬 실행 계층은 초기부터 성능 확장이 가능하도록 분리한다. ## 개발 프로세스 구조 ```text Feature request -> requirements -> research evidence -> FEM formulation -> I/O contract -> reference model and artifact contract -> TDD implementation plan -> C++ implementation -> build/test validation -> HDF5 reference comparison -> physics/release review ``` ## 설계 원칙 - `Domain`은 입력 모델의 의미를 보존하고 파싱 이후 가능한 한 불변에 가깝게 유지한다. - 해석 중 변하는 물리량과 반복 상태는 `AnalysisState`에 명시적으로 분리한다. - 현재 step에서 활성화되는 실행 view는 `AnalysisModel`이 담당하며, `Domain`을 복사하지 않는다. - 요소, 재료, 하중, 경계조건, 해석 알고리즘은 런타임 다형성 기반으로 확장한다. - 결과는 step/frame/field/history 개념으로 저장하여 정적, 비선형, 동적, 열전달 해석을 같은 결과 모델로 다룬다. - 외부 라이브러리인 MKL, TBB, HDF5는 adapter 계층 뒤에 둔다. - Abaqus input 호환성은 parser와 factory/registry 계층에서 관리한다. - shell node는 6자유도이고, 결과 자유도 순서는 `U1, U2, U3, UR1, UR2, UR3`이다. - 단위계는 강제하지 않는다. 입력과 reference artifact metadata에 기록된 일관 단위계를 그대로 사용한다. - 결과 부호와 shell output component naming은 Abaqus 규약을 따른다. - 경계조건은 constrained DOF 제거 방식으로 적용하고, reaction은 full vector 기준 `K_full * U_full - F_full`로 계산한다. - 기본 실수 precision은 `double`이다. - 대규모 모델을 위해 id, index, equation numbering은 int64 기반으로 설계한다. - Mesh quality 진단은 1차 범위에서 제외한다. 대신 singular system 진단은 필수로 제공한다. ## Directory Structure ```text include/fesa/ analysis/ # Static, nonlinear static, dynamic, heat transfer analysis interfaces assembly/ # Global matrix/vector assembly and sparse pattern creation boundary/ # Fix, RBE2, RBE3 and future constraint objects core/ # Domain, AnalysisModel, AnalysisState, DofManager element/ # Node, Element, MITC4 and future elements io/ # Abaqus input parser and HDF5 result writer load/ # NodalLoad, PressureLoad, BodyForce math/ # Vector, Matrix, SparseMatrix, MKL adapter material/ # LinearElastic and future material models property/ # ShellProperty and 1D/2D/3D properties results/ # ResultStep, ResultFrame, FieldOutput, HistoryOutput util/ # Diagnostics, logging, validation helpers verification/ # HDF5 reference comparison utilities src/ analysis/ assembly/ boundary/ core/ element/ io/ load/ math/ material/ property/ results/ util/ verification/ tests/ parser/ element/ assembly/ solver/ hdf5/ reference/ ``` The current repository may not yet contain all directories. They are intended ownership boundaries for implementation planning. ## Core Runtime Objects - `Domain`: owns the validated runtime model object graph created from input: nodes, elements, materials, properties, sets, boundary conditions, loads, and step definitions. - `AnalysisModel`: step-local execution view over active elements, loads, boundary conditions, properties, materials, and equation system view. - `AnalysisState`: owns changing physical quantities and iteration/time state such as displacement, velocity, acceleration, temperature, forces, residual, current time, increment, and element/integration-point state. - `Node`: stores node id, coordinates, and six DOF values in order `U1, U2, U3, UR1, UR2, UR3`. - `Element`: computes local stiffness, internal force/resultants, stress recovery, and connectivity. - `ShellMITC4Element`: 4 nodes, 24 DOF, 2x2 Gauss integration, MITC transverse shear interpolation. - `Material`: base contract for material behavior. - `Property`: element property and section data, including shell thickness. - `LinearElasticShellSection`: isotropic elastic shell section with thickness and shear correction. - `DofManager`: active DOF definitions, constrained/free DOF mapping, equation numbering, sparse pattern ownership, and full/reduced vector reconstruction. - `Assembler`: gathers element contributions into deterministic global sparse data. - `SparseMatrix`: internal sparse matrix abstraction backed by MKL-compatible CSR for v0. - `LinearSolver`: solver interface implemented initially by `MklPardisoSolver`. - `Analysis`: strategy interface for `LinearStaticAnalysis` and future nonlinear/dynamic/thermal analyses. - `Hdf5ResultWriter`: writes mesh, metadata, nodal results, element resultants, stresses, field output, and history output. - `ReferenceComparator`: compares FESA HDF5 output with stored reference HDF5 artifacts using tolerance `1e-5`. ## State Ownership ### Domain `Domain` represents the validated model definition as runtime objects and should not store parser DTOs, equation ids, solver vectors, current displacement, or iteration state. Included: - nodes and elements - materials and properties - node sets and element sets - loads and boundary conditions - analysis step definitions Parser-style definition records may exist as temporary input or factory records, but they are not persistent `Domain` storage. `Domain` owns runtime objects such as `Element`, `Material`, `ShellProperty`, `Load`, and `BoundaryCondition`. ### AnalysisModel `AnalysisModel` is built per active step. It references `Domain` objects by id or stable reference and defines what participates in the current solve. Included: - active elements - active loads - active boundary conditions - active property/material references - current equation system view ### DofManager `DofManager` centralizes all equation numbering. Node or Element objects must not independently own equation ids. Responsibilities: - define active node DOFs - map constrained and free DOFs - assign equation numbers - provide connectivity for sparse matrix pattern generation - reconstruct full vectors from reduced solution vectors ### AnalysisState `AnalysisState` stores mutable quantities and future nonlinear/time history extension points. Included: - displacement, velocity, acceleration - temperature - external force, internal force, residual - current time, increment, Newton iteration - element state and integration point state Phase 1 uses displacement-centered state only, but the structure must not block geometric nonlinear and thermal-stress extensions. ### Results State Results use: - `ResultStep`: analysis step result group - `ResultFrame`: static load increment or dynamic time frame - `FieldOutput`: node/element field results - `HistoryOutput`: selected node, element, set, reaction, or energy histories ## Data Flow ```text Abaqus input file -> InputParser -> temporary parsed records -> Factory/Registry object creation -> Domain runtime object graph -> StepDefinition loop -> AnalysisModel -> DofManager -> sparse pattern creation -> TBB parallel element stiffness computation -> deterministic CSR assembly -> constrained DOF elimination -> MKL PARDISO solve -> full displacement vector reconstruction -> reaction recovery by K_full * U_full - F_full -> TBB parallel element result recovery -> HDF5 step/frame/field/history output -> HDF5 reference comparison ``` ## Patterns ### Strategy Used for swappable analysis and numerical algorithms: - `Analysis`: `LinearStaticAnalysis`, `NonlinearStaticAnalysis`, `DynamicAnalysis`, `HeatTransferAnalysis` - `LinearSolver`: `MklPardisoSolver`, future iterative solver - `TimeIntegrator`: future Newmark/HHT - `ConvergenceCriteria`: future residual, displacement, and energy norms ### Template Method `Analysis::run()` owns the high-level execution order: ```text initialize buildAnalysisModel buildDofMap buildSparsePattern assemble applyBoundaryConditions solve updateState writeResults ``` Nonlinear static analysis will reuse this sequence inside Newton-Raphson loops. Dynamic analysis will reuse it inside time step/frame loops. ### Factory + Registry Abaqus input keywords map to internal object factories: - `*ELEMENT, TYPE=S4` -> `MITC4ElementFactory` - `*ELEMENT, TYPE=S4R` -> `MITC4ElementFactory` - `*MATERIAL`, `*ELASTIC` -> `LinearElasticMaterialFactory` - `*SHELL SECTION` -> `ShellPropertyFactory` - `*BOUNDARY` -> `FixBoundaryFactory` - `*CLOAD` -> `NodalLoadFactory` - `*NSET`, `*ELSET` -> set registry Adding an element, material, load, or boundary condition should not require rewriting the parser core. ### Adapter MKL, TBB, and HDF5 APIs are not exposed directly to solver core objects. Adapter targets: - `SparseMatrix`, `Vector`, `Matrix` - `LinearSolver` - `ParallelFor` - `ResultsWriter` This allows test doubles and future dependency replacement without changing solver physics code. ### HDF5 Dependency Discovery The current local Windows/MSVC HDF5 installation is: ```text C:\Program Files\HDF_Group\HDF5\2.1.1 ``` Implementation planning should use the HDF5 C API through the adapter layer, not the HDF5 C++ API. CMake discovery should prefer one of these explicit environment variables before falling back to default package search: ```powershell $env:HDF5_ROOT = "C:\Program Files\HDF_Group\HDF5\2.1.1" $env:HDF5_DIR = "C:\Program Files\HDF_Group\HDF5\2.1.1\cmake" ``` The expected local artifacts are `include\hdf5.h`, `lib\hdf5.lib`, `bin\hdf5.dll`, and `cmake\hdf5-config.cmake`. `h5dump.exe -V` should report HDF5 `2.1.1` on this machine. ### Runtime Polymorphism Elements, materials, loads, and boundary conditions are handled through base interfaces. Phase 1 prioritizes clarity and testability. If large-model performance requires it later, assembly internals may add type-specific batch kernels. ## MITC4 Result Contract Nodal displacement output: ```text node_id, U1, U2, U3, UR1, UR2, UR3 ``` Nodal reaction output: ```text node_id, RF1, RF2, RF3, RM1, RM2, RM3 ``` Element internal force/resultant output at Gauss points: ```text element_id, gauss_id, xi, eta, N11, N22, N12, M11, M22, M12, Q13, Q23 ``` Stress output: ```text element_id, gauss_id, section_point, S11, S22, S12, S13, S23 ``` ## HDF5 Layout ```text /metadata feature_id solver_version model_id hdf5_version schema_version units tolerance reference_solver /mesh/nodes /mesh/elements/mitc4/connectivity /results/step_000/frame_000/nodal/displacement /results/step_000/frame_000/nodal/reaction /results/step_000/frame_000/element/forces /results/step_000/frame_000/element/stress /results/step_000/frame_000/history ``` ## Parallelism And Sparse Assembly TBB parallelism is allowed for element-local computations, element force recovery, assembly precompute, and independent postprocessing. Global assembly must remain deterministic: ```text parallel element loop -> thread-local sparse contribution buffers -> stable sort by (row, column) -> deterministic sum -> CSR arrays ``` The sparse matrix path must preserve 64-bit index boundaries so MKL `pardiso_64` can be used for large models. The solver must avoid uncontrolled MKL/TBB oversubscription. Thread-count decisions are part of analysis metadata and validation reports. ## Validation Flow ```text python scripts/validate_workspace.py -> CMake configure -> MSVC Debug build -> CTest -> feature-specific reference comparison tests ``` When no CMake project exists yet, validation may report the harness no-op path. Once solver code is introduced, CMake/CTest validation is mandatory. ## Reference Artifact Flow Agents do not run Abaqus or Nastran. ```text Human-approved Abaqus run -> stored HDF5 reference artifact under references/// -> FESA solver HDF5 output -> ReferenceComparator -> pass/fail using abs-or-rel 1e-5 ``` For `mitc4-linear-static-shell`, Abaqus S4R is primary and S4 is diagnostic. ## Performance Extension Direction - Sparse matrix storage is the default global system representation. - MKL direct solver is the first supported solver, but `LinearSolver` must allow future iterative solvers. - Element stiffness and result recovery should be designed for type-specific batch kernels later, but not optimized before correctness evidence exists. - MITC4 formulation should remain clear and reviewable until patch and reference comparisons pass.