docs: add shell pressure feature workflow

This commit is contained in:
KOKO\Mimi
2026-09-01 02:34:04 +09:00
parent c54a528709
commit 2d071069b9
17 changed files with 4835 additions and 1 deletions
+216
View File
@@ -0,0 +1,216 @@
# Step 1: map-pressure-input-contract
## 실행 범위와 상태 소유권
이 Step의 단일 책임은 valid assembly-level `*SURFACE, TYPE=ELEMENT`와 sole static Step의 `*DSLOAD P`를 immutable Domain/Step semantic objects와 non-owning `AnalysisModel` view로 mapping하는 것이다. 이 Step 안에서 `RED -> observed expected failure -> minimal GREEN -> focused VERIFY -> full/Stop VERIFY`를 끝내고 green 상태로 종료한다.
Implementation Agent는 Executor가 선택한 이 Step만 수행한다. 성공 시 `phases/shell-surface-pressure-load/index.json`의 Step 1 `status`와 한 줄 `summary`만, 오류/차단 시 각각 `error_message` 또는 `blocked_reason`만 기록할 수 있다. branch, retry, timestamps, commits, 다음 Step 선택, top-level phase status와 `step1-output.json`은 Harness Executor 소유다.
## 읽어야 할 파일
먼저 전부 읽는다.
- `AGENTS.md`
- `docs/PRD.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/CODINGSTYLE.md`
- `docs/HARNESS.md`
- `docs/HARNESS_WORKFLOW.md`
- `.codex/hooks.json`
- `docs/shell-surface-pressure-load/requirements.md`
- `docs/shell-surface-pressure-load/research.md`
- `docs/shell-surface-pressure-load/formulation.md`
- `docs/shell-surface-pressure-load/numerical-review.md`
- `docs/shell-surface-pressure-load/reference-model.md`
- `docs/shell-surface-pressure-load/io.md`
- `docs/shell-surface-pressure-load/implementation-plan.md`
- `include/fesa/io/abaqus/input_syntax.h`
- `include/fesa/io/abaqus/input_reader.h`
- `src/fesa/io/abaqus/input_reader.cpp`
- `src/fesa/io/abaqus/domain_mapping_context.h`
- `src/fesa/io/abaqus/domain_mapping_context.cpp`
- `src/fesa/io/abaqus/topology_mapper.h`
- `src/fesa/io/abaqus/topology_mapper.cpp`
- `src/fesa/io/abaqus/step_definition_mapper.h`
- `src/fesa/io/abaqus/step_definition_mapper.cpp`
- `src/fesa/io/abaqus/domain_builder.h`
- `src/fesa/io/abaqus/domain_builder.cpp`
- `src/fesa/io/abaqus/domain_mapper.cpp`
- `include/fesa/model/model_types.h`
- `include/fesa/model/domain.h`
- `src/fesa/model/domain.cpp`
- `include/fesa/analysis/analysis_model.h`
- `src/fesa/analysis/analysis_model.cpp`
- `tests/unit/io/abaqus/input_reader_test.cpp`
- `tests/unit/io/abaqus/input_syntax_test.cpp`
- `tests/unit/io/abaqus/domain_mapper_test.cpp`
- `tests/unit/io/abaqus/domain_mapping_components_test.cpp`
- `src/fesa/CMakeLists.txt`
- `tests/CMakeLists.txt`
이 Step에는 이전 Step 산출물이 없다. Existing parser/domain behavior를 먼저 이해하고 legacy beam/shell inputs를 보존한다.
## 소유 파일
먼저 test files를 생성/수정한 뒤 production files를 변경한다.
- Modify: `include/fesa/io/abaqus/input_syntax.h`
- Modify: `src/fesa/io/abaqus/input_reader.cpp`
- Modify: `src/fesa/io/abaqus/domain_mapping_context.h`
- Modify: `src/fesa/io/abaqus/domain_mapping_context.cpp`
- Create: `src/fesa/io/abaqus/surface_definition_mapper.h`
- Create: `src/fesa/io/abaqus/surface_definition_mapper.cpp`
- Modify: `src/fesa/io/abaqus/domain_mapper.cpp`
- Modify: `src/fesa/io/abaqus/step_definition_mapper.cpp`
- Modify: `src/fesa/io/abaqus/domain_builder.cpp`
- Modify: `include/fesa/model/model_types.h`
- Modify: `include/fesa/model/domain.h`
- Modify: `src/fesa/model/domain.cpp`
- Modify: `include/fesa/analysis/analysis_model.h`
- Modify: `src/fesa/analysis/analysis_model.cpp`
- Modify/Test: `tests/unit/io/abaqus/input_reader_test.cpp`
- Create/Test: `tests/unit/io/abaqus/shell_surface_pressure_domain_test.cpp`
- Modify: `src/fesa/CMakeLists.txt`
- Modify: `tests/CMakeLists.txt`
`domain_mapper_test.cpp`와 `domain_mapping_components_test.cpp`는 focused regression 대상으로 우선 읽는다. 이 Step의 valid mapping에 직접 필요한 assertion이 새 feature test로 표현되지 않는 경우에만 최소 수정한다.
## 인터페이스와 semantic contract
`include/fesa/model/model_types.h`에 다음 의미의 candidate value types를 구현한다. Existing style상 이름을 최소 조정해야 하면 upstream semantic fields와 아래 accessors를 빠짐없이 보존하고 summary에 조정 이유를 기록한다.
```cpp
enum class ShellSurfaceSide { kSpos, kSneg };
enum class SurfaceMemberKind { kDirect, kElset };
struct ElementSurfaceFacetDefinition {
EntityIndex element_index;
std::size_t facet_ordinal;
std::string part_name_raw;
std::string part_name_canonical;
std::string instance_name_raw;
std::string instance_name_canonical;
std::int64_t source_element_label;
std::string source_element_label_raw;
std::string source_element_type;
ShellSurfaceSide side;
SourceLocation first_member_location;
std::size_t first_member_ordinal;
SurfaceMemberKind member_kind;
std::string elset_name_raw;
std::string elset_name_canonical;
};
struct ElementSurfaceDefinition {
std::string surface_name_raw;
std::string surface_name_canonical;
std::vector<ElementSurfaceFacetDefinition> facets;
SourceLocation declaration_location;
std::size_t declaration_ordinal;
};
struct SurfacePressureLoadDefinition {
std::string step_name_raw;
std::string step_name_canonical;
EntityIndex surface_index;
std::string surface_name_raw;
std::string surface_name_canonical;
std::string load_type;
double magnitude;
std::string magnitude_raw;
SourceLocation keyword_location;
SourceLocation data_location;
std::size_t data_ordinal;
std::size_t load_ordinal;
};
```
Required queries:
```cpp
const std::vector<ElementSurfaceDefinition>&
Domain::ElementSurfaces() const noexcept;
const std::vector<SurfacePressureLoadDefinition>&
StepDefinition::SurfacePressureLoads() const noexcept;
bool StepDefinition::UsesNonlinearGeometry() const noexcept;
const std::vector<SurfacePressureLoadDefinition>&
AnalysisModel::ActiveSurfacePressureLoads() const noexcept;
```
`ModelDefinition` owns `element_surfaces`; `StaticStepDefinition` owns `surface_pressure_loads`; committed `Domain`/`StepDefinition` remain immutable. `AnalysisModel` returns non-owning references and never copies/reorders the surface inventory; Domain must outlive it. Pressure records do not enter the existing configuration-independent nodal `Load::ComputeContributions` interface.
## RED
Write and register these tests before production implementation:
- `InpSyntax.AcceptsAsciiKeywordContinuationAndPreservesPhysicalSourceLines`
- `ShellSurfacePressureInput.MapsDirectInstanceFacetsForS4AndS4rCaseInsensitively`
- `ShellSurfacePressureInput.MapsExplicitInstanceElsetAndResultNeutralInternalParameter`
- `ShellSurfacePressureInput.MapsMixedDirectAndElsetMembersAcrossTwoExplicitInstancesWithStableDataMemberAndElsetOrder`
- `ShellSurfacePressureInput.PreservesSposSnegMagnitudeTextLocationsAndSourceOrder`
- `ShellSurfacePressureDomain.OwnsCanonicalFacetsAndStepOwnedAdditivePressureRecords`
- `ShellSurfacePressureDomain.AnalysisModelBorrowsActivePressureWithoutCopyingDomain`
- `ShellSurfacePressureInput.AcceptsWhitespaceSignedZeroAndFiniteScientificNotation`
The mixed-instance fixture declares `Instance-A` and `Instance-B` in distinct declaration order, interleaves differently cased direct members and flat assembly ELSET members bound by explicit `INSTANCE=`, and uses the same numeric element label in both instances. It must compare case-insensitive resolution, raw data/member ordinals, flat ELSET provenance, canonical facet order, distinct part/instance/source label/source type/side identities and first-member provenance exactly. It must not accept implicit-instance syntax.
After test edits and CMake test registration, run:
```powershell
cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=C:/git/googletest" `
"-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" `
"-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" `
"-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake"
cmake --build .harness/build --config Debug --target fesa_unit_tests
ctest --test-dir .harness/build -C Debug --output-on-failure -R "^(InpSyntax|ShellSurfacePressureInput|ShellSurfacePressureDomain)\."
```
Expected RED: missing mapper/header/semantic accessors produces compile/link failure, or current unsupported `SURFACE`/`DSLOAD` behavior fails assertions. The mixed-instance fixture must fail because the two explicit instances/mixed direct+ELSET are not resolved or committed identity/provenance is absent. Record command, exit code, duration and meaningful output tail. An unrelated existing failure is `regression`; an unexpected pass is an `evidence-gap`. Stop before production changes until the expected RED is observed.
## Minimal GREEN
- Support physical-line ASCII/256-byte policy, comma/cardinality, physical locations and keyword-parameter-only continuation exactly as `io.md` §3 defines. Do not invent inline comments or data continuation.
- Parse assembly-only element surfaces and parameterless step-level DSLOAD. Surface parameters are exactly `TYPE=ELEMENT` and `NAME`; DSLOAD data is exactly `<surface>,P,<finite C-locale scalar>`.
- Run `SurfaceDefinitionMapper` after topology finalization and before Step binding. Resolve direct `<instance>.<positive label>` and flat assembly ELSETs with explicit `INSTANCE=` case-insensitively.
- One surface may mix direct/ELSET members and multiple explicit instances. Preserve raw data/member order and ELSET expansion provenance, then sort unique committed facets by `(instance declaration ordinal, numeric element label, SPOS before SNEG)`.
- Preserve each facet's internal `element_index` plus part/instance raw+canonical identity, source label/raw token, exact `S4|S4R`, side, facet ordinal and first-member provenance.
- Preserve each Step pressure record's step/surface raw+canonical identity, `load_type="P"`, signed magnitude/raw token, keyword/data locations, data ordinal and total Step load ordinal. Records remain distinct/additive.
- Bind pressure surface references only after every candidate target validates. DomainBuilder commits once. Legacy `StaticStepDefinition` constructors delegate with an empty pressure vector.
## VERIFY and Acceptance Criteria
If `.harness/config.json` exists at execution time, its complete configure/build/test selection takes precedence and the exact resolved commands must be recorded. Otherwise execute:
```powershell
cmake --build .harness/build --config Debug --target fesa_unit_tests
ctest --test-dir .harness/build -C Debug --output-on-failure -R "^(InpSyntax|ShellSurfacePressureInput|ShellSurfacePressureDomain)\."
ctest --test-dir .harness/build -C Debug --output-on-failure -R "^(InpDomainMapping|DomainMappingComponents|InpSyntax)\."
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Acceptance requires exit `0`, nonzero discovered tests, all named tests present/pass, no new MSVC `/W4 /WX` warnings, and all legacy tests green. The automatic Stop hook performs another whole-project MSVC validation; do not call hook scripts manually.
## 불변식, 실패 처리와 증거
- Supported: mixed direct/ELSET and multiple explicit instances in one surface. Unsupported: implicit-instance ELSET, one ELSET mixing instances, part-scope fallback.
- Same numeric label in different instances is never merged. Source identity is not replaced by internal/equation index.
- Parse/map failure returns no Domain and exposes no partial surface/load. Do not update AnalysisState or HDF5.
- Evidence must record RED/GREEN/VERIFY commands, exits, durations/tails, mapped facet/load inventory, source identity/order, warnings and changed files.
- Failure classification: `configure | compile | link | test | harness | environment | upstream-contract | regression | evidence-gap`.
Trace: `FESA-REQ-SHELL-PRESSURE-001`–`004`, `010`, `013`; `io.md` §§2–6; `formulation.md` §3.
## 금지사항
- Do not implement pressure force/tangent or procedure assembly. 이유: Steps 3–5 ownership이다.
- Do not support `*DLOAD`, implicit-instance ELSET, part surface, generalized distributed loads or additional element types. 이유: approved subset 밖이다.
- Do not change HDF5 schema, CLI output contract, upstream docs, tolerance or reference artifacts.
- Do not run Abaqus/reference solvers, create output JSON, invoke `scripts/execute.py`, select Step 2, commit or push.