14 KiB
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:
python scripts/validate_workspace.py
Result:
- CMake configure succeeded.
fesa_coreandfesa_testsbuilt successfully.- CTest ran
fesa_testssuccessfully. - 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:
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:
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:
Coremust remain free ofIO,Results,Assembly, andAnalysisdependencies.DofManagermust remain the only owner of equation numbering and constrained/free mapping.AnalysisStateis documented underCoreindocs/ARCHITECTURE.md; later steps should not relocate it toAnalysisunless the architecture document or an ADR is updated.- Lightweight
NodeandElementmodel records are ambiguous indocs/ARCHITECTURE.md: the directory comment lists them underElement, whileDomainowns them. To avoid a dependency cycle, this audit recommends keeping mesh record types with the domain model inCore, whileElementowns element kernels and formulation code.
Public API Compatibility Rules
During the refactor:
#include <fesa/fesa.hpp>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, andSparseIndexremain 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
.cppfiles 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:
-
AnalysisStatetarget conflict:docs/ARCHITECTURE.mdplacesAnalysisStateunderCore.- P1A-08 currently says to extract
AnalysisStatewithAnalysis. - Recommendation: keep
AnalysisStateinCore, or updatedocs/ARCHITECTURE.md/ADR before P1A-08 if a different ownership rule is desired.
-
Materialmodel timing:Materialas a domain model record is needed byDomain, 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
Materialrecord before IO extraction, or leave a temporary umbrella-forwarded declaration until P1A-07. Do not create an IO-to-Element dependency for material data.
-
Node/Elementownership ambiguity:docs/ARCHITECTURE.mddirectory comment listsNodeandElementunderElement.Domainowns node and element records, andCoreshould not depend on higher-level element kernels.- Recommendation: keep lightweight mesh records in
Coreand keep MITC4 kernels/formulation inElement. If this final layout is accepted, clarifydocs/ARCHITECTURE.mdin a later documentation sync or evaluator closeout.
Extraction Order
- P1A-01 creates directories, CMake source boundaries, and module include smoke tests.
- P1A-02 extracts stable low-level model and state ownership: aliases, diagnostics, DOF mapping, domain model records, validation,
AnalysisModel,AnalysisState, andDofManager. - P1A-03 extracts
Mathprimitives and solver interfaces. - P1A-04 extracts
IOparser while preserving strict unsupported-feature behavior. - P1A-05 extracts
Resultsand reference comparison. - P1A-06 extracts MITC4 geometry, basis, displacement, direct strain, and tying rows.
- P1A-07 extracts MITC4 material transform, integration, stiffness, drilling, internal force, and kernel.
- P1A-08 extracts
AssemblyandAnalysisorchestration. - 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
NodeorElement. - Do not compute
RFfrom reduced vectors. - Do not add parser support for
S4R,Part/Assembly/Instance,*Include, pressure loads, nonzero prescribed displacement, orNLGEOM=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.hppstill compiles as umbrella include.- New module headers can be included together in tests.
python scripts/validate_workspace.pypasses.- No production behavior changes are introduced.