# P1A-00 Architecture Drift Audit And Migration Map Date: 2026-05-05 Author: Codex ## Verdict Architecture drift is confirmed. The Phase 1 rebaseline implementation is behaviorally useful and currently validated, but it does not yet follow the module ownership model in `docs/ARCHITECTURE.md`. Production code is concentrated in `include/fesa/fesa.hpp`, while `src/fesa.cpp` only holds numeric static assertions. This audit is a behavior-preserving migration map. It does not approve parser-scope changes, MITC4 formula changes, reference tolerance changes, solver behavior changes, or numerical convention changes. ## Baseline Evidence Pre-refactor validation was run before writing this artifact: ```bash python scripts/validate_workspace.py ``` Result: - CMake configure succeeded. - `fesa_core` and `fesa_tests` built successfully. - CTest ran `fesa_tests` successfully. - 1 test executable passed. Current production/test layout: | Path | Current state | |---|---| | `include/fesa/fesa.hpp` | 2682 lines, main production implementation body | | `src/fesa.cpp` | 8 lines, static assertions only | | `tests/test_main.cpp` | 1947 lines, all Phase 1 tests and test harness | | `CMakeLists.txt` | Builds `fesa_core` from only `src/fesa.cpp` | ## Target Module Set Use the module names documented in `docs/ARCHITECTURE.md`: ```text Analysis Assembly Boundary Core Element IO Load Math Material Property Results Util ``` Keep `include/fesa/fesa.hpp` as an umbrella facade during and after the refactor unless an ADR explicitly changes the public include policy. ## Dependency Direction Recommended extraction dependency direction: ```text Core type aliases -> Util diagnostics/string/numeric helpers -> Math primitives and solver interfaces -> Boundary/Load/Property/Material model primitives -> Core Domain, AnalysisModel, AnalysisState, DofManager -> IO parser -> Results and reference comparison -> Element MITC4 formulation and kernel -> Assembly -> Analysis workflow -> umbrella facade ``` Practical notes: - `Core` must remain free of `IO`, `Results`, `Assembly`, and `Analysis` dependencies. - `DofManager` must remain the only owner of equation numbering and constrained/free mapping. - `AnalysisState` is documented under `Core` in `docs/ARCHITECTURE.md`; later steps should not relocate it to `Analysis` unless the architecture document or an ADR is updated. - Lightweight `Node` and `Element` model records are ambiguous in `docs/ARCHITECTURE.md`: the directory comment lists them under `Element`, while `Domain` owns them. To avoid a dependency cycle, this audit recommends keeping mesh record types with the domain model in `Core`, while `Element` owns element kernels and formulation code. ## Public API Compatibility Rules During the refactor: - `#include ` must keep working for all existing tests and clients. - Public symbols remain in namespace `fesa`. - Existing type aliases remain unchanged: `Real = double`, `GlobalId`, `LocalIndex`, `EquationId`, and `SparseIndex` remain signed 64-bit paths. - Existing class/function names should remain source-compatible unless a narrow compile conflict forces a documented alias or forwarding wrapper. - Module headers may be introduced for direct includes, but the umbrella header remains the compatibility surface. - Moving inline definitions to `.cpp` files is allowed only when declarations remain available through the umbrella facade and CMake compiles the moved implementations. - No MKL, TBB, or HDF5 API may leak into solver core while files are moved. - Each implementation extraction step must preserve `python scripts/validate_workspace.py`. ## Production Symbol Migration Map Line numbers refer to the current `include/fesa/fesa.hpp` audit snapshot. | Current symbols/range | Target module | Extraction step | Notes | |---|---|---|---| | `Real`, `GlobalId`, `LocalIndex`, `EquationId`, `SparseIndex` lines 23-27 | `Core` | P1A-02 | Keep centralized; static assertions remain covered. | | `Severity`, `SourceLocation`, `Diagnostic`, `hasError`, `containsDiagnostic`, `makeDiagnostic` lines 29-59 | `Util` | P1A-02 | Diagnostics may include `Core` type aliases only. | | `trim`, `lower`, `splitCsv`, `parseReal`, `parseInt64`, `addUnique`, `generatedRange` lines 61-121 and 303-318 | `Util` | P1A-02 | General parsing/list helpers; avoid IO-specific ownership unless helper becomes keyword-specific. | | `Dof`, `allDofs`, `dofIndex`, `abaqusDofNumber`, `dofFromAbaqus`, `dofLabel`, component-label helpers lines 124-169 | `Core` | P1A-02 | Preserve DOF order `UX,UY,UZ,RX,RY,RZ`. | | `Vec3`, vector arithmetic, `dot`, `cross`, `norm`, `isFinite`, normalization lines 171-223 | `Math` | P1A-03 | Low-level math primitive used by Core and Element. | | `Node`, `ElementType`, `Element`, `NodeSet`, `ElementSet`, `StepDefinition`, `Domain` lines 225-300 | `Core` | P1A-02 | Recommended Core ownership to avoid `Core -> Element` cycle; Element module owns kernels. | | `Material` lines 257-261 | `Material` | P1A-02 or P1A-07 contract refinement | Basic material record is needed by Domain and IO before MITC4 stiffness extraction; see contract refinements below. | | `ShellSection` lines 263-267 | `Property` | P1A-02 | Phase 1 shell property record. | | `BoundaryCondition` lines 269-274 | `Boundary` | P1A-02 | Phase 1 fixed-boundary model record; no RBE support added. | | `NodalLoad` lines 276-280 | `Load` | P1A-02 | Phase 1 concentrated load record; no pressure/body load support added. | | `KeywordLine`, `parseKeywordLine`, `ParseResult`, `AbaqusInputParser` lines 320-761 | `IO` | P1A-04 | Preserve strict Abaqus Phase 1 subset and unsupported-feature diagnostics. | | `numericTarget`, `resolveNodeTarget`, `dofNameOrNumber`, `validAbaqusDofRange` lines 763-813 | `Core` or `Util` | P1A-02 | Domain target/DOF helpers used outside parser; keep parser-independent. | | `shellSectionForElement` lines 790-801 | `Property` | P1A-02 | Property lookup over Domain element sets. | | `validateDomain` lines 815-960 | `Core` with `Util` diagnostics | P1A-02 | Domain validation/singular-prone model checks; no parser support changes. | | `AnalysisModel`, `buildLinearStaticAnalysisModel` lines 964-1017 | `Core` | P1A-02 | Architecture document places active model view near Core. | | `DofAddress`, `DofManager` lines 1019-1146 | `Core` | P1A-02 | Must remain sole equation-numbering owner. | | `SparsePatternEntry`, `SparsePattern` lines 1149-1166 | `Math` | P1A-03 | Data representation for future sparse path. | | `buildReducedSparsePattern` lines 1169-1192 | `Assembly` | P1A-08 | It derives assembly pattern from Domain and DofManager; data type remains Math. | | `DenseMatrix` lines 1195-1235 | `Math` | P1A-03 | Current deterministic dense test matrix, not production sparse backend. | | `recoverFullReaction` lines 1238-1247 | `Assembly` | P1A-08 | Preserve `K_full * U_full - F_full`. | | `SolveResult`, `LinearSolver`, `GaussianEliminationSolver` lines 1250-1314 | `Math` | P1A-03 | Keep `LinearSolver` as adapter boundary for future MKL. | | `ShapeData`, `shapeFunctions`, `LocalBasis` lines 1317-1347 | `Element` | P1A-06 | Current shape helper is MITC4-oriented. | | `MITC4NaturalPoint`, `MITC4TyingPoint`, node/tying coordinate helpers lines 1350-1369 | `Element` | P1A-06 | Preserve FESA/Abaqus S4 node order and A/B/C/D tying labels. | | `MITC4DirectorFrame`, `MITC4MidsurfaceDerivatives`, `MITC4Geometry`, `MITC4IntegrationBasis` lines 1372-1410 | `Element` | P1A-06 | Geometry/director/basis layer. | | MITC4 type aliases and strain component helpers lines 1413-1433 | `Element` | P1A-06 | Preserve strain order contract. | | `MITC4LocalRotations`, displacement derivative/evaluation/row structs lines 1435-1469 | `Element` | P1A-06 | Kinematic and B-row data. | | `MITC4MaterialMatrixEvaluation` and `MITC4MaterialMatrix` helpers lines 1472-1488 and 1800-1854 | `Material` | P1A-07 | Plane-stress material law and material vector operations. | | `MITC4StrainTransform` and transform helpers lines 1481-1488, 1856-1955 | `Element` with `Material` inputs | P1A-07 | Transform depends on integration basis; keep formulas unchanged. | | `MITC4IntegrationPoint`, material integration sample/data lines 1490-1518 and 1785-1798, 1958-1985 | `Element` | P1A-07 | Element integration scaffolding. | | Global axis helpers, MITC4 diagnostics, append diagnostics lines 1520-1536 | `Element` or `Util` | P1A-06 | Keep MITC4-specific diagnostics near Element; generic append helper can move to Util. | | Geometry/director/basis/displacement/strain row functions lines 1540-1779 | `Element` | P1A-06 | No formula/sign changes. | | `computeLocalBasis` lines 1988-1995 | `Element` | P1A-06 | Legacy-facing wrapper around current geometry policy. | | `ElementStiffnessOptions`, drilling/stiffness result structs lines 1997-2025 | `Element` | P1A-07 | Drilling scale policy remains documented baseline. | | Local DOF transform, strain-row transform, `B^T D B`, drilling, stiffness, internal force, `MITC4ElementKernel` lines 2028-2208 | `Element` | P1A-07 | Preserve `2 x 2 x 2`, drilling reference diagonal, and internal force behavior. | | `AssemblyResult`, `ReducedSystem`, `assembleSystem`, `projectToReducedSystem` lines 2211-2316 | `Assembly` | P1A-08 | Preserve full-space stiffness/load data for RF. | | `FieldOutput`, `ResultFrame`, `ResultStep`, `ResultFile`, `InMemoryResultsWriter` lines 2319-2417 | `Results` | P1A-05 | Preserve step/frame/field metadata for `U` and `RF`. | | `AnalysisState` lines 2420-2426 | `Core` | P1A-02 or P1A-08 contract refinement | Architecture document places `AnalysisState` under Core. | | `AnalysisResult`, `Analysis`, `LinearStaticAnalysis`, `runLinearStaticInputString` lines 2428-2528 | `Analysis` | P1A-08 | Preserve Strategy + Template Method and solver injection. | | `CsvDisplacementRow`, `CsvDisplacementTable`, CSV loaders, `ComparisonOptions`, `ComparisonResult`, `compareDisplacements` lines 2531-2679 | `Results` | P1A-05 | Reference-comparison layer; no tolerance/header changes. | ## Test Migration And Characterization Map Keep tests behavior-preserving. Existing tests can remain in `tests/test_main.cpp` initially, but each extraction step should add direct module include smoke tests and may later split tests only with a dedicated contract. | Test range | Coverage area | Must protect during | |---|---|---| | lines 310-331 | Core aliases and DOF mapping | P1A-02 | | lines 333-544 | Abaqus parser and reference input compatibility | P1A-04 | | lines 557-678 | `AnalysisModel` and domain validation/singular diagnostics | P1A-02 | | lines 690-805 | DofManager, full-vector reconstruction, RF formula, sparse connectivity | P1A-02, P1A-03, P1A-08 | | lines 826-895 | Assembly projection, full-space preservation, Gaussian solver diagnostics | P1A-03, P1A-08 | | lines 917-1099 | Results schema, CSV loading/comparison, `quad_02_phase1` regression | P1A-05, P1A-08 | | lines 1116-1492 | MITC4 shape, geometry, strain, tying, material transform/integration | P1A-06, P1A-07 | | lines 1512-1749 | MITC4 stiffness, drilling, patch, locking-sensitivity, internal force | P1A-07 | | lines 1777-1920 | Linear static analysis workflow, parse/validation routing, solver injection | P1A-08 | ## Contract Refinements To Consider Before Later Steps These are not behavior changes, but they are important for avoiding dependency cycles: 1. `AnalysisState` target conflict: - `docs/ARCHITECTURE.md` places `AnalysisState` under `Core`. - P1A-08 currently says to extract `AnalysisState` with `Analysis`. - Recommendation: keep `AnalysisState` in `Core`, or update `docs/ARCHITECTURE.md`/ADR before P1A-08 if a different ownership rule is desired. 2. `Material` model timing: - `Material` as a domain model record is needed by `Domain`, parser, validation, assembly, and MITC4 stiffness. - P1A-07 owns material/stiffness helpers, but IO extraction occurs earlier in P1A-04. - Recommendation: either extract the basic `Material` record before IO extraction, or leave a temporary umbrella-forwarded declaration until P1A-07. Do not create an IO-to-Element dependency for material data. 3. `Node`/`Element` ownership ambiguity: - `docs/ARCHITECTURE.md` directory comment lists `Node` and `Element` under `Element`. - `Domain` owns node and element records, and `Core` should not depend on higher-level element kernels. - Recommendation: keep lightweight mesh records in `Core` and keep MITC4 kernels/formulation in `Element`. If this final layout is accepted, clarify `docs/ARCHITECTURE.md` in a later documentation sync or evaluator closeout. ## Extraction Order 1. P1A-01 creates directories, CMake source boundaries, and module include smoke tests. 2. P1A-02 extracts stable low-level model and state ownership: aliases, diagnostics, DOF mapping, domain model records, validation, `AnalysisModel`, `AnalysisState`, and `DofManager`. 3. P1A-03 extracts `Math` primitives and solver interfaces. 4. P1A-04 extracts `IO` parser while preserving strict unsupported-feature behavior. 5. P1A-05 extracts `Results` and reference comparison. 6. P1A-06 extracts MITC4 geometry, basis, displacement, direct strain, and tying rows. 7. P1A-07 extracts MITC4 material transform, integration, stiffness, drilling, internal force, and kernel. 8. P1A-08 extracts `Assembly` and `Analysis` orchestration. 9. P1A-09 independently evaluates architecture alignment and records any residual debt. ## Non-Negotiable Behavior Locks - Do not change `Real`, id, equation id, sparse index, or DOF ordering. - Do not move equation ids into `Node` or `Element`. - Do not compute `RF` from reduced vectors. - Do not add parser support for `S4R`, `Part/Assembly/Instance`, `*Include`, pressure loads, nonzero prescribed displacement, or `NLGEOM=YES`. - Do not change MITC4 formulation, tying signs, integration order, or drilling scale. - Do not change displacement CSV column mapping or reference tolerances. - Do not require Abaqus execution. - Do not add MKL, TBB, or HDF5 dependencies during this refactor phase. ## Handoff To P1A-01 P1A-01 should start by creating the full documented module directory scaffold and include smoke tests while leaving production implementation in place. It should not move large bodies of code yet. Required P1A-01 baseline checks: - `include/fesa/fesa.hpp` still compiles as umbrella include. - New module headers can be included together in tests. - `python scripts/validate_workspace.py` passes. - No production behavior changes are introduced.