refactor: add phase1 module scaffold

This commit is contained in:
NINI
2026-05-05 00:35:31 +09:00
parent 90307dc13c
commit 59dcc77a24
31 changed files with 239 additions and 6 deletions
+5 -1
View File
@@ -2,7 +2,11 @@ cmake_minimum_required(VERSION 3.20)
project(FESA VERSION 0.1.0 LANGUAGES CXX)
add_library(fesa_core STATIC src/fesa.cpp)
file(GLOB_RECURSE FESA_CORE_SOURCES CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
)
add_library(fesa_core STATIC ${FESA_CORE_SOURCES})
target_include_directories(fesa_core PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)
+3 -3
View File
@@ -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-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.
Execute the Phase 1 structure-alignment refactor in `phases/1-structure-alignment-refactor`, continuing with P1A-02 Core/Util extraction. P1A-00 completed the architecture drift audit and P1A-01 created the module scaffold, source directories, CMake source boundary, and include smoke test without moving production behavior. 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` 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.
- Step numbering is zero-based. `step0.md` is complete and wrote `phases/1-structure-alignment-refactor/step0-architecture-map.md`; `step1.md` is complete and created module scaffold headers, source directories, CMake source discovery, and umbrella compatibility smoke coverage; `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`.
@@ -58,7 +58,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 | 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-01 | completed | 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 |
| P1A-04 | pending | generator | Extract Abaqus parser into IO. | P1A-02 | Parser subset and unsupported-feature diagnostics unchanged |
+53 -1
View File
@@ -13,10 +13,62 @@ Every new agent session must read this file together with `PLAN.md` before plann
- Do not remove history unless the user explicitly asks for archival cleanup.
## Current Status
Phase 1 has a completed rebaseline execution path in `phases/1-linear-static-mitc4-rebaseline`. Steps 0 through 15 are complete, and P1R-15 recorded a pass-with-documented-gaps evaluator closeout. A follow-up architecture refactor phase is now planned in `phases/1-structure-alignment-refactor` because the current production implementation is concentrated in `include/fesa/fesa.hpp` instead of the module directories documented in `docs/ARCHITECTURE.md`. `quad_02_phase1.inp` is the normalized Phase 1-compatible input path for the stored `quad_02` S4 reference pair, while the original `quad_02.inp` remains preserved unsupported provenance. Core numeric aliases, DOF mapping, validation harness, model diagnostic context, the Phase 1 parser/domain subset, validation/singular diagnostics, DofManager/reaction foundation, minimum result model metadata, displacement CSV comparator foundation, MITC4 geometry/director scaffolding, MITC4 displacement/strain/tying row scaffolding, MITC4 material/transform/integration scaffolding, MITC4 stiffness/drilling/internal-force scaffolding, MITC4 patch/locking-sensitivity tests, full-space assembly, reduced projection, sparse-pattern scaffold, solver adapter injection, full-vector internal/reaction force state, active AnalysisModel construction, input-to-AnalysisState-to-U/RF result workflow, and the first stored Abaqus displacement regression have been revalidated. Full PRD Phase 1 completion still depends on the open architecture/reference gaps R-014, R-010, and R-013. The old `phases/1-linear-static-mitc4` path is historical and superseded after the MITC4 formulation reset.
Phase 1 has a completed rebaseline execution path in `phases/1-linear-static-mitc4-rebaseline`. Steps 0 through 15 are complete, and P1R-15 recorded a pass-with-documented-gaps evaluator closeout. The follow-up architecture refactor phase in `phases/1-structure-alignment-refactor` is underway because the current production implementation is concentrated in `include/fesa/fesa.hpp` instead of the module directories documented in `docs/ARCHITECTURE.md`; P1A-00 and P1A-01 are complete, so the next step is P1A-02 Core/Util extraction. `quad_02_phase1.inp` is the normalized Phase 1-compatible input path for the stored `quad_02` S4 reference pair, while the original `quad_02.inp` remains preserved unsupported provenance. Core numeric aliases, DOF mapping, validation harness, model diagnostic context, the Phase 1 parser/domain subset, validation/singular diagnostics, DofManager/reaction foundation, minimum result model metadata, displacement CSV comparator foundation, MITC4 geometry/director scaffolding, MITC4 displacement/strain/tying row scaffolding, MITC4 material/transform/integration scaffolding, MITC4 stiffness/drilling/internal-force scaffolding, MITC4 patch/locking-sensitivity tests, full-space assembly, reduced projection, sparse-pattern scaffold, solver adapter injection, full-vector internal/reaction force state, active AnalysisModel construction, input-to-AnalysisState-to-U/RF result workflow, and the first stored Abaqus displacement regression have been revalidated. Full PRD Phase 1 completion still depends on the open architecture/reference gaps R-014, R-010, and R-013. The old `phases/1-linear-static-mitc4` path is historical and superseded after the MITC4 formulation reset.
## Completed Work
### 2026-05-05 - P1A-01 module scaffold and facade completed
Author: Codex
Changed files:
- `CMakeLists.txt`
- `include/fesa/ModuleInfo.hpp`
- `include/fesa/Analysis/Analysis.hpp`
- `include/fesa/Assembly/Assembly.hpp`
- `include/fesa/Boundary/Boundary.hpp`
- `include/fesa/Core/Core.hpp`
- `include/fesa/Element/Element.hpp`
- `include/fesa/IO/IO.hpp`
- `include/fesa/Load/Load.hpp`
- `include/fesa/Math/Math.hpp`
- `include/fesa/Material/Material.hpp`
- `include/fesa/Property/Property.hpp`
- `include/fesa/Results/Results.hpp`
- `include/fesa/Util/Util.hpp`
- `include/fesa/fesa.hpp`
- `src/Analysis/Analysis.cpp`
- `src/Assembly/Assembly.cpp`
- `src/Boundary/Boundary.cpp`
- `src/Core/Core.cpp`
- `src/Element/Element.cpp`
- `src/IO/IO.cpp`
- `src/Load/Load.cpp`
- `src/Math/Math.cpp`
- `src/Material/Material.cpp`
- `src/Property/Property.cpp`
- `src/Results/Results.cpp`
- `src/Util/Util.cpp`
- `tests/test_main.cpp`
- `phases/1-structure-alignment-refactor/index.json`
- `PLAN.md`
- `PROGRESS.md`
Summary:
- Added architecture module scaffold headers and matching source directories for `Analysis`, `Assembly`, `Boundary`, `Core`, `Element`, `IO`, `Load`, `Math`, `Material`, `Property`, `Results`, and `Util`.
- Added `include/fesa/ModuleInfo.hpp` to record the module list and stable umbrella facade header policy without changing solver behavior, and exposed it through the existing `fesa/fesa.hpp` umbrella.
- Updated CMake to discover current and future `src/**/*.cpp` files under the module directories.
- Added an include compatibility smoke test that includes all module headers before `fesa/fesa.hpp` and checks the module list plus existing DOF mapping still works.
- No production symbols were moved from `include/fesa/fesa.hpp` in this step.
Verification:
- First ran `python scripts/validate_workspace.py` after adding the smoke test; it failed as expected because `fesa/Analysis/Analysis.hpp` did not exist yet.
- After adding the scaffold and CMake wiring, `python scripts/validate_workspace.py` configured CMake, built `fesa_core` and `fesa_tests`, and ran CTest successfully.
- CTest result: 1 test executable passed.
Follow-up:
- Continue with P1A-02 Core/Util extraction while preserving all public symbols and behavior.
- Keep R-014 open until P1A-09 independently accepts the final architecture alignment.
### 2026-05-05 - P1A-00 architecture drift audit completed
Author: Codex
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kAnalysis = "Analysis";
} // namespace fesa::module
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kAssembly = "Assembly";
} // namespace fesa::module
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kBoundary = "Boundary";
} // namespace fesa::module
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kCore = "Core";
} // namespace fesa::module
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kElement = "Element";
} // namespace fesa::module
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kIO = "IO";
} // namespace fesa::module
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kLoad = "Load";
} // namespace fesa::module
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kMaterial = "Material";
} // namespace fesa::module
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kMath = "Math";
} // namespace fesa::module
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <array>
#include <string_view>
namespace fesa {
using ModuleList = std::array<std::string_view, 12>;
inline constexpr ModuleList kArchitectureModules = {
"Analysis", "Assembly", "Boundary", "Core", "Element", "IO",
"Load", "Math", "Material", "Property", "Results", "Util",
};
constexpr const ModuleList& architectureModules() noexcept {
return kArchitectureModules;
}
constexpr std::string_view umbrellaFacadeHeader() noexcept {
return "fesa/fesa.hpp";
}
} // namespace fesa
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kProperty = "Property";
} // namespace fesa::module
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kResults = "Results";
} // namespace fesa::module
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
namespace fesa::module {
inline constexpr std::string_view kUtil = "Util";
} // namespace fesa::module
+2
View File
@@ -1,5 +1,7 @@
#pragma once
#include "fesa/ModuleInfo.hpp"
#include <algorithm>
#include <array>
#include <cctype>
@@ -3,7 +3,7 @@
"phase": "1-structure-alignment-refactor",
"steps": [
{ "step": 0, "name": "architecture-drift-audit", "status": "completed", "artifact": "step0-architecture-map.md" },
{ "step": 1, "name": "module-scaffold-and-facade", "status": "pending" },
{ "step": 1, "name": "module-scaffold-and-facade", "status": "completed" },
{ "step": 2, "name": "core-domain-dof-extraction", "status": "pending" },
{ "step": 3, "name": "math-solver-extraction", "status": "pending" },
{ "step": 4, "name": "io-parser-extraction", "status": "pending" },
+1
View File
@@ -0,0 +1 @@
#include "fesa/Analysis/Analysis.hpp"
+1
View File
@@ -0,0 +1 @@
#include "fesa/Assembly/Assembly.hpp"
+1
View File
@@ -0,0 +1 @@
#include "fesa/Boundary/Boundary.hpp"
+1
View File
@@ -0,0 +1 @@
#include "fesa/Core/Core.hpp"
+1
View File
@@ -0,0 +1 @@
#include "fesa/Element/Element.hpp"
+1
View File
@@ -0,0 +1 @@
#include "fesa/IO/IO.hpp"
+1
View File
@@ -0,0 +1 @@
#include "fesa/Load/Load.hpp"
+1
View File
@@ -0,0 +1 @@
#include "fesa/Material/Material.hpp"
+1
View File
@@ -0,0 +1 @@
#include "fesa/Math/Math.hpp"
+1
View File
@@ -0,0 +1 @@
#include "fesa/Property/Property.hpp"
+1
View File
@@ -0,0 +1 @@
#include "fesa/Results/Results.hpp"
+1
View File
@@ -0,0 +1 @@
#include "fesa/Util/Util.hpp"
+32
View File
@@ -1,3 +1,15 @@
#include "fesa/Analysis/Analysis.hpp"
#include "fesa/Assembly/Assembly.hpp"
#include "fesa/Boundary/Boundary.hpp"
#include "fesa/Core/Core.hpp"
#include "fesa/Element/Element.hpp"
#include "fesa/IO/IO.hpp"
#include "fesa/Load/Load.hpp"
#include "fesa/Math/Math.hpp"
#include "fesa/Material/Material.hpp"
#include "fesa/Property/Property.hpp"
#include "fesa/Results/Results.hpp"
#include "fesa/Util/Util.hpp"
#include "fesa/fesa.hpp"
#include <array>
@@ -7,6 +19,7 @@
#include <type_traits>
#include <stdexcept>
#include <string>
#include <string_view>
#include <vector>
static_assert(std::is_same_v<fesa::Real, double>, "Real must remain double");
@@ -330,6 +343,25 @@ FESA_TEST(core_types_and_dof_mapping_are_stable) {
FESA_CHECK(!fesa::dofFromAbaqus(7).has_value());
}
FESA_TEST(module_scaffold_headers_are_include_compatible_with_umbrella) {
const auto modules = fesa::architectureModules();
FESA_CHECK(modules.size() == 12);
FESA_CHECK(modules[0] == std::string_view("Analysis"));
FESA_CHECK(modules[1] == std::string_view("Assembly"));
FESA_CHECK(modules[2] == std::string_view("Boundary"));
FESA_CHECK(modules[3] == std::string_view("Core"));
FESA_CHECK(modules[4] == std::string_view("Element"));
FESA_CHECK(modules[5] == std::string_view("IO"));
FESA_CHECK(modules[6] == std::string_view("Load"));
FESA_CHECK(modules[7] == std::string_view("Math"));
FESA_CHECK(modules[8] == std::string_view("Material"));
FESA_CHECK(modules[9] == std::string_view("Property"));
FESA_CHECK(modules[10] == std::string_view("Results"));
FESA_CHECK(modules[11] == std::string_view("Util"));
FESA_CHECK(fesa::umbrellaFacadeHeader() == std::string_view("fesa/fesa.hpp"));
FESA_CHECK(fesa::dofFromAbaqus(1).value() == fesa::Dof::UX);
}
FESA_TEST(parser_accepts_phase1_subset) {
fesa::AbaqusInputParser parser;
auto parsed = parser.parseString(phase1Input());