diff --git a/PLAN.md b/PLAN.md index 35a9989..0c78d3a 100644 --- a/PLAN.md +++ b/PLAN.md @@ -13,7 +13,7 @@ Every new agent session must read this file together with `PROGRESS.md` before p - If an item becomes obsolete, move it to `PROGRESS.md` with a short reason instead of silently deleting it. ## Current Objective -Execute the Phase 1 structure-alignment refactor in `phases/1-structure-alignment-refactor`, starting with P1A-00 architecture drift audit. This phase must align the current monolithic `include/fesa/fesa.hpp` implementation with the module ownership model in `docs/ARCHITECTURE.md` without changing solver behavior. Product-level Phase 1 reference gaps R-010 and R-013 remain open and must not be hidden by the refactor. +Execute the Phase 1 structure-alignment refactor in `phases/1-structure-alignment-refactor`, starting with P1A-01 module scaffold and facade. P1A-00 completed the architecture drift audit and recorded the migration map in `phases/1-structure-alignment-refactor/step0-architecture-map.md`. This phase must align the current monolithic `include/fesa/fesa.hpp` implementation with the module ownership model in `docs/ARCHITECTURE.md` without changing solver behavior. Product-level Phase 1 reference gaps R-010 and R-013 remain open and must not be hidden by the refactor. ## Required Reading For New Agents 1. `AGENTS.md` @@ -37,7 +37,7 @@ Execute the Phase 1 structure-alignment refactor in `phases/1-structure-alignmen ## Phase Files - Active phase directory: `phases/1-structure-alignment-refactor` - Execute with: `python scripts/execute.py 1-structure-alignment-refactor` -- Step numbering is zero-based. `step0.md` audits current architecture drift and writes a symbol-to-module migration map; `step1.md` creates module scaffold and umbrella facade policy; `step2.md` extracts Core/Util domain, diagnostics, DofManager ownership, and Phase 1 Boundary/Load/Property model ownership; `step3.md` extracts Math and solver adapter boundaries; `step4.md` extracts the Abaqus parser into IO; `step5.md` extracts Results and reference comparison code; `step6.md` extracts MITC4 geometry/strain helpers; `step7.md` extracts MITC4 material/stiffness helpers; `step8.md` extracts Assembly and Analysis workflow; `step9.md` is the independent architecture evaluator closeout. +- Step numbering is zero-based. `step0.md` is complete and wrote `phases/1-structure-alignment-refactor/step0-architecture-map.md`; `step1.md` creates module scaffold and umbrella facade policy; `step2.md` extracts Core/Util domain, diagnostics, DofManager ownership, and Phase 1 Boundary/Load/Property model ownership; `step3.md` extracts Math and solver adapter boundaries; `step4.md` extracts the Abaqus parser into IO; `step5.md` extracts Results and reference comparison code; `step6.md` extracts MITC4 geometry/strain helpers; `step7.md` extracts MITC4 material/stiffness helpers; `step8.md` extracts Assembly and Analysis workflow; `step9.md` is the independent architecture evaluator closeout. - Completed phase directory: `phases/1-linear-static-mitc4-rebaseline` - Historical execution command: `python scripts/execute.py 1-linear-static-mitc4-rebaseline` - Step numbering is zero-based. `step0.md` is complete and recorded in `phases/1-linear-static-mitc4-rebaseline/step0-audit.md`; `step1.md` is complete and created the `quad_02_phase1.inp` normalized reference path; `step2.md` is complete and revalidated core harness guardrails; `step3.md` is complete and revalidated the Phase 1 parser/domain subset; `step4.md` is complete and strengthened validation/singular diagnostics; `step5.md` is complete and revalidated the DofManager/reaction foundation; `step6.md` is complete and revalidated the minimum result model plus displacement CSV comparator; `step7.md` is complete and revalidated MITC4 natural coordinates, tying points, center directors, and integration bases; `step8.md` is complete and revalidated degenerated-continuum displacement, direct covariant strain rows, and MITC shear tying rows; `step9.md` is complete and revalidated plane-stress material, convected-to-local transform, and `2 x 2 x 2` material integration scaffolding; `step10.md` is complete and revalidated MITC4 stiffness, internal force, six-DOF transform, and drilling stabilization; `step11.md` is complete and added MITC4 membrane, bending, shear, twist, drilling-sensitivity, and thin-cantilever locking-sensitivity tests; `step12.md` is complete and revalidated full-space assembly, reduced projection, deterministic sparse-pattern scaffold, solver adapter injection, and full-vector internal/reaction force state; `step13.md` is complete and revalidated active AnalysisModel construction plus input-to-AnalysisState-to-U/RF result workflow; `step14.md` is complete and added the first stored Abaqus displacement regression for `quad_02_phase1`; `step15.md` is complete and recorded the independent evaluator closeout in `phases/1-linear-static-mitc4-rebaseline/step15-evaluator-report.md`. @@ -57,7 +57,7 @@ This phase is an architecture-preserving refactor. It must not change Phase 1 so | ID | Status | Owner | Objective | Depends On | Acceptance Focus | |---|---|---|---|---|---| -| P1A-00 | pending | planner/evaluator | Audit `fesa.hpp` architecture drift and create a symbol-to-module migration map. | P1R-15 | Complete migration map and validation baseline | +| P1A-00 | completed | planner/evaluator | Audit `fesa.hpp` architecture drift and create a symbol-to-module migration map. | P1R-15 | Complete migration map and validation baseline | | P1A-01 | pending | generator | Create module directory scaffold, CMake source boundaries, and umbrella facade policy. | P1A-00 | Module include smoke tests and build stability | | P1A-02 | pending | generator | Extract Core/Util domain, diagnostics, aliases, DOF mapping, `AnalysisModel`, `DofManager`, and Phase 1 Boundary/Load/Property model ownership. | P1A-01 | Core has no dependency on higher layers; Boundary/Load/Property types are no longer hidden in the umbrella header; DOF tests unchanged | | P1A-03 | pending | generator | Extract Math and solver adapter boundaries. | P1A-02 | Linear solver interface remains adapter-ready; int64 paths unchanged | diff --git a/PROGRESS.md b/PROGRESS.md index 2405576..e52a426 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -17,6 +17,32 @@ Phase 1 has a completed rebaseline execution path in `phases/1-linear-static-mit ## Completed Work +### 2026-05-05 - P1A-00 architecture drift audit completed +Author: Codex + +Changed files: +- `phases/1-structure-alignment-refactor/step0-architecture-map.md` +- `phases/1-structure-alignment-refactor/index.json` +- `PLAN.md` +- `PROGRESS.md` + +Summary: +- Confirmed the Phase 1 architecture drift: production code is concentrated in `include/fesa/fesa.hpp`, `src/fesa.cpp` only holds static assertions, and `tests/test_main.cpp` holds all Phase 1 tests. +- Added a module-by-module migration map assigning current Phase 1 production symbol groups to `Analysis`, `Assembly`, `Boundary`, `Core`, `Element`, `IO`, `Load`, `Math`, `Material`, `Property`, `Results`, and `Util`. +- Recorded behavior locks for the refactor: no parser-scope changes, no MITC4 formula changes, no numerical convention changes, no reference tolerance changes, no reduced-vector RF recovery, no Abaqus execution requirement, and no MKL/TBB/HDF5 dependency introduction. +- Identified contract refinements that later steps should resolve carefully: `AnalysisState` belongs to `Core` in `docs/ARCHITECTURE.md`, the basic `Material` domain record is needed before IO extraction, and `Node`/`Element` record ownership should avoid a `Core` to element-kernel dependency cycle. +- Marked P1A-00 completed and moved the active objective to P1A-01. + +Verification: +- Before writing the audit artifact, `python scripts/validate_workspace.py` configured CMake, built `fesa_core` and `fesa_tests`, and ran CTest successfully. +- CTest result: 1 test executable passed. +- After writing the audit artifact and status updates, `phases/index.json` and `phases/1-structure-alignment-refactor/index.json` parsed successfully, `git diff --check` passed, and `python scripts/validate_workspace.py` passed again. + +Follow-up: +- Continue with P1A-01 module scaffold and umbrella facade. +- Keep R-014 open until the full structure-alignment refactor passes P1A-09. +- Keep R-010 and R-013 visible; P1A-00 does not solve missing Abaqus reaction CSV or the three-reference PRD target. + ### 2026-05-05 - Phase 1 structure-alignment refactor phase planned Author: Codex diff --git a/phases/1-structure-alignment-refactor/index.json b/phases/1-structure-alignment-refactor/index.json index 953a98d..e731a64 100644 --- a/phases/1-structure-alignment-refactor/index.json +++ b/phases/1-structure-alignment-refactor/index.json @@ -2,7 +2,7 @@ "project": "FESA", "phase": "1-structure-alignment-refactor", "steps": [ - { "step": 0, "name": "architecture-drift-audit", "status": "pending" }, + { "step": 0, "name": "architecture-drift-audit", "status": "completed", "artifact": "step0-architecture-map.md" }, { "step": 1, "name": "module-scaffold-and-facade", "status": "pending" }, { "step": 2, "name": "core-domain-dof-extraction", "status": "pending" }, { "step": 3, "name": "math-solver-extraction", "status": "pending" }, diff --git a/phases/1-structure-alignment-refactor/step0-architecture-map.md b/phases/1-structure-alignment-refactor/step0-architecture-map.md new file mode 100644 index 0000000..eaf434e --- /dev/null +++ b/phases/1-structure-alignment-refactor/step0-architecture-map.md @@ -0,0 +1,207 @@ +# 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.