diff --git a/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md b/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md new file mode 100644 index 0000000..422c765 --- /dev/null +++ b/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md @@ -0,0 +1,527 @@ +# Linear Static 3D Euler Beam End-to-End Design + +## Metadata + +- feature_id: `linear-static-3d-euler-beam` +- phase_name: `linear-static-3d-euler-beam` +- status: `approved` +- approved_by: user +- approved_on: `2026-08-08` +- source_formulation: `docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- implementation_environment: C++17, MSVC, CMake, CTest, GoogleTest, Intel oneMKL, Intel oneTBB, HDF5 + +## 1. 목적 + +이 설계는 Abaqus `.inp` keyword subset을 읽어 2절점 3차원 +Euler–Bernoulli beam의 단일 선형 정적 step을 해석하고, 변위·반력·요소 내력·축응력을 +authoritative HDF5 파일 `results.h5`에 기록하는 FESA V0 파이프라인을 정의한다. + +런타임 순서는 다음과 같이 고정한다. + +```text +.inp 입력 +-> Domain 생성 +-> 현재 step의 AnalysisModel 생성 +-> DofManager 및 sparse pattern 생성 +-> 요소강성 계산과 전역강성 조립 +-> free/constrained partition +-> MKL PARDISO factorization +-> 전체 하중벡터 조립과 effective RHS 생성 +-> PARDISO substitution +-> 전체 변위벡터 복구 +-> 반력·요소 내력·요소 축응력 복구 +-> results.h5 기록 +-> 정상 종료 +``` + +## 2. 범위 + +### 2.1 포함 범위 + +- 입력 파일당 하나의 `*STEP, *STATIC` +- small displacement, small rotation, 선형 탄성 해석 +- 2절점 직선 3D Euler–Bernoulli beam +- 절점당 자유도 `[UX, UY, UZ, URX, URY, URZ]` +- 축, 두 방향 굽힘, Saint-Venant 비틀림 +- nodal concentrated load와 prescribed displacement +- nonzero prescribed displacement를 포함한 자유/구속 partition +- deterministic COO-to-CSR sparse assembly +- MKL PARDISO factorization과 substitution의 분리 +- oneTBB 기반 element-local 계산 +- 변위, 반력, equilibrium end action, section resultant, axial `S11` 출력 +- Abaqus B33 변위·반력·section resultant reference comparison + +### 2.2 제외 범위 + +- Abaqus full compatibility +- Abaqus B31/Timoshenko beam +- 다중 analysis step과 step 간 load/BC propagation +- instance translation/rotation, nested assembly, dependent/independent mesh 차이 +- `I12 != 0`, taper, offset, release, curved beam, warping +- distributed load용 Abaqus `*DLOAD` 입력 +- 기하·재료비선형, dynamics, contact, thermal effects +- transverse shear stress와 torsional shear stress recovery +- beam stress에 대한 Abaqus reference comparison +- reference artifact의 자동 생성, 수정 또는 Abaqus 실행 + +## 3. Phase 구성 + +단일 Harness task `linear-static-3d-euler-beam`은 다음 29개 step으로 구성한다. +각 step은 하나의 gate 또는 하나의 C++ 모듈만 소유한다. + +### 3.1 문서 및 계약 gate + +| Step | Name | Primary output | +| ---: | --- | --- | +| 0 | `requirements-baseline` | `docs/requirements/linear-static-3d-euler-beam.md` | +| 1 | `research-evidence` | `docs/research/linear-static-3d-euler-beam-research.md` | +| 2 | `formulation-alignment` | 승인 범위와 정렬된 기존 beam formulation | +| 3 | `numerical-review` | `docs/numerical-reviews/linear-static-3d-euler-beam-review.md` | +| 4 | `io-contract` | `docs/io-definitions/linear-static-3d-euler-beam-io.md` | +| 5 | `reference-model-contract` | `docs/reference-models/linear-static-3d-euler-beam-reference-models.md` | +| 6 | `implementation-plan` | `docs/implementation-plans/linear-static-3d-euler-beam.md` | + +### 3.2 C++ TDD 구현 + +| Step | Name | Module responsibility | +| ---: | --- | --- | +| 7 | `cmake-test-foundation` | CMake, GoogleTest, CTest, dependency discovery | +| 8 | `core-diagnostics` | IDs, source locations, diagnostics, status | +| 9 | `dense-math-adapters` | MKL BLAS `Matrix` and `Vector` | +| 10 | `domain-model` | Immutable model definitions and source identities | +| 11 | `inp-syntax-parser` | Keyword/data/comment lexical and syntax parsing | +| 12 | `inp-domain-mapping` | Part/Assembly/Instance semantic mapping | +| 13 | `analysis-model` | Active single-step views into Domain | +| 14 | `dof-manager` | DOFs, constraints, numbering, sparse pattern | +| 15 | `analysis-state` | Displacement, forces, residual, step/frame state | +| 16 | `euler-beam-element` | B33 element stiffness, transformation, load/recovery kernels | +| 17 | `parallel-for-tbb` | oneTBB adapter for deterministic element-local work | +| 18 | `sparse-assembly` | COO contribution collection and CSR finalization | +| 19 | `essential-constraints` | Matrix partition and full/reduced vector mapping | +| 20 | `mkl-pardiso-solver` | PARDISO adapter, factorization, substitution, diagnostics | +| 21 | `load-assembly` | Nodal load vector and prescribed-displacement RHS | +| 22 | `result-recovery` | Reactions, end actions, resultants, axial stress | +| 23 | `hdf5-results-writer` | Versioned HDF5 schema and atomic finalization | +| 24 | `linear-static-cli` | Analysis orchestration and `fesa.exe` entry point | + +### 3.3 최종 gate + +| Step | Name | Primary output | +| ---: | --- | --- | +| 25 | `build-test-verification` | `docs/build-test-reports/linear-static-3d-euler-beam.md` | +| 26 | `reference-verification` | `docs/reference-verifications/linear-static-3d-euler-beam-reference-verification.md` | +| 27 | `physics-sanity` | `docs/physics-evaluations/linear-static-3d-euler-beam-physics-evaluation.md` | +| 28 | `release-readiness` | `docs/releases/linear-static-3d-euler-beam-release.md` | + +## 4. 아키텍처와 소유권 + +### 4.1 Domain 계층 + +`Domain`은 parser가 만든 전체 모델을 소유하며 parsing 이후 가능한 한 불변으로 +취급한다. 최소 semantic object는 다음과 같다. + +- `Node` +- `EulerBeam3DDefinition` +- `LinearElasticMaterial` +- `GeneralBeamSection` +- `NodeSet`, `ElementSet` +- `BoundaryCondition`, `NodalLoad` +- `StaticStepDefinition` + +Part 내부 source label은 변경하지 않는다. 외부 identity는 +`SourceEntityId { instance_name, source_label }`로 유지하고, Domain은 별도의 stable +internal index를 부여한다. 같은 part의 여러 identity instance는 허용하지만 instance +transform data가 있으면 입력 오류로 처리한다. + +### 4.2 AnalysisModel + +`AnalysisModel`은 단일 static step에 활성화된 element, load, boundary condition, +material, section의 ID/reference view를 제공한다. Domain 객체를 복사하거나 수정하지 +않는다. 두 번째 `*STEP`은 V0 unsupported diagnostic을 발생시킨다. + +### 4.3 DofManager + +`DofManager`만 다음 정보를 소유한다. + +- node별 6개 DOF 정의 +- full DOF index +- constrained/free mapping +- free equation numbering +- element scatter map +- sparse matrix pattern +- full/reduced vector reconstruction + +Node와 Element에는 equation ID를 저장하지 않는다. + +### 4.4 AnalysisState + +`AnalysisState`는 다음 해석 중 상태를 소유한다. + +- full displacement +- external force +- internal force +- residual +- constrained reaction +- current step/frame identity +- element recovery rows + +V0에서는 velocity, acceleration, temperature, iteration history를 할당하지 않는다. + +### 4.5 요소 계약 + +`EulerBeam3D`는 +`docs/formulations/3d-isoparametric-euler-beam-formulation.md`의 부호, DOF 순서, +2점 Gauss rule, transformation을 따른다. 구현 API는 다음 책임을 분리한다. + +```cpp +Matrix localStiffness() const; +Matrix globalStiffness() const; +Vector localEquivalentLoad() const; +BeamRecovery recover(const Vector& globalElementDisplacement) const; +``` + +요소는 equation ID를 소유하지 않는다. `BeamRecovery`는 endpoint equilibrium end +action, endpoint section resultant, Gauss-point generalized strain/resultant, section-point +`S11`을 구분한다. + +### 4.6 LinearSolver 계약 + +Solver core에는 MKL 타입을 노출하지 않는다. + +```cpp +class LinearSolver { +public: + virtual ~LinearSolver() = default; + virtual Status factorize(const SparseMatrix& matrix) = 0; + virtual Status solve(const Vector& rhs, Vector& solution) const = 0; +}; +``` + +`MklPardisoSolver`는 factorization 상태를 소유하고 같은 matrix에 여러 RHS +substitution을 수행할 수 있다. singularity와 invalid CSR은 구조화된 diagnostic으로 +반환한다. + +## 5. Matrix, Vector 및 SparseMatrix + +### 5.1 Vector + +`Vector`는 연속된 `double` 데이터와 크기를 소유한다. copy/move semantics와 +bounds-checked access를 제공한다. 다음 연산은 MKL CBLAS를 사용한다. + +- copy +- `dot` +- Euclidean norm +- `scale` +- `axpy` + +### 5.2 Matrix + +`Matrix`는 연속된 row-major `double` 데이터, row count, column count를 소유한다. +copy/move semantics와 bounds-checked access를 제공한다. matrix-vector와 +matrix-matrix 연산은 `CBLAS_ROW_MAJOR`의 MKL CBLAS를 사용한다. beam의 3x3, 4x12, +12x12 dense 연산도 이 타입을 사용한다. + +MKL header와 MKL-specific type은 `.cpp` adapter 경계 밖으로 노출하지 않는다. + +### 5.3 SparseMatrix + +`SparseMatrix`는 CSR 전용 별도 타입이며 `Matrix`를 상속하지 않는다. CSR row pointer, +column index, values를 소유하고 0-based indexing을 사용한다. PARDISO adapter가 +필요한 indexing과 descriptor 변환은 adapter 내부에서 수행한다. + +## 6. 입력 계약 + +### 6.1 지원 keyword + +- `*HEADING` +- `*PART`, `*END PART` +- `*NODE` +- `*ELEMENT, TYPE=B33` +- `*NSET`, `*ELSET`, including `GENERATE` +- `*MATERIAL`, `*ELASTIC` +- `*BEAM GENERAL SECTION, SECTION=GENERAL` +- `*SECTION POINTS` +- `*ASSEMBLY`, `*END ASSEMBLY` +- `*INSTANCE`, `*END INSTANCE` +- `*BOUNDARY` +- `*CLOAD` +- `*STEP`, `*STATIC`, `*END STEP` + +Keyword와 parameter는 case-insensitive이고 label identity는 원문 값을 보존한다. +Comment line은 `**`로 시작한다. + +### 6.2 General beam section mapping + +`*BEAM GENERAL SECTION, SECTION=GENERAL`의 data는 +`A, I11, I12, I22, J` 순서로 읽는다. + +- `I12`는 0이어야 한다. +- Abaqus first beam section axis `n1`을 FESA local `y`로 둔다. +- `t x n1`을 FESA local `z`로 둔다. +- `Iy = I11`, `Iz = I22`로 매핑한다. +- `E`와 Poisson ratio `nu`로 `G = E / (2(1 + nu))`를 계산한다. +- `E`, `G`, `A`, `Iy`, `Iz`, `J`는 양수여야 한다. +- beam length와 projected guide-vector norm은 승인된 tolerance보다 커야 한다. + +이 축 계약은 Abaqus의 right-handed `(t, n1, n2)` section system 및 현재 formulation의 +`(x, y, z)` system과 일치한다. + +### 6.3 B33 의미 보존 + +Abaqus B31은 transverse shear deformation을 포함하는 Timoshenko beam이고 B33은 +2절점 cubic Euler–Bernoulli beam이다. FESA V0는 `TYPE=B33`만 Euler 요소로 매핑한다. +`TYPE=B31`은 `unsupported-element-formulation` 오류로 거부한다. 기존 B31 reference +결과를 tolerance 확대로 Euler reference인 것처럼 사용하지 않는다. + +이 결정은 [[Abaqus Structural Element Families]], [[Beam and Frame Finite Elements]], +[[Abaqus-Analysis-User-s-Guide-Volume-IV|Abaqus Analysis User's Guide Volume IV]]의 +beam-family 구분을 따른다. + +### 6.4 Instance 제한 + +- 같은 part의 여러 identity instance를 허용한다. +- instance name과 source node/element/set label을 보존한다. +- source identity를 stable Domain index로 deterministic하게 매핑한다. +- translation 또는 rotation data가 있으면 `unsupported-instance-transform` 오류를 낸다. +- nested assembly와 dependent/independent mesh semantics는 지원하지 않는다. + +### 6.5 No-op allowlist + +다음 keyword와 관련 data line은 구조화된 warning을 기록하고 해석에서는 사용하지 +않는다. + +- `*PREPRINT` +- `*RESTART` +- `*TRANSVERSE SHEAR STIFFNESS` +- `*OUTPUT, FIELD` +- `*OUTPUT, HISTORY` +- `*NODE OUTPUT` +- `*ELEMENT OUTPUT` +- `*CONTACT OUTPUT` +- 위 output request에 속한 미지원 variable data + +이 allowlist 밖의 미지원 keyword는 오류다. FESA의 기본 출력은 Abaqus output request와 +무관하게 항상 생성된다. + +## 7. 선형 정적 알고리즘 + +1. `AbaqusInputReader`가 syntax model과 source location을 만든다. +2. semantic mapper가 immutable `Domain`을 만든다. +3. `AnalysisModel`이 단일 static step의 active view를 만든다. +4. `DofManager`가 DOF, constraints, scatter map, sparse pattern을 만든다. +5. `ParallelFor`가 element-local global stiffness를 계산한다. +6. element internal index 순서로 COO contribution을 deterministic하게 reduce하고 CSR로 + finalize한다. +7. free/constrained partition으로 `Kff`, `Kfc`, `Kcf`, `Kcc`를 만든다. +8. `MklPardisoSolver::factorize(Kff)`를 호출한다. +9. nodal load를 full `F`에 조립한다. +10. `rhs = Ff - Kfc * dc`를 만든다. +11. `solve(rhs, df)`로 substitution하고 full `d`를 복구한다. +12. `Rc = Kcf * df + Kcc * dc - Fc`로 reaction을 복구한다. +13. element displacement를 gather하여 end action, section resultant, strain, `S11`을 + 복구한다. +14. `ResultsWriter`가 임시 HDF5 파일을 완성한 뒤 최종 `results.h5`로 교체한다. + +반력은 요소 끝력의 별도 합산 경로가 아니라 전체 조립 residual `K*d-F`에서 구한다. + +## 8. 결과 복구 + +### 8.1 변위와 반력 + +모든 node에 전역 성분 `[UX, UY, UZ, URX, URY, URZ]`를 기록한다. 반력은 동일한 +6성분 순서로 기록하고 free DOF의 값은 수치 residual 검사에 사용한다. + +### 8.2 요소 내력 + +다음 데이터를 서로 다른 dataset으로 유지한다. + +- equilibrium end action: `Kl*dl-fl_dist`, local `[FX,FY,FZ,MX,MY,MZ]` +- section resultant: endpoint `xi=-1,+1`의 `[N,T,My,Mz]` +- generalized strain/resultant: 두 Gauss point의 formulation 값 + +Abaqus internal-force CSV는 equilibrium end action이 아니라 section resultant와 +비교한다. component mapping은 다음과 같다. + +| Abaqus | FESA local component | +| --- | --- | +| `SF1` | `FX` / `N` | +| `SF3` | `FY` | +| `SF2` | `FZ` | +| `SM3` | `MX` / `T` | +| `SM1` | `MY` | +| `SM2` | `MZ` | + +### 8.3 Axial stress + +General beam section은 section point에서 axial stress만 복구한다. + +```text +S11 = E * (epsilon0 + x2*kappa1 - x1*kappa2) +``` + +FESA 좌표로는 `x1=y`, `x2=z`, `kappa1=kappa_y`, `kappa2=kappa_z`다. +`*SECTION POINTS`가 있으면 지정 순서대로 출력한다. 없으면 FESA-specific centroid +point `(0,0)`을 만들고 `source=fesa-default`로 기록한다. Stress는 두 Gauss point에서 +평가한다. Transverse shear stress와 torsional shear stress는 출력하지 않는다. + +이 계약은 [[Abaqus Beam and Shell Section Definitions]]과 +[[Abaqus-Analysis-User-s-Guide-Volume-IV|Abaqus Analysis User's Guide Volume IV]]의 +general beam section output 제한을 따른다. + +## 9. HDF5 schema v0 + +Authoritative output은 `results.h5` 하나다. 최소 schema는 다음과 같다. + +```text +/metadata +/model/nodes +/model/elements +/steps//frames/0/nodal/displacement +/steps//frames/0/nodal/reaction +/steps//frames/0/element/end_force_local +/steps//frames/0/element/section_resultant +/steps//frames/0/element/generalized_strain +/steps//frames/0/element/stress_s11 +/diagnostics +``` + +`/metadata`에는 schema version, solver version, source input identity, unit-system label, +coordinate convention, element formulation을 기록한다. Node/element group은 stable internal +ID와 instance/source label mapping을 함께 저장한다. + +- displacement: `[node_count, 6]` +- reaction: `[node_count, 6]` +- end force: `[element_count, 2, 6]` +- section resultant: `[element_count, 2, 4]`, `xi={-1,+1}` +- generalized strain: `[element_count, 2, 4]`, two Gauss points +- stress: flat row identity with element, Gauss point, section point, `(x1,x2)`, `S11` + +HDF5 API는 `Hdf5ResultsWriter` implementation 밖으로 노출하지 않는다. Writer failure 시 +불완전한 최종 `results.h5`를 남기지 않는다. + +## 10. CLI와 diagnostics + +```powershell +fesa.exe --output +``` + +`--output`을 생략하면 현재 작업 디렉터리에 `results.h5`를 생성한다. + +| Exit code | Meaning | +| ---: | --- | +| 0 | success | +| 2 | CLI usage error | +| 3 | input syntax or semantic mapping error | +| 4 | model validation error | +| 5 | factorization or substitution error | +| 6 | HDF5 output error | + +각 diagnostic은 `severity`, `code`, `file`, `line`, `keyword`, `entity_identity`, +`message`를 가진다. CLI는 오류 diagnostic을 stderr에 deterministic한 순서로 출력한다. + +## 11. TDD와 검증 + +### 11.1 C++ step 규칙 + +각 production C++ step은 다음 순서를 같은 step 안에서 증명한다. + +1. GoogleTest 작성 +2. 관련 test target 실행과 요구사항을 재현하는 RED 실패 확인 +3. 최소 production 구현 +4. 관련 CTest GREEN 확인 +5. 전체 MSVC x64 Debug build와 CTest VERIFY + +새 경고를 허용하지 않으며 FESA target에만 MSVC `/W4 /WX`를 적용한다. Third-party +GoogleTest target에는 FESA warning policy를 강제하지 않는다. + +### 11.2 테스트 포트폴리오 + +- Matrix/Vector ownership, bounds, dimension mismatch, BLAS result checks +- parser case-insensitivity, comments, set generation, wrapper nesting, allowlist diagnostics +- B31 rejection, B33 acceptance, instance transform rejection, unknown keyword rejection +- Domain duplicate label와 dangling reference validation +- AnalysisModel active view와 Domain non-copy/non-mutation 검사 +- DofManager numbering, constraints, scatter map, full/reduced reconstruction +- Hermite interpolation, B matrix, 2-point Gauss vs closed-form stiffness +- symmetry, rank 6, six rigid modes, positive deformation energy +- local/global transform orthogonality와 energy invariance +- deterministic parallel COO reduction과 CSR structure +- nonzero prescribed displacement와 reaction recovery +- PARDISO factorization/substitution 분리, repeated RHS, singular diagnostic +- axial, torsion, y/z bending cantilever analytical cases +- HDF5 schema, identity, component, metadata, atomic finalization +- CLI `.inp -> results.h5` integration + +### 11.3 수치 tolerance + +| Check | Criterion | +| --- | --- | +| matrix symmetry and Gauss/closed-form comparison | normalized `1e-12` | +| rigid-mode and linear-system residual | normalized `1e-10` | +| analytical solution tests | relative `1e-9` | +| Abaqus B33 reference comparison | relative `1e-6` | +| SI displacement and rotation absolute floor | `1e-9` | +| SI force and moment absolute floor | `1e-3` | + +Reference row 판정은 `abs_error <= abs_tol OR rel_error <= rel_tol`을 사용한다. +Reference metadata가 SI가 아니면 quantity별 absolute tolerance를 동일 차원으로 변환해야 +하며 변환 근거를 verification report에 기록한다. + +### 11.4 공통 build/test command + +GoogleTest checkout은 `C:/git/googletest`에 있고 승인 당시 revision은 +`04ee1b4f2aefdffb0135d7cf2a2c519fe50dabe4`다. 절대경로를 production CMake에 +하드코딩하지 않고 cache variable로 전달한다. + +```powershell +cmake -S . -B .harness/build -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 +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +CTest discovery 결과는 한 개 이상의 test를 포함해야 한다. + +## 12. Reference 및 release gate + +기존 `reference/cantilever beam/` bundle은 Abaqus B31 결과이므로 수정하지 않고 V0 +Euler verification에 사용하지 않는다. Reference Model Contract는 사람이 Abaqus에서 +생성할 B33 bundle의 다음 artifact를 요구한다. + +- `model.inp` using `TYPE=B33` +- `metadata.json` with Abaqus version, units, coordinate system, provenance, tolerances +- `_displacements.csv` +- `_reactions.csv` +- `_internalforces.csv` +- `README.md` +- stress CSV: explicitly `not-applicable` for this feature + +Agent와 Harness는 Abaqus를 실행하거나 reference artifact를 생성·수정하지 않는다. +B33 artifact가 없으면 reference-verification step은 `blocked`로 끝나며 사용자가 bundle을 +준비한 후 해당 step을 `pending`으로 되돌려 재개한다. + +Reference comparison이 pass한 뒤에만 physics sanity를 수행한다. Physics sanity는 +global force/moment equilibrium, reaction sign, displacement direction, symmetry, element +section-force consistency, normalized residual을 검사한다. Release readiness는 모든 이전 +gate evidence와 known limitations를 확인한다. + +## 13. 완료 조건 + +다음 조건을 모두 만족해야 phase를 완료할 수 있다. + +1. 요구조건, 연구, 정식화, 수치 검토, I/O, reference model, 구현 계획 문서가 승인 + 상태다. +2. 모든 production C++ 변경에 대응 테스트와 RED/GREEN/VERIFY evidence가 있다. +3. MSVC x64 Debug configure, build, CTest discovery, 전체 CTest가 성공한다. +4. `fesa.exe`가 승인된 B33 single-step input에서 `results.h5`를 생성한다. +5. HDF5 변위·반력·내력 rows가 Abaqus B33 reference CSV와 tolerance 안에서 일치한다. +6. Beam stress reference comparison은 명시적 N/A이고 stress output schema/test는 + 통과한다. +7. Physics sanity가 pass한다. +8. Release report에 지원 subset과 모든 V0 제한사항이 기록된다. +